Keycloak - Use Client scope with client_credentials and authorization code flow - oauth-2.0

I have a RESTful API that is consumed by a browser frontend and multiple machine-to-machine clients. So I'm issuing tokens with Keycloak 18 through Standard Flow (Authorization code) and Service Account Flow (Client credentials).
The operations on the API's resources are protected by scopes like read:resourceA, update:resourceA, read:resourceB, etc.
When I assign a Realm Role to a Client Scope, and if I map a user to the same Realm Role, the tokens issued through the Authorization Code Flow (browser frontend) contain the scope.
Also, when I create a Machine-to-Machine client and I add to Client Scope directly to the Client, the tokens for the M2M client also contain the scope.
So far so good. But as soon as I try to do both at the same time, I no longer have the scope in tokens issued by the M2M-client.
It seems that adding a Client Scope to a Role makes it impossible to use that scope otherwise.
The obvious, but bad solution would be to create a second set of scopes for this kind of client. Is there any other solution I'm not aware of?
I'm migrating from Auth0.com to Keycloak, and that's currently the only point blocking me from finishing this migration.
Thanks,
Pascal

In a standards based approach, scopes are composed of claims. Scopes are fixed at design time, whereas claims have runtime values. So at runtime a particular client and user may result in these values:
- myscope
- roles: [user, admin]
- subscription-level: gold
An example is the built-in profile scope, which includes name and email claims, and might look like this at runtime:
- profile
- name: John Doe
- email: john#doe.io
It is recommended to avoid scope explosion, as you suggest. In Keycloak I would keep scopes the same for all clients, so that nothing changes in the client interface.
A realm role is a type of claim, though a Keycloak specific concept I think. Perhaps you can represent it differently, or configure a realm role for the M2M client also?

It turns out that I missed the concept of Service Account Roles. For all those running into the same troubles:
How to add a new Role to an Authorization code flow client
Create client with Default Flow enabled
Create client role
In Client Scope Settings, add the new client role to the scope
In Client Settings, add the scope(s) to the list of default scopes
Add the new client role to the user
How to add a new M2M client
Create the new client
Create a new client role in the Client settings
In the Client settings, in the tab Service Account Roles, assign the new Client Role
In the Client scope settings, assign the new client role
In Client Settings, add the scope(s) to the list of default scopes

Related

Securing URL with user owned resources in OAuth2

I'm aware of how OAuth2 and OIDC can use custom scopes and token introspection to secure an URL like this:
/users/me/documents
I can give this URL the documents:view scope and when receiving the token from the authenticated user, I can ask the authorization server if this user has the correct permissions. Then I can use the preferred_username claim or similar to see who /me actually is.
But what if I have a resource which is accessible by multiple users? Let's say a user has documents but they can be viewed by his direct manager. To retrieve the employee's documents as a manager, I'd need to have an url like this:
/users/${userId}/documents
How could I enforce it in a way that only the resource owner and direct manager can view this resource? I don't want everyone to access everyone's documents by knowing the userId. I could grant access as a whole to all users with the manager role, but that's not specific enough.
I'm aware there's the UMA extension where users can grant access to resources on his behalf to other users, but it's not the user who grants permission. It's the system who states in this case that managers can access their employees documents.
Would it make sense to write a custom policy which extracts the ${userId} and performs the check? Or should this not be done by the authorization server at all and be done by the resource server instead? Perhaps a different approach to reach the same goal?
Finer grained authorization like this is done with claims rather than scopes. There may be business rules around which docs a user can see, eg:
A user can access their own docs
An admin has view access to all docs
A manager can view docs for people they manage
In an access token this might be represented by these claims:
userId
role
Claims are often domain specific like this and the preferred option is to add them to tokens during token issuance. At Curity we have some good resources on this topic:
Claims Best Practices
CLAIMS AND AUTHORIZATION
The Authorization Server issues access tokens and then APIs (resource servers) verify the access token and use the token data to apply authorization rules (which are often domain specific) on every single request.
Claims are often used when dynamic behaviour is needed - they are runtime values that derive from the user identity, whereas scopes are fixed design time values. In your example an API might also need to vary SQL to retrieve documents based on the user identity.
There are more complex variations on this theme, such as an API calling a system such as Open Policy Agent, so that documents returned are determined by rules configured by a security administrator. That policy would still involve using claims from the access token though.
EXAMPLE CODE
If it helps, here is some sample code of mine that show the type of approach when enforcing domain specific authorization rules. Typically you need to filter collections and check access to individual items.

