I am using Identityserver4 for AuthZ and AuthN and trying to understand the purpose of scopes for a webapi
I am implementing a first party application an internal application which will works in intranet. so there will be no consent page.
image : application architecture
I have 3 users
User X : who can perform read and write operation on Web API ‘A’ Only
User Y : who can perform read and write operation on Web API ‘B’ Only
User Z : who can perform read and write operation on both Web API ‘A’ and ‘B’
Since all the user will log in using the ‘Angular front end’. In the front at the time of login the scopes requested must be like below
{
response: code
scopes : ‘openid A:read A:write B:read B:write’
}
As I said earlier, I am using Identityserver4 once the user successful logins the client will receive Id_token and access_token.
I understood from different article that api will check for the scope to provide access to an operation like read and write. So,
If User X logs in, access_token should contain scope only A:read, A:write
If User Y logs in, access_token should contain scope only B:read, B:write
If User Z logs in, access_token should contain scope only A:read, A:write, B:read, B:write
Since ‘Angular front UI’ is same for all the 3 users (X, Y, Z) in my case.
Client will request all the scopes (A:read, A:write, B:read, B:write) is this correct ?
Do I need to write any custom logic when access_token is getting generated, its should include only scope that user is entitled too?
If I have to write this custom logic which interface I need to implement. is it IProfileService?. i have to use something like role to find out the scopes?
Lastly, in other word, scopes for an web api is nothing but permissions am I right?
In IdentityServer I would create one ApiScope (perhaps named ApiAccess). Then I would create two ApiResources, one for each API and associate them with the ApiScope created earlier.
Then have a UserClaim (perhaps named access) associated with the ApiScope, that contains the particular users access (read or write).
the value for the access claim is then retrieved from the user database.
Also, do see my answer here for a clarification between ApiSope, ApiResources and IdentityResources.
To complement this answer, I write a blog post that goes into more detail about this topic:
IdentityServer – IdentityResource vs. ApiResource vs. ApiScope
Related
I have an IdentityServer4 application, a client application and a .Net 5 API. I want the client application to be able to talk to my API on the users behalf with an access token. Some users should be able to do admin requests while others should only be able to do normal user tasks.
I believe I need to add two scopes for these, api.admin and api.normal.
First question is where would I add these scopes in identityserver? Does the client request both scopes and just gets back whatever IS decides is right for that user?
Secondly, how do I validate what scopes are in the access token on my API. Method 1 should only be used if the access token contains the api.admin scope for eg.
Thanks!
First, scopes are something you typically hard-code in your client and it does not "vary" between users. It main purpose is to indicate what the "client" application want to have access to, not the user.
So you only need only one scope like "api".
Then you have different roles or claims in the access-token that describe what the authenticated user have access to.
You then use the authorization middleware in the API to determine what the user actually have access to.
Like what the picture below shows:
There is no reason that different scopes could not be requested by the client based on the user interacting with the client or even environmental based criteria.
As some quick example, a USER that has Authenticated to a Client Application that determines the user is a "Preferred Customer" vs a visitor might be granted scope to allow reading "Preferred Content".
The client then requests a "preferredcontent" scope for the "Preferred Customer" and not for the visitor.
And of course the Authorization Server may reject the scopes requested for any reason.
I'm designing the architecture for a college project and I don't know how to deal with the user authentication and authorization part of it. The project is a desktop Electron app which would need two types (hence the roles) of users. They both need to be authenticated in order to use the app, and depending on their identity, they will have different authorizations. Since the project is meant to be used by teachers and students as part of a laboratory class after it is done, I don't think more than 30 people will be using it at the same time.
My first thought was using a PostrgeSQL database in AWS for this and implementing the authentication myself, but this means that users will have to sign up and create a new profile, which means remembering yet another <username/email, password>. Trying to avoid this, I read a bit about OAuth 2.0 and OIDC, and how it can be used to authenticate and authorize users without implementing either of those tasks oneself, but rather delegating the task to OIDC. I created a free account with Auth0 and thought about using it for the OIDC integration but after reading about 40 pages of an "OIDC integration handbook" they offer for free, I could not know if I would be able to distinguish my user base through these roles or tags as I mentioned. I just followed the steps in the tutorial handbook and tried to understand how the auth flow worked, but that didn't give me any information on my question.
So all in all what I want to know is: is it possible to implement this with Auth0 (free account) without having to use a third-party database solution (such as PostgreSQL with AWS)? If not, what would you recommend me to look into? Preferrably a solution that will let me discriminate between the two types of users BUT at the same time taking advantage of the OIDC implementation of Google for example.
There are 2 separate solutions here:
DESKTOP AUTHENTICATION
The 2 standard requirements are:
Use Authorization Code Flow (PKCE)
Login via System Browser
You listen for a login response via one of these mechanisms (I prefer the latter):
Loopback web server
Private URI scheme OS notification
My blog has some tutorials + code samples that use Electron. You can run both of the above listening options and see what you prefer.
API AUTHORIZATION WITH ROLES
You need to make roles available to the API via claims. This can be done by either of these mechanisms (I prefer the latter):
Including roles in access tokens via Auth0
Get the API to read user roles from its own database
My Authorization blog post discusses building up a claims object in an easy to extend way. The main objective is usually for API OAuth processing to result in an object something like this:
class UserPrincipal {
// The technical user id from the access token
string sub;
// The user id from your own database
string userId;
// The user's roles
string[] roles;
}
Given that object you can do things like this:
Use role based authorization when needed
Serve up user resources after login from your application data
TO SUMMARISE
Auth0 will meet some of your requirements and may be all you need in the early days. You will probably need to manage non OAuth user data in your API at some point though.
Happy to answer any follow up questions ..
This is an API related question that applies to the APIs that I'm working on and would like to know the standard way of doing this.
say a user1 has created accounts so he can access it by
GET /accounts
but when he accesses transactions for a particular account
GET /accounts/acct1/transactions
how would this API know that the acct1 actually belongs to that user1 and is not the case where user2 is accessing user1's accounts.
This api is accessed via a Mobile app using Oauth 2.0 tokens. So while the access token control the access to API endpoints, how do we control access to only specific user's data at that endpoint. (using scopes?)
I've been looking at Spotify's apis and they seem to be doing this via v1/me end point.. Still reading...
I'm a noob at this and it looks to me that this should be documented somewhere in a standard manner in some RFC, but I couldn't find it and would appreciate direction
Can you provide more details on your use case? Why are you using OAuth?
It sounds like you need an authentication protocol - i.e. a protocol to let your server know who is accessing a particular API.
To quote the OAuth website:
OAuth 2.0 is not an authentication protocol
OAuth's main use-case is letting one application perform operations on behalf of a user of another application.
As an example, if your server wants to post a message on Facebook on behalf of a user, you will use OAuth to obtain a token from Facebook which lets you post messages on behalf of the user. Note that, in the most general case, your application does not know which user is represented by the token. Indeed, the user may not even be a (registered) user of your application - they only have to be a user of Facebook.
Practically speaking, you often can use the token you have to query Facebook for the identity of the user. So your server would extract the OAuth token from the request headers and use it to issue a query to Facebook's Graph API to obtain the user ID.
Note that the user is a Facebook user rather than a user of your app, so you will need to somehow map the Facebook user ID to your own users and permission system - i.e. check your database to ensure that the user has permissions to do what they asked to do.
This is the mechanism that is typically used when using OAuth like an authentication protocol (which, as quoted above, it is not).
I should add that if your app obtains an OAuth token and passes it to your server for the purposes of authentication, then this flow is not 100% secure, as discussed for example here, so make sure you do proper risk analysis for your case. In a nutshell, a determined attacker can theoretically impersonate your app and obtain tokens representing other users.
I'm connected to an API that provides information about cars based on their registration. According to the docs the api can provide both user specific data and general data about the registration supplied.
I am using the connection method which does require specific users data, and therefore does not require me to gain access to any specific users account.
On my end users will visit my application and enter a registration number which I will use to call the API and return all of the information about the car.
Am I right in my thinking that my application is essentially the 'user' as far as the api is concerned, and I will only need to use one access token. I can then use this access token to make multiple API calls (one for each user that searches on my application)?
Or will i need to set up an access token for each user that visits my application and treat them separately.
Only your application making the API requests requires a token, unless the licence agreement/documentation of this car API says otherwise.
As far as your users are concerned, your application is just magically sourcing the registration info from its database.
I'd like to ask a question to confirm my understanding of how to use Scopes and Claims (roles). Let's say I have a User (User A with read only rights i.e. suitable read only role), a Windows Service (Client A with read only access), an MVC site (Client B with full access), and a Web API. I want the Web API to be accessed by Users and Clients with full access and read only access.
I create two Scopes "sampleApi.full and "sampleApi.read_only"
I create two Roles "full_access" and "read_only"
I configure the Web API with RequiredScopes = new[]{"sampleApi.full", "sampleApi.read_only"}
When Client A connects to the Web API, it passes an Access Token containing Scope "sampleApi.read_only" and I can use [ScopeAuthorize("sampleApi.full)] or ScopeAuthorize("sampleApi.full, sampleApi.read_only")] on my Classes and Methods to fine tune accessibility. No problem.
However, when User A logs in, then he/she "inherits" the Scopes of Client B. So the Access Token contains "sampleApi.full", "sampleApi.read_only", and Role "read_only".
Now I have a problem at the WebApi in that I need to act differently when being called by a User. In that case I ignore the Scopes and use his/her Roles and the User gets "read_only" access which is what I want.
That being correct, it no longer makes sense to use the ScopeAuthorize attribute, and I need a custom hybrid attribute that does something along the lines:
If Caller is a User
- then use Roles to determine accessibility
Else
- use Scopes to determine accessibility
or have I completely misunderstood?
Scopes model what a client (not user) is allowed to access. They are manifest as claims in the token. The user's claims are also in the token. Authorization in the resource will be based on a combination of what the client is allowed to do and what the user is allowed to do. That's it.