ory / kratos

Next-gen identity server replacing your Auth0, Okta, Firebase with hardened security and PassKeys, SMS, OIDC, Social Sign In, MFA, FIDO, TOTP and OTP, WebAuthn, passwordless and much more. Golang, headless, API-first. Available as a worry-free SaaS with the fairest pricing on the market!
https://www.ory.sh/kratos/?utm_source=github&utm_medium=banner&utm_campaign=kratos
Apache License 2.0
11.05k stars 950 forks source link

improve multi schema handling in different auth flows #765

Open c0depwn opened 3 years ago

c0depwn commented 3 years ago

Is your feature request related to a problem? Please describe.

I came across an issue when spinning up kratos along with the oathkeeper proxy and selfservice-ui-node. I have defined multiple identity schemas in json inside the kratos config. One is for an “employee” user type and the second one for a “customer” user type. My issue is that I would like to be able to specify the schema when registering a new account from the selfservice endpoints or public API or anywhere else where I can create/edit a user. The admin API seems to offer a POST /identities which allows you to send schema_id in the request body which works, but there currently is no way to specify any credentials in this way (which makes sense and I think is already addressed in v0.5). Also when I create a new user via the selfservice-ui-node and check the created identity in the admin API with GET /identities the schema_id always seems to be “default” since I cannot specify one in the selfservice flows. Only when using the previously mentioned admin API endpoint to create a user the schema is actually “employee” or “customer” instead of “default”.

It would be awesome to have some way to distinguish between schemas and to use identity schema_id's similar to how a "role" would work. Especially when having a SPA, it would be awesome to be able to restrict the UI according to the schema_id which is retrieved inside the response of the GET /session/whoami or in the JWT sub on the backend when using oathkeeper along with kratos. Additionally, I think it would be an improvement to actually set the schema_id instead of "default" when creating a user with the current implementation through the selfservice registration flow.

Describe the solution you'd like

Specify schema_id in flows effecting identity creation/modification in some way to render proper traits/form inputs. Additionally, store the proper schema_id instead of "default", even when only 1 schema is specified in the config.

Describe alternatives you've considered

None at the moment.

Additional context

This feature brings along some security concerns, since we wouldn't want to be able to let a user register with, let's say, an "admin" schema, without actually having the right to do so.

aeneasr commented 3 years ago

Thank you for the write-up and sorry for the late response!

Specify schema_id in flows effecting identity creation/modification in some way to render proper traits/form inputs. Additionally, store the proper schema_id instead of "default", even when only 1 schema is specified in the config.

The problem here is that the user is allowed to pick the schema to their liking. Are they really an employee? Or do they just say they're one? When it comes to roles in a company (which the schema in this case would infer) it is very dangerous to leave that open.

Generally though, I think it should be possible to set the schema for registration flows to something other than default. Would that maybe address your issue?

Alternatively, we could probably offer an Admin API endpoint which initializes a new registration flow with the given schema ID. Then you would have a privileged backend service initializing the flow and setting the flow's schema ID to the value you want.

c0depwn commented 3 years ago

I think it would make sense to modify the Admin API so that an authorised backend could choose a schema by supplying the schema_id when initialising the registration flow.

aeneasr commented 3 years ago

Yup, that sounds the most reasonable to me as well!

atreya2011 commented 2 years ago

@aeneasr First of all, thank you for providing such an excellent service as open source.

Generally though, I think it should be possible to set the schema for registration flows to something other than default. Would that maybe address your issue?

Please correct me if I am wrong. By doing the above, we should technically be able to specify the schema for self-service registration flows right?

If that is the case, then does this endpoint require modification? https://www.ory.sh/kratos/docs/next/reference/api#operation/initializeSelfServiceRegistrationFlowForBrowsers

Since the above endpoint is public, I don't think it is secure to specify the schema ID as anyone can just change that and try to register using a different schema ID.

Which is why, I think the following comment was made:

The problem here is that the user is allowed to pick the schema to their liking. Are they really an employee? Or do they just say they're one? When it comes to roles in a company (which the schema in this case would infer) it is very dangerous to leave that open.

For example, I would like to implement a customer registration UI that automatically saves the customer information using the customer json schema instead of the default schema. However I am not able to visualize the registration flow if we restrict specifying the schema ID to just the admin API.

gitn00b1337 commented 2 years ago

I'd argue this should be "both". In this issues example then the employee is a restricted account type you'd want to hide. But for many SAAS products there's multiple account types (business customer, end users, affiliates etc) which all would be fine to have public registration for. And if there's specific logic required to "validate" the account registration before acceptance you can already do that via hooks.

