I'm trying to understand how OAuth 2 works.
I don't understand this thing: if Authorization Server and Resource Server are not the same system, as in this image:
How the resource server can know who is the user and what are his permissions?
Can I retrieve these information from the Access Token or I must have a back-end comunication between Authorization Server and Resource Server?
Depends on the type of token as to how it's consumed by the resource server.
Self encoded access tokens tokens (e.g. JWT bearer tokens) will contain all the user and scope information in the token. Or some Auth systems use token introspection as detailed in Jan's answer.
This is a good introduction to the resource server and the types of token.
And a very common self encoded token is the JWT Token.
Taking the example of a self-encoded access token:
The Access Token will contain the user identifier and scopes / permissions for the token issued in the example above - which is the "implicit" grant type.
The Resource server should not need to contact the auth server. This can be one of the key benefits of Oauth 2.0 for APIs. It must trust it though. It should confirm the token has been signed by the auth server, and it may also need to be able to decrypt the token, if encrypted by the auth server.
Obviously the resource server needs to be able to access the data for the user in the token. It may be that the auth server and resource server point to the same underlying database.
Access token is usually a randomly generated string, so you cannot read any information out of it (but there may be OAuth2 implementations that use some meaningful values). The resource server must validate the access token and its scopes, not the permissions of the user who was authenticated before creating the token (resource owner). That's an important detail, because OAuth2 is a protocol for permission delegation from a resource owner to a client in form of an access token and its scopes. To do that, the resource server needs to make an HTTP request to the Token Introspection endpoint of the auth server. The JSON response contains
Boolean flag active that says whether the access token is still valid (not revokend, not expired)
Parameter scope holds its scopes granted by the resource owner
username of the resource owner
Some other useful fields.
The resource server should check that the access token is active and that it contains scopes required by the requested resource or service. It may perform some other validations (such as the requested resource is owned by the resource owner identified by the username field).
The introspection response for a given access token may be cached by the resource server (to improve performance). See the RFC for security considerations.
Access token may self-contain the authorization information in a verifiable manner (for example signed JWT). In such case, the resource server should be able to verify the authenticity (signature) and scopes of the token without calling the auth server, but then it's hard to implement the token revoke endpoint, since the resource server would accept a token even if it gets revoked at the auth server.
It can be complicated. There are many different implementations and combinations relationships between the User, Application and Resources.
Perhaps a more descriptive explanation of your architecture and relationships between the entities involved would be helpful.
If you are trying identify the User, then OAuth is not the correct protocol. YOu should look into OpenID Connect or User-Managed Access.
Generally the Resource server would only need to know the scopes to be able to provide access. Not the Identity of the user.
-jim
Related
When setting up Azure AD B2C authentication using the Microsoft Identity Platform there is an option to store and return custom claims for a user. The question is specifically about when developing a .NET Core Web Application that uses an App Registration to log users in.
EDIT: In this scenario, the web app does not call a downstream API - There is a single web app (MVC), the user authenticates against AAD B2C, they use the web app and the controllers on the back-end use an Authorize attribute
You can define a custom attribute "TeamId" and return that as a claim to the application that a user logs into - It will be in a claim called "extension_TeamId" in this case and available on the ClaimsPrincipal.
Is it safe to use the value in that claim to determine which tenant a user belongs to, or is it possible for that value to be spoofed by the user, making them appear to be within another tenant - I would class this as authorization information which Microsoft states you should never retrieve from an ID token, only an Access Token:
ID tokens are issued by the authorization server and contain claims that carry information about the user. They can be sent alongside or instead of an access token. Information in ID Tokens allows the client to verify that a user is who they claim to be. ID tokens are intended to be understood by third-party applications. ID tokens should not be used for authorization purposes. Access tokens are used for authorization. The claims provided by ID tokens can be used for UX inside your application, as keys in a database, and providing access to the client application.
https://learn.microsoft.com/en-us/azure/active-directory/develop/id-tokens
The alternative is to store the data in a table that links a user to a team, where the users B2C ID (Guid) is used to lookup their assigned team from the DB first, rather than taking it straight from their claims and looking up info about that team.
I may be getting confused between ID Tokens and Access Tokens and want to understand what the Microsoft Identity platform is returning in this case. Is the token sent from the .NET Core Web Applications front-end to the backend an ID Token or Access Token?
The ID Token returned informs the receiving client application details about how the user authenticated and who he is. From the ID-token, the local "session/identity" is then created. The ID token is not meant to be passed around to other services and typically it has a very short lifetime.
The received access token is used by the receiving client to get access to APIs and resources. The client application should not need to look inside the access token.
The claims in the ID-token (optionally with the claims from the UserInfo endpoint) ends up in the local user session and can be used to authorize various features in the client application.
So, yes claims from the provider can be used to authorize the users, but you need to understand the different use cases for the ID and access token.
I have a web application in C# through which I'm trying to get access token for Microsoft Graph API. I'm able to get tokens through using Client secret, but don’t want to get the token by using the client secret but get the token by other means, want to get tokens without client secrets.
I'm successfully getting the tokens using secrets and have stored them in KeyVault but getting an alert for "Explicit Credentials are being used for your application/service principals", so require some alternative to get tokens.
Is there any way to get tokens without secrets. Any help would be great.
One can use ROPC oAuth grant based on username and password instead of using Client Secrets to get access tokens. Microsoft identity platform supports the OAuth 2.0 Resource Owner Password Credentials (ROPC) grant, which allows an application to sign in the user by directly handling their password. Refer, https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth-ropc
Warning:
Microsoft recommends you do not use the ROPC flow. In most scenarios, more secure alternatives are available and recommended. This flow requires a very high degree of trust in the application, and carries risks which are not present in other flows. You should only use this flow when other more secure flows can't be used.
It is not a recommended way to use without client secret since due to security concerns.
If you still don't want to use client secret go with implicit grant flow which we can easily implement on the front end by maintaining SPA and passing token to the backend
When creating a WCF service application I've implemented UserNamePassValidator for custom authentication and this works as expected.
But due to the large amount of functionality on the service, I've decoupled this into different service contracts such as a stock management service, location management service, task management service etc. and I've then exposed these on different endpoints within the same service.
This seems to work fine, however what I would prefer is to authenticate with one endpoint and have this session state maintained across all of the endpoints. At present what happens is I authenticate to one, I can then access the functionality of that service contract but if I was to connect to another endpoint it requires me to authenticate again.
My current crutch solution is to pass the ClientCredentials between forms on the client side for authenticating, and although it's using Message security so they're encrypted over the wire this is obviously not an ideal solution.
Is there a solution to first part? And if not, what's the best practice for storing user entered credentials in memory (during runtime) at the client side.
You can implement a scheme similar to WS-Federation. It is kind of Federated Security for service level.
Firstly, your Authentication endpoint should be called STS (Security
Token Service). What it does is authentication and return a security
token to the client.
Secondly, STS should be trusted by all the Service Endpoints. When
invoking the endpoints you should pass in the security token that STS
provided so that the endpoints will be able to read that token and
recognize that the token was issued by a trusted STS.
I have implemented one with Thinktecture at https://github.com/khoanguyen/Test-WS-Federation but sorry that I didn't give explanation you will need to research a little bit about WS-Federation and Thinktecture and WIF. But you should know that it is possible to do.
A lightweight solution that I am using for REST services for mobile project is below:
I set up a Authentication endpoint. That endpoint hold a DSA private/public key pair. When client is authenticated, this endpoint generate a token and sign it with DSA private key. Then I combine the signature and token together and return it as a security token to the client.
At the service endpoints, I gave them the DSA public key (from the key pair of Authentication endpoint). The DSA public key is for verifying the security tokens.
When client call the service endpoints, it attaches the security token as a Header of HTTP message. Then, the service endpoints read the header to retrieve the security token -> extract the token and the signature from the security token -> use DSA public to verify it.
The strategy for generating the token depends on your need. In my case, my token contains client's username, expiration timestamp. By using DSA, the hacker can extract all the token's data but they cannot alter it because they must have the DSA private key to sign the altered token. Our job is just keeping the private key in secret and don't leave any sensitive info (e.g password) in the token.
This is very cheap way. I don't need to access DB to verify user, just ensure got a valid security token, token's data is just for extra need, you can even generate a random token and sign it. No session state needed.
Note: This is not about coding, but about the approach itself.
I'm making a client for a website which uses OAuth 2.. Since this is my first time using oauth 2 I have some problems in understanding the approach. As I know until now:
I should send my access token with every request. To get this access token in the first time I send user to the website and after login I get an authorization code. Then I send this authorization code and my client_id and client_secret to get the access token and finish.
until here every thing is fine. But in the next application execution, I don't know what to do. I don't want to ask user to login every time. But how can I know my access token is still valid?
should I save my authorization code and request a new access token again?
I request a non-expiring access token, but to refresh the access token I should send some refresh_token? What is this? Should I send the old access token as this?
#Eugenio's answer is correct.
To answer your specific questions
But how can I know my access token is still valid?
The access token comes with an expiration time, usually one hour. The other way is to try to use it and catch the 401 status if it's expired.
should I save my authorization code and request a new access token again?
No. The authorization code can only be used once. You can either request a refresh token, save that, and then use that to get subsequent access tokens, or you can repeat the authorization process, which depending on the provider, may or may not require user involvement since the provider will know that the user has previously authorized your app.
I request a non-expiring access token, but to refresh the access token I should send some refresh_token?
There is no such thing as a non-expiring access token. You use a refresh token in order to obtain a new access token.
What is this [refresh token]?
It's a string that your app can pass to the provider to say "hey it's me again. Remember a while ago user xxxxx, granted me, application yyyy (client id), the authority to do aaaa and bbbb (scopes) on his behalf, even when he's not present. Well I'd like to do some now so please can I have an access token".
Should I send the old access token as this?
No. Once an access token has expired it has no use or significance at all.
The access_token you get from the authentication site is good to call their APIs, not your app. You should keep it if you need to call them back eventually in your app.
For example, if your users are authenticating with Facebook, the access_token you get will be good to call Facebook's endpoints.
OAuth2 is in essence an authorization protocol: the user is granting you permission to access his/her information on their behalf.
A commonly used, and useful side effect of this process is to treat these users as "authenticated" because, presumably, you can only get an access_token from a legitimate user.
It is then up to your site to establish a session with them. You would do this exactly as you would if you were authenticating the user yourself, likely after you successfully retrieved the access_token using the code. (or sometimes after retrieving the user profile from the Authorization Server, another common technique).
You can browse a sample that does this on the .NET platform here: https://docs.auth0.com/aspnet-tutorial (this is configured to work with our own OAuth server, but the principles are generic).
The code this sample relies on is available here: https://github.com/auth0/auth0-aspnet
I want my web server code (invoked from ASP.NET MVC3 site's controller) to be able to save files to Dropbox account.
I have examined two out of three .Net/Dropbox libraries and all of them require a user to "authenticate" via web-redirect to Dropbox to get a token.
Examined libs are Spring.Social.Dropbox and DropNet.
Can this authentication and upload be done via purely .net code without messing with the user's browser? Can the acquired token be saved for later use? This is theoretical question, not about particular implementation.
This is a bit of a complicated subject. As far as I know Dropbox uses OAuth, which is an authentication and authorization protocol.
General process is this:
You create authorization request token
User gets redirected, authenticates and grants permissions to your app.
You trade the request token for an access token
You must save the access token because it is used to perform actions on the users behalf
Access tokens don't usually expire and only stop working if a user revokes your application permissions.
This means the user will have to authenticate and authorize your application at least once so you can get the access token and access token secret.
After that, you are pretty much free to perform actions on the users' behalf based on the permissions granted. You must specify the access token attained by the above-mentioned process in order to perform actions.
In short, get an access token, save it, use it for requests.
Does this clarify it a bit for you?