Do we use "scope" for client credential grant type? Why?

In most OAuth2 typical use cases, the scope is used by resource owner password grant type, or authorization code flow, where a user login is required.
It seems that scope is mainly used to control access of users' resource. For example, to authorize a 3rd party client to access the resource owner (user) resource at another server.
In some cases, user is not present. For example, a company wants to provide a API for another company only. Client credential is being used. Most API gateway products have subscriber management option to control which client ID can access which APIs. In that case, is it still meaningful to use OAuth scopes to manage access to APIs? Why?
Besides, I cannot find any examples using scopes along with client-credential grant type. Is it rare use case?
The Client Credentials grant type is used to access protected resources that both sides own/control/trust.
Scopes are supported by this grant type. They are typically not used because the trust is already there and limiting that trust via scopes is not required.
In other words, the reason that scopes are not used is that if the trust is not there, other grant types are more appropriate.

Restrict client access in a single realm with keycloak

I have a single realm with 3 single-page applications and a shared backend. I want to restrict the access to one of the SPAs so that users without a specific role can't log in.
But once you create a user in the realm, he can log in to every SPA client. I can restrict the endpoints of the backend but I don't want to programmatically reject the user in the specific SPA but automatically on the login page.
I tried to use client roles which don't seem to have an effect in this case. The only solution I have found so far is to create separate realms which I think is conceptually the correct way but unfortunately brings up some practical issues, e.g. the administrators of one realm must be able to manage (CRUD) users of another realm which seems fairly unintuitive.
users without a specific role can't log in - it isn't good requirement. How system will known if user has a specific role without log in (authentication)? Keycloak provides Open ID Connect SSO protocol, which is designated for authentication. After successful OIDC authentication is token generated, which may contains also user role. So only then authorization can be applied. So let's change requirement to: users without a specific role can't access SPA, which better fits into OIDC concept.
The mature OIDC SPA libraries offer authorization guard (name can differs, it is some kind of post login function), where authorization can be implemented. Authorization requires to have a specific role in the token usually, otherwise user is redirected to the custom route, e.g./unauthorized. That's the page, where you can say a reason for denying access. Common use case is also customization of the app based on the user roles. For example users with admin role will see more items in the menu than standard users - that's also kind of authorization. Random example of SPA library with authorization guard (I'm not saying that's a best implementation) - https://github.com/damienbod/angular-auth-oidc-client/issues/441
Keep in mind that SPA is not "secure" - user may tamper code/data in the browser, so in theory user may skip any authorization in the browser. He may get access to SPA, so it's is important to have proper authorization also on the backend (API) side. Attacker may have an access to SPA, but it will be useless if API denies his requests.
BTW: You can find hackish advices on the internet how to add authorization to the Keycloak client with custom scripting (e.g. custom scripted mapper, which will test role presence). That is terrible architecture approach - it is solving authorization in the authentication process. It won't be clear why user can't log in - if it is because credentials are wrong or because something requires some role in the authentication process.
You should indeed not create multiple realms, since that is besides the point of SSO systems. Two approaches are possible in your - presumably - OAuth 2.0 based setup:
restrict access at the so-called Resource Server i.e your backend
use a per-SPA "scope" for each SPA that is sent in the authentication request
The first is architecturally sound but perhaps less preferred in some use cases as you seem to indicate. The second approach is something that OAuth 2.0 scopes were designed for. However, due to the nature of SPAs it is considered less secure since easier to spoof.
I was able to restrict users access to application using following approach:
I've created to clients in my default realm (master) i called my clients test_client1 and test_client2 both of them are OIDC clients with confidential access by secret
I've created a role for each of them, i.e. i have role test_client1_login_role for test_client1 and test_client2_login_role for test_client2.
I've created a two users - user1 and user2 and assign them to client 1 and client2 role. But to restrict access to client1 i have to delete default roles:
That did the trick, when i am logging with user2 i see test_client2 and not test_client1 as available application:
But i did n't delete roles from user1 and therefore i could see both clients when i am log in with user1:
Therefore you should use different clients for your applications, assign to each of a client specific role and remove from users default roles and add one releted to specific application.