Kaishu-Sahu commented 2 years ago

I also think there should be both because in our use case, we have two types of customers phone/password and email/password. We want to keep them separated as both have different roles to do.

nikist97 commented 1 year ago

I am facing the same problem. Two different account types (so different schemas) - for simplicity, I would just call one of the account types a "business owner account" and the other "a customer account". Users are able to register as a regular customer or as a business owner.

I was trying to find in the API spec if there is a way to initiate the registration flow with a non-default schema ID, but this doesn't seem to be possbile based on the information in this issue.

Any advice?

ramirobg94 commented 1 year ago

I am also trying to understand what is the best way to implement different roles, any idea or documentation?

Also I need to populate the role into the claims to be used by other services like hasura

sijumoncy commented 1 year ago

Any updation in passing schemas id in registration flow instead of default schema . ?

aeneasr commented 1 year ago

Yes, the design should be like this. When specifying identity schemas, one should be able to specify whether a schema can be used for registration (naming is just a suggestion):

identity:
  schemas:
    - id: ...
      url: ...
      self_service_available: true

Then, during the init registration flow, it can be set as a query parameter:

GET /self-service/.../browser?use_schema={schema_id}
nikist97 commented 1 year ago

@aeneasr do you know if anyone is working on implementing this suggestion?

aeneasr commented 1 year ago

Afaik not!

nikist97 commented 1 year ago

@aeneasr Would you say this is something a first-time contributor can implement? I haven't touched the Kratos code base before, but will be willing to spend some time on this since it's important for the project I am working on

aeneasr commented 1 year ago

Depends a bit on how well you know Go but if you do I think it should be doable. The most difficult part will be writing the tests most likely!

nikist97 commented 1 year ago

Got it, I will give it a try, hope you don't mind me reaching out on Slack if I get stuck

aeneasr commented 1 year ago

Of course :)

sijumoncy commented 1 year ago

.https://github.com/ory/kratos/issues/765#issuecomment-1303073978

Thanks for the reply @aeneasr Sorry for not providing the clarification in the first question. What if I am using baseurl:4443/self-service/registration/api , How can I specify the schema that I need when I initialize the register flow with this ?

nikist97 commented 1 year ago

@sijumoncy my understanding is that the suggestion from @aeneasr (I will let him correct me if I am wrong) will work the same way for both browser-based and API-based flows - a query parameter use_schema so in your case self-service/registration/api?use_schema=<schema_id>

MJEND7 commented 1 year ago

@nikist97 Did you end up starting on this? This is something that I would love to have working!

nikist97 commented 1 year ago

@MJEND7 I have briefly looked through the code, but unfortunately didn't have the chance to actively work on it yet due to project re-prioritization. I was hoping to find the time to work on it this month, but if you have an urgent need feel free to pick it up instead of me

nikist97 commented 1 year ago

Just providing a quick update here, I finally found some time to try to implement this feature and have an initial version; currently working on fixing existing tests and adding new ones

@aeneasr hope you don't mind if I reach out here or on Slack in case I get stuck

nikist97 commented 1 year ago

Unfortunately, this seems like a more complex feature than I originally expected since there's lots of logic in the code that assumes the default schema was used during registration. My suspicion is that the registration flow instance will need to be updated to store the chosen schema ID in order to be able to implement this (pending discussion with @aeneasr)

till commented 9 months ago

Is there a document to read on what the schemas can be used for? Aside from the admin APIs, they don't seem to be used in any APIs? And what's the correlation with identifiers, can I have multiple identities that share the same email address, but use different schemas?

zeroows commented 3 months ago

Has progress been made by having different schemas work with login/registration flows?

acmayberry commented 3 months ago

I'm also curious about progress on this issue. I'd love to see @aeneasr's approach implemented.

renom commented 4 weeks ago

What if, let's say I need two different registration (login) flows:

  1. The first flow accepts one schema (registration and login from internet).
  2. The second flow accepts multiple schemas (registration and login from internal network).

I.e. I allow the first case flows from internet with oathkeeper, while the second case flows are only allowed from internal network. Can I achieve this? If no, please consider supporting it.

renom commented 4 weeks ago

Can I run a second instance of kratos with a different config (but the same db) as a workaround?

sijumoncy commented 4 weeks ago

@renom Yes you can run 2 Kratos point to same db. It might lead to complication in maintenance, but it works well.

I used 2 Kratos instance, points to the same PostgreSQL database

These instances are containerised with Docker