network icon indicating copy to clipboard operation
network copied to clipboard

Traits from the Update Registration API Flow payload with OIDC get lost

Open openscript opened this issue 1 year ago • 7 comments

Preflight checklist

Describe the bug

When a user registers via the self-service registration flow with OIDC and traits are provided, the user will be created, but the traits are missing.

image

Reproducing the bug

Steps to reproduce the behavior:

  1. Have a identity schema which has additional traits. (example below)
  2. Initialize registration flow:
    curl --request GET \
      --url 'https://example.com/.ory/kratos/public/self-service/registration/api?return_session_token_exchange_code=true&return_to=example%3A%2F%2Fregistration
    
  3. Submit registration flow:
    curl --request POST \
      --url 'https://example.com/.ory/kratos/public/self-service/login?flow=dac5c20f-20ba-4357-8163-edb2e60a5216' \
      --header 'content-type: application/json' \
      --data '{
      "method": "oidc",
      "provider": "google",
      "traits": {
        "lang": "de-CH",
        "tac": "1234",
        "dp": "4321"
      }
    }'
    
  4. Kratos redirects you to the OIDC provider. Open the provided link inside a browser.
  5. Authenticate successfully with an account
  6. Check via admin api if the new identity contains the traits

Relevant log output

No response

Relevant configuration

My identity schema looks like this:


{
  "$id": "https://example.com/identity.schema.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Customer",
  "type": "object",
  "properties": {
    "traits": {
      "type": "object",
      "properties": {
        "lang": {
          "type": "string",
          "title": "Language"
        },
        "tac": {
          "type": "string",
          "title": "Terms and Conditions"
        },
        "dp": {
          "type": "string",
          "title": "Data Protection"
        },
        "email": {
          "type": "string",
          "format": "email",
          "title": "Email",
          "minLength": 3,
          "ory.sh/kratos": {
            "credentials": {
              "password": {
                "identifier": true
              }
            },
            "verification": {
              "via": "email"
            },
            "recovery": {
              "via": "email"
            }
          }
        }
      },
      "required": [
        "email"
      ],
      "additionalProperties": false
    }
  }
}

Version

1.0.0

On which operating system are you observing this issue?

Linux

In which environment are you deploying?

Docker Compose

Additional Context

This topic was discussed here too: https://github.com/ory/kratos/discussions/3413

It worked with 0.12 for many months, but it doesn't with version 1.0.0. We directly migrated from 0.12 to 1.0.0.

openscript avatar Aug 07 '23 09:08 openscript

This should work as you have documented (which is also why it worked in 0.12). Looks like this is a regression - but it could have many reasons. Is there some way for you to pin-point why it isn't working or provide a reproducable case with e.g. your website? Thanks!

aeneasr avatar Aug 07 '23 10:08 aeneasr

Thank you @aeneasr for your quick reaction.

I've reproduced the issue on Orys Network: https://silly-easley-16pa1lzvl4.projects.oryapis.com (UI)

If you need to look into the private instance details or modify the instance, go for it. I've created it just for this issue. The reproduction steps with this instance are:

  1. Initialize registration API flow:
    curl --request GET \
      --url 'https://silly-easley-16pa1lzvl4.projects.oryapis.com/self-service/registration/api?return_session_token_exchange_code=true&return_to=http%3A%2F%2Fopenscript.ch%2Fregistration'
    
  2. Update registration API flow:
    curl --request POST \
      --url 'https://silly-easley-16pa1lzvl4.projects.oryapis.com/self-service/registration?flow=08d22e2b-900b-476d-9931-a7f6877999dc' \
      --header 'content-type: application/json' \
      --data '{
      "method": "oidc",
      "provider": "google",
      "traits": {
        "lang": "de",
        "tac": "1234",
        "dp": "4321"
      }
    }'
    
  3. Follow the "redirect_browser_to" and authenticate.
  4. Get https://silly-easley-16pa1lzvl4.projects.oryapis.com/admin/identities to see if the traits are available

image

openscript avatar Aug 07 '23 12:08 openscript

Is something wrong with the data mapping I configured for the social login via Google?

local claims = {
  email_verified: true,
} + std.extVar('claims');

{
  identity: {
    traits: {
      [if 'email' in claims && claims.email_verified then 'email' else null]: claims.email
    },
  },
}

openscript avatar Aug 07 '23 12:08 openscript

Thank you, that is very helpful!

aeneasr avatar Aug 07 '23 13:08 aeneasr

I've investigated this issue and can reproduce it. The issue is that the continuity container (which holds the "traits": { "lang": "de", "tac": "1234", "dp": "4321" } data) cannot be retrieved from the database without the ory_kratos_continuity cookie, which of course doesn't make sense in an API flow. See https://github.com/ory/kratos/blob/a0f2420ae74af2393d855aaab1b3bbfbe5f5e732/selfservice/strategy/oidc/strategy.go#L303-L318C3

We need a second implementation of continuity.Manager. Right now, there's only continuity.ManagerCookie, which looks inside a browser cookie to find the continuity container.

cc @hperl

alnr avatar Aug 08 '23 12:08 alnr

For us this is a show stopper. How can I support you to proceed with this bug?

openscript avatar Sep 19 '23 15:09 openscript

A solution to this is not trivial, but possible. I think that we need to attach the continuity container which contains the previously submitted form payload to the state parameter for native flows. This should be fine since we validate the incoming state parameter with an expected state parameter from the API call.

aeneasr avatar Oct 02 '23 09:10 aeneasr