How is the correct way to add specific information for Resource Server inside OAuth2 access token?

I have a scenario where my Resource Server (RS) can connect to multiple databases and it can be multi-tenant. It has an environment configuration where I can say: Env A points to database A and belongs to tenant A; Env B points to database B and belongs to tenant B;
Our desktop apps store that information in a data structure that is sent to RS on every call and our web apps store it inside ASP.NET Session. The user select the environment at login.
Now we are moving our APIs completely to REST services and protecting them with oAuth2 using IdentityServer4.
I need to send that environment value to the APIs and I think that should be part of the access token.
The first question is: Is that correct? Can a access token have that kind of information?
The second is: Which is the best IdentityServer4 service that I should extend to inject that value as a claim inside access token and consequently inside ClaimsPrincipal.
The third is: Sometimes I don't have a user to select the environment at login (client credentials grant, for example). In this case, is the correct treat environment as a client claim? There is a way to have dynamic client claims?
Sorry about the long question!
Regards,
Diogo
If that claim is about the users (or clients) identity - yes - it is a candidate for the token.
Add the claim to the resource scopes that represent your API - this way the claim type will be requested in the profile service and you can add it to the token.
Client claims are not dynamic though.

What is scope in IdentityServer

I am trying to understand IdentityServer3 and different terms associated with it in order to secure my Web APIs. Can someone explain what is significance of Scope in IdentityServer with some good example.
I found this link but idea is not clear.
Thanks in advance!
Scope
It's safe to say that Scope is kind of a role to access a specific set of resources IMHO. IdentityServer has two scope types, the ScopeType enum is defined and described as 'OpenID Connect scope types.'
Identity Scope : representing identity data (e.g. profile or email)
For example, if you have a profile identity scope, then clients with this scope can get the profile data from an identity provider ( e.g. IdentityServer )
Resource Scope : representing a resource (e.g. a web api)
For example, if clients have a calendar resource scope, then they can call a /get/calendar/months web api and get the resources.
Scope will be included in Claim when a HTTP request with an access token is in flight and will be further validated at the validation stage for the access token.
Of course the client should be added prior to running IdentityServer and proper scopes should be specified in AllowedScopes; a member of the Client class in IdentityServer.
The better resource to know about oAuth2 is IETF, and about OpenID Connect is openid.net.
IdentityServer is an implementation of OAuth2 and OpenID so it's documentation will not cover the basics that related to OAuth2 and OpenID.
To understand first about scopes you should have a clear understanding about clients.
Client: Models an OpenID Connect or OAuth2 clients (not your client application) and it should have a clear flow for example you defined a client which uses implicit flow.
The flow is the way that you should follow in order to get the needed data for example access_token and id_token.
All flows can be used with any cases but there are recommended flows for every case.
For example, up until now, it was recommended that you use implicit flow with native and javascript clients. Though, recently this has been changed to Authorization Code with PKCE. See Identity Server's blog post on this change to IETF/OpenID recommendations
Scopes: Models an OpenID Connect (Identity scopes like email, given_name etc.) or OAuth2 (Resource scopes like your WebApi that you want to protect it's data) scopes.
You can think about scopes as intent of the client, for example: The Client ask you to use your resource owner to grant me access to your openid scopes > given_name, email & prefered_username and your OAuth2 scope > WebApi.
For full understanding:
1- Pluralsight - Building and Securing a RESTful API for Multiple Clients in ASP.NET
2- Pluralsight - OAuth2 and OpenID Connect Strategies for Angular and ASP.NET

Resources