Securing URL with user owned resources in OAuth2 - oauth-2.0

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.

Related

Can sub field from JWT be used to grant permission to API resource?

I have been reading a lot the past few days about OAuth2, I understand the use of scopes to delegate access in the name of a user. My question is, if I have users sub: A and sub: B with a /resource/X, only user A should have access to /resource/X, should I use a scope "read:X" in combination with sub field to determine if the user can access that resource, or is it enough to only have the sub field with value A?
I am learning how to use Auth0 API, and there is a question posted from 2018 with no answers that explains exactly my doubts:
Comment about the sub field from tokens
In simple APIs it is common to use scopes alone to determine access to resources. Read and write scopes are common, as are scopes to represent other high level privileges. There are limits to how well this scales though.
In more complex business apps you usually need to identify the user from the token (via the sub claim) so that you can then serve resources associated to that particular user's history.
This typically involves mapping the sub claim from access tokens to your API's own data, as in my below posts:
User Data Management
API Authorization

Using Auth Tokens to grant access to a specific item

I have an application which provides authenticated users with views into data about various objects in a database. There's another application in our ecosystem that provides different views into some of the same objects, using its own permission model. We trust that other application's permission model, and would like to allow them to issue access tokens to users who haven't been authenticated through our application's usual method, so those users can only view specific objects that the other application has verified they have access to.
Rather than coming up with our own spec for the communication between these two applications, I was wondering if there's already a standard approach available via something like OpenID Connect. OIDC seems to handle most of the gnarly details we'd have to consider in a case like this, but the one aspect where it doesn't seem to fit is that its access tokens seem to be general-purpose, rather than calling out a specific object that the user has access to. It says "Here's a user who can access your application", but not "Here's a user who can access Item 123".
Is there a standard for using an access token to grant access to a specific item, preferably using OAuth 2 and/or OpenID Connect? Am I correct in assuming that using an item's ID as a scope on the access token would be an inappropriate use of OAuth scopes?
I've always found the best design for most real world apps to be like this:
OAuth 2.0 based tech identifies the user
You then lookup user details at an application level to enforce authorization
OAuth 2.0 scopes etc cannot handle things like this:
You don't have access to account 123
You don't have access to region US
So I tend to look them up from the user id in the token after login. This tends also to be much easier to extend, if for example the items and user rights in the external app grows over time.
For more concrete info see my write up on API Claims Caching.
Also here is an example of the coded algorithm in a Rest API, resulting in a claims object that can be injected into logic classes.
In your case the custom claims provider would be the external app, and you could query claims from it, for data that does not really fit well into OAuth tokens.
Just my thoughts - not sure if it will fully work for you - but I've found this to be quite an adaptable solution, which often puts responsibilities in the right places.

OAuth 2.0 flow for user groups / organizations

OAuth 2.0 protocol provides permissions delegation of a user so that third-party apps can operate on its behalf. A typical way this is done on the OAuth flow is requesting a user consent to either approve or deny access for the app (Okta example). Here is an official spec describing how it works in general concepts.
I'm looking for the standardized approach to perform the same flow but for the user groups (e.g. organizations). GitHub does that in some way for organizations, so it looks like organizations represent just a group of user accounts. Are there any standardized approaches to this problem?
If not maybe there are any recommended ways how its typically done architecturally or can fit into OAuth 2.0/OpenID Connect protocols.
The OAuth 2.0/OpenID Connect protocols do not cover how access control is performed.
You can, within the OAuth 2.0/OpenID Connect protocols, pass OAuth Scopes or use the OIDC user info endpoint data to allow the resource server to make determination for Access Control.
Many of the commercial products within this area allow the use of LDAP as a back-end for authentication and will even convert LDAP Groups to Scopes.
I would assume, but I do not know, that GtHub stores data with a link (like a group) for the on Organization and/or the user. I know GitHub exposes this using OAuth Scopes.
Oh, and the OAuth Spec is at: https://oauth.net/2/
But if you require Authentication of users then you need to be using OpenID Connect which is built on-top of OAuth 2.0.
Remember that "OAuth 2.0 is NOT an Authentication protocol"
-jim
There are limits to what you can show on the consent screen and dynamically calculated data is not usually supported.
You ought to be able to express a high level scope that you can present to the user though.
In terms of authorizing based on a user's organisations the claims caching technique here can be useful:
https://authguidance.com/2017/10/03/api-tokens-claims/
That is:
* Use OAuth for user identification and high level checks
" Then do the real Authorization based on your back end data
I'm making some assumptions here, but I believe the issue arises from trying to authenticate two things at once.
If the organization is what you need, then go ahead and create a flow to authenticate the organization as the principal subject (via a user who has access to it), instead of actually authenticating the user itself.
Once the access token is generated, you do not necessarily need to know which user generated it anymore (or at least, the token itself does not need to know). If your user needs to be able to view and/or revoke access tokens, they should still be able to do that, since they have access to the organization in your app.

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.

Resources