Need some conceptual guidance of scope vs roles - oauth-2.0

I'm trying to wrap my head around scopes for this scenario.
I have a SPA client and an API. The client only communicates with this API and the API has no other clients communicating with it.
The application has two access levels, say a user and an admin (the SPA may block some routes for the user and the API may block some endpoints).
The roles are administered with AD-groups and mapped to the roles claim.
So what role does scopes play in this scenario? I do all authorization based on the roles claim. But I still need to specify a scope, so I have a API://[clientid]/all scope. Could someone help me make sense of all this?

Scopes are fixed at design time. They are high level privileges that indicate an area of data and what you can do with that data. These are often used as sanity checks, eg to prevent tokens for a valid user but wrong app being used to call an API.
orders_read
Claims are dynamic values looked up at runtime, and tend to have different values for different users. Pretty much all real world authorization is based on claims:
role = supervisor
company_id = 407
So in your case just define a scope or two, but keep them high level and easy to manage. Your claims based authorization (using roles) seems fine.
FURTHER INFO
At Curity we have a couple of good docs that explain the science of designing authorization based on OAuth standards:
Scope Best Practices
Claims Best Practices

Related

How to secure an API with OIDC/OAuth

I'm trying to better understand how to make use of OIDC/OAuth in securing a restful API, but I keep getting lost in terminology. Also when I research this question most of the answers are for Single Page Apps, so for purposes of this question assume the API will not be used for an SPA.
Assumptions:
Customers will access a restful API to interact with <Service>.
It is expected that customers will create automated scripts, or custom application in their own system to call the API.
Once setup it is not expected that there will be a real person who can provide credentials every time the API is called.
<Service> uses a 3rd party IDP to store and manage users.
3rd part IDP implements OIDC/Oauth and that is how it should be integrated into <Service>
Questions:
What OIDC/OAuth flow should be used in this situation?
What credentials should be provided to the customer? client-id/client-secret or something else?
What tokens can/should be used to communicate information about the "user"? E.g. Who they are/what they can do.
How should those tokens be validated?
Can you point me to any good diagrams/resources that explain this specific use case?
Am I missing anything important in the workflow?
It sounds like these are the requirements, if I am not misunderstanding you. The solution contains not just your own code and is more of a data modelling question than an OAuth one.
R1: Your company provides an API to business partners
R2. Business partners call it from their own applications, which they can develop however they see fit
R3. User authentication will be managed by each business partner, resulting in a unique ID per user
R4. You need to map these user IDs to users + resources in your own system
OAUTH
Partner applications should use the client credentials flow to get an access token to call the API. Each business partner would use a different credential for their set of users.
Using your own IDP to store users does not seem to make sense, since you do not seem to have an authentication relationship with the actual end users.
Access tokens issued to business partners would not be user specific by default. It is possible that a custom claim to identify the user could be included in access tokens - this would have to be developed in a custom manner such as via a custom header, since it is not part of the client credentials flow.
Access tokens would be verified in a standard OAuth manner to identify the partner - and possibly the end user.
DATA
Model users in your own system to have these fields, then store resources (such as orders) mapped against the User ID:
User ID (your generated value)
Partner ID (company the user is from)
External User ID (an ID that is easy for partners to supply)
Typically each partner would also have an entry in one of your database tables that includes a Client ID, name etc.
If you can't include a custom User ID claim in access tokens, partners have to tell you what user they are operating on when they call the API, supplying the external user ID:
POST /users/2569/orders
Your API authorization needs to ensure that calls from Partner A cannot access any resources from Partner B. In the above data you have all the fields you need to enable this.
SUMMARY
So it feels like you need to define the interface for your own APIs, based on how they will be called from the back end of partner apps. Hopefully the above hints help with this.

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.

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.

Oauth2, client_credentials, and scope

I've been using Oauth2 for quite some time as a developer but still feel at times I need to go back to the basics. I have a general question around this topic, specifically when it comes to using scopes.
As I understand, scopes are a kind of filter that can be applied to certain APIs and the bearer token is required to possess any scope the API requires. In that sense, they offer an extra 'layer' of protection after the token itself. However, what I would like some feedback on is how best to protect an API that requires scopes. If a consumer obtains a valid bearer token from the issuer and discovers what scope is required for a service, what's the best way to prevent them from making a POST using a token obtained through client_credentials, for example, on a restricted resource?
I believe I know a few solutions: require some sort of user token as well and further lock down resources via a authorization in your business logic (e.g. customers can only modify their own data). Another option might be to require api registration and an approval workflow so only 'approved' clients can invoke a service. Similar to how Akana and other API Gateway products operate. But are there other things I'm missing? Are Scopes really meant to serve as an authorization mechanism at all, or am I misinterpreting their real purpose, because to me they don't seem like they offer much.
Thanks for feedback in advance.

Resources