A simple scenario I have a typical architecture a client,authorization server(OAuth Server) and Resource Server.Client gets token from authorization server with client_credentials and sends token to resource server and it serves the request.So if I have 2 API's either the logged in user can access all or none based on valid or invalid token.
Is there a mechanism to grant access to 1 API ? The question is can token be API specific like it give access to 1 API and not the other.
The scope mechanism can be used to differentiate between permissions that are associated with the access token. E.g. there could be a scope for API A and one for API B. The client could ask for one of those scopes or both and the token would be valid for respectively calling both APIs or just one of them.
See also: https://www.rfc-editor.org/rfc/rfc6749#section-3.3 which doesn't say much about the semantics of scope but in practice a scope is almost always associated with a (set of) permission(s).
Related
My application is composed of an API layer which is accessable by presenting a Bearer Token, obtained from our Identity Server. Each of our API has a level of scopes that the token must contain in order to be invoked: this means, for example, that if you want to make the API call which "creates a product" you need a write access to products (i.e. the scope "products") while you may just need the scope "products_read" if you only want to retrieve them.
Scopes are bound into the token when you authenticate onto the ID server.
Now, I need this user to be able to perform different operations on different "workspaces". Each workspace administrator can set which permissions each user have. This is, in fact, linked to the scopes that each user will have when operating on that particular workspace.
Right now we have implemented that, if you are trying to access a different workspace, the API layer will check:
if your bearer token is valid (by validating it on the ID server)
if you are authorized to access that workspace
changing associated claims by removing the original "scopes" (set into the token by the ID server) and overwriting with those assigned by the administrator of that workspace
This somehow works, but it stinks because I don't want my application layer (API) to have this kind of responsability and the opportunity to tamper with the token. I want the ID server to handle it and, after the user tries to enter into a different workspace, it generates a new crafted bearer token with correct claims (so the API will just need to trust it).
What's the best approach in doing that? I'm digging into the "custom grant type": may this be the right approach?
Scopes are fixed at design time and the same for all users. I like your use of products and products_read - that is very standard.
When you need dynamic behaviour, implement claims, which depend on who the user is. In your case I would use a workspaces array claim. Since this is a key vaue for authorization, it should be added to access tokens at the time of token issuance. Think in terms of your products scope being composed of claims.
It feels like workspaces and other permissions are part of your business data rather than your identity data. At the time of token issuance, IdentityServer should send identity attributes (eg subject claim) to an API endpoint you provide. which returns business attributes (workspaces). I believe in IdentityServer this is done via a custom profile service.
I'd try to avoid different tokens for different workspaces, since that will be awkward in terms of usability and code complexity. The standard way to do it would be to redirect the user each time.
I want to implement a solution where having 2 apis which take data from one another restrict access to the exposed endpoints by scopes.
Let's say that api1 exposes two scopes. read-only and write-only. some of its endpoints will allow only one out of the two some will allow both. Same for api2.
What I don't understand is where are the scopes validated ? Or to be more specific how exactly can I limit access to my api based on the requestor allowed scopes ?
I can undersatnd that on the identity server both the api resource and client should be configured and for the client to allow it to request access for specific scopes configured for the api resource, but I'm missing some information about how to validate the scopes.
Are the allowed_scopes part of the access_token ? If so as being part of the access_token, the api resource for which the token was generated should like decript the token and get the scopes or how exactly does this process work ?
Your thinking is on the right lines. APIs receive access tokens and authorize requests in 3 main stages:
First verify the digital signature of the JWT
Second each API endpoint verifies scopes, using the scope array received in the access token
Thirdly more detailed authorization is done using claims
A common way to check scopes is to use attributes on each controller method. Eg in .NET you get some help from the framework and can do this. See also this tutorial for sone other options:
[HttpGet]
[RequiredScope(myscope)]
public IEnumerable<TodoItem> Get()
{
// Do the work and return the result.
// ...
}
Context
We use Identity Server for identity and access control in our solution. Our scope names have the form of URLs so they are 40-60 characters long.
Some time ago we received a request to increase the max length for scopes in the request. The default value is set to 300 in InputLengthRestrictions class and it can be changed very easily. However, after some discussions, it turned out that for now it may be enough to increase the max value to 500 or 1000 but in the future, an even bigger limit may be needed in order to be able to request 10, 20 or more scopes.
Here comes the question. Is it a good practice to request an access token with such a large number of scopes? What are the pros and cons?
My thoughts
From my perspective, the main benefit of having one "super" access token has one main advantage i.e. it is convenient because it allows you to call all APIs.
On the other hand, I see some drawbacks and/or code smells:
The fact that a large number of scopes must be requested may mean
that scopes are too granular.
The fact that a large number of scopes must be requested may also suggest that scopes are used more as permissions. It is especially a problem in the case of long-lived tokens as they cannot be revoked easily.
Requesting a large number of scopes may suggest that you request
more than you actually need. However, it is recommended to "choose the most restrictive scopes possible".
Having a super access tokens expose a higher security risk if such a token is intercepted.
In implicit flow, a token is passed in URL so the large super token can exceed the maximum length of the URL.
Super tokens might be too big to store them in cookies (it is a
different topic if tokens should be stored in cookies).
Super tokens can be quite large so the network performance can be affected.
What do you think? Do you see any other pros/cons of super tokens? I'm not sure but maybe large super tokens can affect Identiy Server performance.
I don't have pros or cons for you, but perhaps this answer can help you.
Looking at IdentityServer you'll see three parts, the resource, the client and the user. IdentityServer has two main responsibilities, authorize the client and authenticate the user. User authorization is actually not the responsibility of IdentityServer. That's why they created PolicyServer.
Consider the following resource:
resource = CalendarApi
scope = Calendar.Read
scope = Calendar.Write
scope = Calendar.Event.Create
The resource is just a logical name. It can consist of one or seperate api's (as in projects), where an api can implement a single or multiple scopes. In the api a scope is an implementation of certain functionality.
Only a client can request a scope, because the client knows how to use the functionality.
Suppose I have two clients: Mvc1 and Mvc2. Mvc1 has a calender view and an admin page, while Mvc2 only shows the calendar.
My configuration:
Mvc1: scope = Calendar.Read Calendar.Write Calendar.Event.Create
Mvc2: scope = Calendar.Read
It has no use for Mvc2 to request all scopes, because it doesn't use the other functionality. It wouldn't make sense to request all scopes. And in case Mvc2 is a third party app, you shouldn't, because they could use it even when this was not the purpose.
Best practice here would be that a client only requests scopes that are allowed (as configured in IdentityServer) and may be implemented by the client.
So far the user was not involved, because there is no relation between scopes and users. However, the client needs the user (as resource owner) to actually access the resource.
It then comes to user authorization to determine whether the user can create events on the calendar. This 'permission' is not the scope.
The scope Calendar.Event.Create doesn't allow the user to create an event. It only allows the client to connect to the resource.
When combining the clients and users, then there is only one situation where a user can create an event: when a user with create permission uses the admin page in Mvc1.
Mvc2 can't access the resource, not even when the user has create permission.
Now getting to your question:
Is it a good practice to request an access token with such a large
number of scopes?
The access token should only contain the scopes that are needed, as described above. Only necessary scopes should be requested by the client.
Agree. The number of scopes should not be too detailed. Don't treat scopes as permissions, e.g. create, edit, read. Though I did as example, a better scope would be Calendar, where the user permissions define what the user is allowed to do (CRUD permissions).
Agree, should be investigated.
I would say yes, as argumented above.
It is still the user that has to be authorized. But you should limit the possibility for clients to use functionality that was not meant for that client.
/ 6. / 7. Hitting limits is a good indication that the architecture may need some redesign. In general you should not expose more than necessary and you should avoid hitting limits.
I suspect the problem is that scopes are used as permissions. Remove the 'CRUD' from the scopes and redesign user authorization. Don't set permissions in claims.
In my design there is no need for a super token, nor will I ever hit a limit. There are only few scopes, the access token only contains the sub claim and policy server tells me what the user is allowed to do.
I hope this helps you in any way. Please let me know if something is not clear.
You can implement Service Account flow for same. Using it you can get token of respective client with all allowed scopes to client.
By this way your token does not have included all scope but has scope allowed to client.
I don't have sample code right now but you can check how service account can be implemented
This question already has answers here:
How to validate an OAuth 2.0 access token for a resource server?
(6 answers)
Closed 4 years ago.
How REST API protects itself against an access token which was not generated by an allowed OAuth Access Token URL?
Token generated by an allowed OAuth Access Token URL
"Authorization: Bear MTqvlvbdm73SIsN2PEhsetOwEHW439N2"
Token generated by a hacker
"Authorization: Bear CAqvlvbdm73SIsN2PEhsetOwEHW439N2"
This is outside the scope of the Oauth protocol: see Section 1.5 of the specification and note that your question is step D. The document says:
Steps (C), (D), (E), and (F) are outside the scope of this specification, as described in Section 7.
Section 7 says:
The client accesses protected resources by presenting the access token to the resource server. The resource server MUST validate the access token and ensure that it has not expired and that its scope covers the requested resource. The methods used by the resource server to validate the access token (as well as any error responses) are beyond the scope of this specification but generally involve an interaction or coordination between the resource server and the authorization server.
However I note that it does not always need to be this way. For example, if your access token is a JWT, then the resource server should be able to verify without interacting with the authorization server.
The reason why it is outside the scope is because it depends upon your architecture. There are various ways that this can be implemented. For example, if the resource server and the access server share the same database, then they do not need to talk to each other.
I need to add a token inside a token for an "act-as" schema on a custom grant type in IdentityServer3.
I tried with PreserveAccessToken but it just adds the token as a claim in the current ClaimsPrincipal, but can't find a way to nesting it as a claim when getting another token to pass along to the next service/api in the chain.
The idea behind this is for being able to keep an audit of all the hops from the end-user to the last service/api in a chain of calls.
This can be achieved using a custom grant. This allows extending the token endpoint with custom "operations" - e.g. issuing a token that contains delegated claims - e.g. a token.
docs are here: https://identityserver.github.io/Documentation/docsv2/advanced/customGrantTypes.html
here is also a sample that comes close to your scenario: https://github.com/IdentityServer/IdentityServer3.Samples/tree/master/source/Multi%20Hop%20Delegation%20(ActAsCustomGrant)
that said - this is probably the most expensive way to convey a user id over multiple hops.
If there is a trusted subsystem between the back-end system, simply transmitting the required data as payload is much simpler and much faster.