Background Explanation
When it comes to Identity Server 4, I come to a road block when i think about the design of user management in the client applications.
At this point, I have Identity Server setup using ASP Identity User Accounts as its user store.
I've built the UI for adding users to the Identity Server User Store.
I've tested setting up a client which is an MVC application, and I'm at the point where i can successfully authenticate with Identity Server and receive the openid identity token in my client application.
Identity Server is providing my client application with authentication.
Now, i need to concentrate on authorization within my app. This is where i get stuck, I need to create users local to the application, where user privileges within the application are stored.
I will need to link / associate the user in Identity Server to the user in the client application.
One way to do this would be to store the sub in the identity token as a user claim in the client application database (Asp Identity). This way, when a user authenticates i can locate them in the local db, based on the sub in the token.
The sub would have to be the user's unique id in the identity server user store. This way, if the user's email is changed, we can still link the two user accounts.
The user accounts in the client application wouldn't require passwords or email addresses, it would be purely claims and roles that are used for authorization across the application, as well as any other application specific information.
Question
Communication between Identity Server and the client application must need to exist when creating users in the client application?
We need to associate the two accounts?
We need to ensure that the client user account being created also has an Identity Server user account to be successfully authenticated?
When in the process should these tasks be complete? Im looking for some guidance in the flow of the communication between the two applications?
EDIT
Is it feasible that there are no User Accounts in the client application at all?
By this i mean that all user claims for a user are stored in the User store of Identity Server.
When a client authenticates with the IDP it requests only the user claims that are specific to the client application.
Example user claims in the User Store :-
"clientA_role" : "administrator"
"clientB_role" : "user"
When Client Application A authenticates, it requests only the scope clientA_role
This feels bad!
Any suggestions?
If you have many client applications then the way I recommend to do the user management is:
User Management Service:
Create a separate service for users management that identityserver will use as user store and applications will use as user repository when user metadata is needed.
Also why would you do something like:
Example user claims in the User Store :-
"clientA_role" : "administrator"
"clientB_role" : "user"
why not
just "roles": "user"? and in your application you will protect your resources using Authorize[Role] annotation.
do not create different fields for different applications, think of it as general user management service, I am pretty sure that standardizing your identity management will make it easier and will gain you maintainability and flexibility.
IdentityServer service handles identity management:
might be a good idea to keep user store inside the same service providing authorization if you feel that your application does not have such deep users management needs.
again in this case, store standard claims and return the claims you need inside an id_token or access-token.
Update:
For a specific user that have different roles in different applications:
let us say we have the following:
1- User1 has user role in first app and admin role in second app, then
User1.Roles{"FirstAppUser","SecondAppAdmin"}
2- User2 has admin role in both apps, then:
User2.Roles{"FirstAppAdmin","SecondAppAdmin"}
Related
I've got following setup:
IdentityServer4 using asp.net core identity
Accounts app - where user can edit his account data and users can register
Portal - where users can login and select an organization to which they're connected (same as in azure devops)
API that is used by portal
Does anyone have experience setting up something similar ? My question would be how to authorize the calls at API level to make sure he is only editing entities that belong to his organization.
Thanks !
One way could be to use a tenant claim within each bearer token, so that when a user changes an organization on the portal (in case one user has access to several orgs), you perform relogin to the chosen tenant, or just request a new access token with a chosen tenant_id inside.
You can use this and this answers for the reference on how to pass a custom parameter (such as tenant id) with your request to Identityserver.
Our OAuth client application is built with Spring (through JHipster). The OAuth provider only serves the authentication functionality, but not the authorization functionality. Ideally, we should only allow a small group of people to access our OAuth client application, but not all those users who can sign in to the OAuth provider.
A solution I can think of at this moment is to create a custom user role to control the access in the OAuth client application. That, however, only can be done after the user's first sign-in when the user account data is created in the application.
Any better solutions?
Ideally you would apply user access control before creating user account data is created in the application. You could do so by providing an application specific scope or claim in the token that is generated for your application (aka. Client). Upon receiving the token, the application would check for the required attribute in the token before allowing access.
How do I best configure Keycloak so that a user needs to have an account for a client to be able to login into that client?
I have to replace a proprietory SSO-Impl. It deals with users, roles and clients much like Keycloak. However, it also knows about accounts. A user is only allowed to login to a client if he has an account for that client.
In Keycloak, if a user simply exists in a realm he may login to a client of that realm. Nothing else is needed. So no "account" is needed. In the old application, he needs an account as well.
What functionality in Keycloak is best suited to overcome this difference?
I have one idea:
Create a client-role in each client namend "HasAccount" and assign it to users. Then, restrict access if that role is missing.
This is discussed here: "Restrict client access in a single realm with keycloak"
It has at least two drawbacks:
It mixes authentication and authorization in the legacy app. I can understand that. But creating a role was already a workaround. That is why I described my initial problem here.
I have clients in 3+ languages/technologies. Adding functionality there seems like more work than in Keycloak.
Last remark:
Before you ask "This is not single sign on" anymore. It is only for administrative purposes. The admin can allow users to login into a client or not by creating an account or not. The user does not have to login a second time. If he is logged in in App A and has an account for App B, accessing App B works without logging in there.
A user is only allowed to login to a client if he has an account for that client. is really not a task for Identity Provider (IdP). It provides only identity and not authorization.
Of course you can ignore that and implement authorization as well. See: User attribute based web service access control by Keycloak
From the design perspective I would add auth reverse proxy in front of legacy app (but it isn't a best solution for SPA apps). Auth proxy will provide authentication via OIDC protocol and also authorization. Legacy apps may keep own OIDC authentication - it will be seamless auth from the user perspective, because SSO will be used.
Account entity - you can use group entity in the Keycloak instead of original account.
In our project, we are using oauth (implementation - apifest) for token generation and validation. I am unable to understand the scope concept.
As per my understanding, oauth scope is used for authorization, which consists of some permission.
We have capability and role concept in our project, where:
Capability - permissions
Role - group of capabilities.
A role will be assigned to a user, based on which he functionality across application will be defined.
Role creation is dynamic.
Is this role concept the same in oauth? or is the scope defined at application level, where the users in that application will have the same scope?
I tend to think of Scopes as a permission (or entitlement) to perform some action.
A role is typically a collection of permissions required to perform a "Job" or work within a "Project"
OAuth has no concept of a "Role"
Scopes are Requested by the client but are only Granted by the Authorization Server.
Scopes requested may not be granted and additional scopes may be granted that were not requested.
Scopes are used to delimit which applications can act on the behalf of the resource owner.
If you have an application, say a voting service, at voting.example.com. You have two roles: voters, which can see a poll, and vote, and admins, which can see the full results. The voting application enforces permissions based on these roles. A local user is assigned a local role. The application is protected using OAuth, so a user can be identified by a token.
You also have a social network app, social.example.com. This app provides a page where users can vote on the voting service. It is also connected to the same OAuth authorization server.
Finally, someone else has a reporting app, reports.example.com. This app would like to allow users to see the vote tally by requesting it from the voting service. It is connected to the same authorization server.
The authorization server, say iam.example.com. The authorization server has three clients, one for each app described above. There are two scopes defined in the authorization server, voting, and reporting.
The reporting app, when you login will request the reporting scope. The actual login happens on iam.example.com which will grant the token to reports.example.com. The login form will ask you, the user, whether you grant the client (reports.example.com) the right to act on your behalf and obtain reports from the voting service (provided by the reports scope). The scope will be recorded and associated with the token it sends to reports.example.com.
Now the reporting app can make a request to voting.example.com which says, "I would like to see the voting tally" The voting.example.com app will check the token, and provided it has the reports scope, it will send back the tally.
If it tries to make a request to the voting service to vote, it should be refused by voting.example.com, because the bearer token does not have the scope allowing you to vote. This must be enforced by the voting app. The authorization server manages which client is granted which scope. Only to see the reports. This is not related to your role in the voting application itself.
OAuth itself doesn't provide a mechanism for identity validation, so you do not have a mechanism for validating who you are from the token, and what roles you have. OpendID connect (OIDC) provides extra functionality for this by providing a scoped based identity endpoint protected by the authorization endpoint which allows it to reveal your identity to the app. So if we assume you have OIDC too, then it will check, from the token, who you are. It can then check it's database to see whether you have the right role, and whether you are allowed to see the tally before sending it.
What the scope enforces, is that the reports app, using it's client, can obtain a token to act on your behalf and ask for the information. When you grant the client the scope, you are allowing it to communicate with the voting service to obtain the information.
Roles are managed by your application and with a permission system, determine who can vote, who can read the votes.
Using something like OIDC, you can extend OAuth so the token identifies who you are. voting.example.com can then check that you are a) authorized to vote (by the local logic), b) that the application doing it on your behalf is allowed to act on your behalf (through the scope attached to the token).
I'm looking to use an identity service such as Azure B2C, Auth0 or OKTA to secure my application.
After the user signs up for an account, I need to display a custom registration form in my application in order to complete the registration. This form requires a business process behind the scenes and therefore it can't be part of the Identity Service (IDS are quite limited to capturing static data).
How do I ensure the user has completed the registration form on my application, when they sign in?
I'm thinking of using a claim such as "RegistrationComplete" and setting this to False when the user signs up. After they've signed up I can update this claim to be True.
I can't find any information online about this scenario so I not entirely sure its standard best practice.
Disclaimer: I work at Okta
Okta does have some features which should allow this. You can pull properties from the user's profile in Okta and put those properties on tokens as claims when the user is authenticating. So the user profile holds the state you care about. Your app/service can then read this claim from the token to determine if the form should be shown. Once the form is complete, your backend service can use the Okta APIs to update this user profile state, and then send the user through the authorize flow again to get a new token with the updated claim (specifying to not prompt for re-authentication when going through the authorize flow again).
There is a restful provider feature in azure ad b2c. Using the Rest Apis from any service along with custom policies in b2c, we can get user input and save that user input to any database. The REST apis can be used to orchestrate any step.
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-rest-api-step-custom