I want a backend app to use another backend service's API, and control per app what it is authorized to call on the backend service. I am using OAuth 2.0 client credentials flow and Keycloak as the authorization server.
I expect roles defined for the backend service and set for the backend app to appear in the access token I request from Keycloak. But the only thing I can manage to appear, are realm level client scopes.
I tried the following (I don't expect to need all of this, but I wanted to try anything that made a little sense):
created realm Test
added client scope on the realm (realm-clientscope1)
added roles on the realm (realm-role1, realm-role2)
define client "backend-service", made this a "bearer-only" client since it doesn't have to authorize itself to other services
create roles on this client (backendservice-role1, backendservice-role2, backendservice-role3-comp)
define client "backend-app", made this a confidential client, with service account enabled
added role on this client (backendapp-role1)
assigned realm-clientscope1 as a default scope
on the scope tab (backend-app Scope Mappings), turned off "Full Scope Allowed", assigned realm-role1, realm-role2, and client roles backendservice-role1, backendservice-role2, backendservice-role3-comp
assigned service account roles with the same roles as on the scope tab (realm-role1, realm-role2, and client roles backendservice-role1, backendservice-role2, backendservice-role3-comp)
After all this, I used Postman to get an access token for grant_type client-credentials. The only thing on the access token is the realm scope "realm-clientscope1".
Why all these options to set service account roles, etc. If they don't show up?
I assume I am misunderstanding how roles are used, but I can't find a proper explanation either.
To try and cover all bases, I also turned on Authorization Enabled on the "backend-app" client, and under authorization, tried to define authorization scopes, policies and permissions that made some sense.
This too, did not result in any more authorization info appearing on the access token.
The last thing I tried, is changing my "backend-service" app from "bearer-only" to "confidential" with Service Accounts Enabled. This also did not make a difference (as expected).
Keycloak version is 15.1.0 (thanks for asking, dreamcrash).
A little late, but I hope that it can be helpful to someone having the same problem.
Basically, it's necessary go to Client scopes tab, and add roles to default scope.
Notice that desired role must be setted in both Scope and Service account roles tabs or it can be setted Allow full scope in Scope tab, and then just set the desired role in Service account roles tab.
EDIT: I forgot to say these configurations must be set in client.
So, in my JWT token, I can see the role:
Related
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.
Is there any way we could pass extra parameters to the signinsilent / silent refresh call from oidc-client based on which I could add extra claims to the access token?
Basically we have resource servers and authorisation server ( identity server 4 setup) which deals with both identity Managment and authorization). Our product is an Angular app and we call APIs using access tokens and we are using oidc-client on client side. We use silent renew to renew the token on client side.
In our application user can have access to multiple organization and in each organization use can have different roles. Currently when user logs in I am adding roles of default organization as role claims. When user switch to other organization I need to refresh claims with new organization roles. I am using implicit flow.
Please help me out with suggestions.
To follow the oidc protocol you can use something like &acr_values=tenant:your-org in the tail of your query, then handle that on IdSrv side. This answer to a similar question could help.
And you do not have to embed that into the existing silent refresh triggering logic. You may construct your new auth request yourself, just keep the redirect_uri to silent-refresh.html. In general that's it.
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).
Can I define custom scope(s) and have them returned when using the client credential flow in Azure AD?
In my experiment, I configured 2 Azure AD applications, one for a Web API and one for a client (Web API Client A). I added a scope to the Web API but when requesting the access token via the client credential flow, the scope wasn’t returned. 🤔
Also, it only allowed me to request an access token when using .default for a scope, i.e. api://web-api-client-credential-flow/.default.
I ran across this Azure Feedback item: V2.0 Client Credentials Implement Scopes so it appears scopes aren't supported in Azure AD under the client credential flow?
What’s the point in giving my Web API Client A application permissions for that scope if they are not returned? How could the Web API know if the daemon application has that scope to perform the necessary action?
It would seem I would have to use application permissions?
Yes, you have to use application permissions.
Scopes aka delegated permissions only apply when a user is involved in the login process.
They allow you to act on behalf of a user.
Application permissions are sort of roles given to the application itself.
They only apply when doing client credentials authentication, where no user is involved.
You can define application permissions on the app via the Manifest in the app registration.
These can then be assigned to the client application.
When getting the token, you must use .default because you cannot change your app permissions dynamically.
You always get what has been granted already.
In the token the permissions will be in a roles claim.
Can I define custom scope(s) and have them returned when using the client credential flow in Azure AD?
No, but you can define application permission(s) via the manifest (definitely not as nice as the UI for delegated scopes) and have them returned via the client credential flow:
Then you can provide the client app permission:
Now when requesting a token with a scope of api://web-api-client-credential-flow/.default the "scopes" are returned in the roles claim. Sample JWT
Yes, you need to use api://web-api-client-credential-flow/.default for client credential flow.
And the application permissions will be returned in roles instead of scopes.
I am using Identity Server 4 for authenticate user from a single application page. For the need of the project, I have to use the resource owner password flow.
Identity Server and my application work fine together. Identity Server give an Access Token and I can use this token to access some API that we own.
However, I was asking myself about the Access Token, users and socpes. For now my setup is this one.
I have an API that require the scope API-1.
I have a client (my SPA) where I defined the scope API-1
And I have a user.
In this configuration, it is the client who own the right to access the API, not the user. And I'm wondering how to give this scope to the user and not anymore to the client.
Stupidly, I'm wondering if user can own the scope and not the client. Maybe I've miss or misunderstood something, so please teach me.
In the Resource Owner Password Flow your client will always need to have permission to the scope that your resource is protected by. This does not mean that you cannot protect your API based on claims related to the user however.
If in your API for example you need different permissions based on the user accessing the API look to use the claims information as part of your authorization. In the Resource Owner Password Flow example at http://docs.identityserver.io/en/release/quickstarts/2_resource_owner_passwords.html you will see that it mentions this at the foot of the page, see the two paragraphs as follows:
When you send the token to the identity API endpoint, you will notice one small but important difference compared to the client credentials grant. The access token will now contain a sub claim which uniquely identifies the user. This “sub” claim can be seen by examining the content variable after the call to the API and also will be displayed on the screen by the console application.
The presence (or absence) of the sub claim let’s the API distinguish between calls on behalf of clients and calls on behalf of users.