kratos icon indicating copy to clipboard operation
kratos copied to clipboard

Microsoft Graph not returning `userPrincipalName`

Open mooijtech opened this issue 2 years ago • 2 comments

Preflight checklist

Describe the bug

Using subject_source: me for Microsoft OIDC using the User.Read scope does not return information such as userPrincipalName, see https://github.com/ory/kratos/blob/master/selfservice/strategy/oidc/provider_microsoft.go#L109

Reproducing the bug

N/A

Relevant log output

No response

Relevant configuration

No response

Version

v1.0.0

On which operating system are you observing this issue?

Linux

In which environment are you deploying?

Binary

Additional Context

I would like to get the email of the user from userPrincipalName.

mooijtech avatar Jul 31 '23 15:07 mooijtech

References https://github.com/ory/kratos/pull/3411

mooijtech avatar Aug 01 '23 17:08 mooijtech

I cannot get the mapper to pass the value to the frontend, it's returning the browser flow after OIDC instead of flow containing the requested information.

This is my kratos.yml:

version: v1.0.0

# ./kratos -c kratos.yml migrate sql -e --yes
dsn: sqlite:///tmp/example.sqlite?_fk=true

serve:
  public:
    base_url: https://auth.example.com/
    cors:
      enabled: true
      debug: true

      allow_credentials: true
      allowed_origins:
        - "https://auth-admin.example.com/"
        - "https://auth.example.com/"
        - "https://example.com/"
        # Just in case
        - "https://microsoftonline.com/"
        - "https://login.microsoftonline.com/"
        # Desktop
        - "wails://wails.localhost:34115"
      allowed_methods:
        - POST
        - GET
        - PUT
        - PATCH
        - OPTIONS
        - DELETE
      allowed_headers:
        - Authorization
        - Content-Type
        - X-CSRF-Token
        - Cookie
        - Set-Cookie
        - X-Requested-With
        - X-Session-Token
        - Accept
        - Accept-Version
        - Content-Length
        - Content-MD5
        - Content-Type
        - Date
        - X-Api-Version
        - X-Kratos-Authenticated-Identity-Id
      exposed_headers:
        - Authorization
        - Content-Type
        - X-CSRF-Token
        - Cookie
        - Set-Cookie
        - X-Requested-With
        - Accept
        - Accept-Version
        - Content-Length
        - Content-MD5
        - Content-Type
        - Date
        - X-Api-Version
        - X-Kratos-Authenticated-Identity-Id
  admin:
    base_url: https://auth-admin.example.com/

cookies:
  same_site: Lax

selfservice:
  default_browser_return_url: https://example.com/register
  allowed_return_urls:
    - https://example.com

  methods:
    profile:
      enabled: true
    link:
      enabled: true
    password:
      enabled: true
    oidc:
      enabled: true
      config:
        providers:
          - id: microsoft
            provider: microsoft
            mapper_url: file:///home/whatever/microsoft-mapper.jsonnet
            client_id: MY_CLIENT_ID
            client_secret: MY_CLIENT_SECRET
            subject_source: userinfo
            scope:
              - openid
              - profile
              - email
            microsoft_tenant: common
            requested_claims:
              id_token:
                preferred_username:
                  essential: true

  flows:
    error:
      ui_url: https://example.com/error

    settings:
      ui_url: https://example.com/settings
      privileged_session_max_age: 15m

    recovery:
      enabled: true
      ui_url: https://example.com/password-reset
      after:
        hooks:
          - hook: revoke_active_sessions

    verification:
      enabled: true
      ui_url: https://example.com/verification
      after:
        default_browser_return_url: wails://wails.localhost:34115/projects

    logout:
      after:
        default_browser_return_url: https://example.com/login

    login:
      ui_url: https://example.com/login
      lifespan: 10m

    registration:
      ui_url: https://example.com/register
      after:
        password:
          default_browser_return_url: https://example.com/register
          hooks:
            - hook: session
        oidc:
          default_browser_return_url: https://example.com/register
          hooks:
            - hook: session

log:
  level: trace
  format: text
  leak_sensitive_values: true

secrets:
  cookie:
    - PLEASE-CHANGE-ME-I-AM-VERY-INSECURE
  cipher:
    - 32-LONG-SECRET-NOT-SECURE-AT-ALL

ciphers:
  algorithm: xchacha20-poly1305

hashers:
  algorithm: bcrypt
  bcrypt:
    cost: 12

identity:
  default_schema_id: default
  schemas:
    - id: default
      url: file:///home/whatever/user-identity-schema.json

courier:
  smtp:
    from_name: Example
    from_address: [email protected]
    connection_uri: MY_CONNECTION_URI

I am running Caddy locally for HTTPS and I have the domains mapped in /etc/hosts:

127.0.0.1 example.com
127.0.0.1 auth.example.com
127.0.0.1 auth-admin.example.com
auth.example.com:443 {
        reverse_proxy localhost:4433
        tls internal
}

example.com:443 {
        reverse_proxy localhost:3000
        tls internal
}

auth-admin.example.com:443 {
        reverse_proxy localhost:4434
        tls internal
}

api.example.com:443 {
        reverse_proxy localhost:3003
        tls internal
}

This is my user-identity-schema.json:


{
  "$id": "default",
  "title": "User",
  "type": "object",
  "properties": {
    "traits": {
      "type": "object",
      "properties": {
        "email": {
          "title": "Email",
          "type": "string",
          "format": "email",
          "ory.sh/kratos": {
            "credentials": {
              "password": {
                "identifier": true
              }
            },
            "recovery": {
              "via": "email"
            }
          }
        }
      },
      "required": [
        "email"
      ],
      "additionalProperties": false
    }
  }
}

This is my microsoft-mapper.jsonnet:

local claims = std.extVar('claims');
{
  identity: {
    traits: {
      email: claims.preferred_username,
    },
  },
}

I cannot receive the value preferred_username. I can do email: claims and I can see the value does show up but I cannot receive it because as soon as I change to this configuration the JavaScript (NextJS) returns the browser flow instead of flow containing no information.

mooijtech avatar Aug 02 '23 10:08 mooijtech