Oauth 2 with Client Credentials Flow - Is it safe to assume subject will always be null? - authentication

I have an API which takes access tokens which can be provided by either Implicit or Client Credentials grant types.
It would be useful for me to know, by inspecting the access token, which grant type is being used (It will allow me to make some optimizations in our authentication code).
What I have read here: https://github.com/IdentityServer/IdentityServer3/issues/76
suggests to me that if the subject isn't provided in the access token, it can be assumed that it's the client credentials flow. At least with Identity Server.
My question is, is this a safe assumption to make, regardless of the Authorization Server?

Related

Refresh tokens: security & implementation

When a user is authenticated by the server, the server sends, according to the most common implementation I found(which is were my question stems from), sends BOTH access token and the refresh token to the client.
-- My first questions is:
What is the point of sending both tokens to the client if, to my understanding, we have the refresh token in the first place to help us mitigate the consequences of an access token being leaked?
If both tokens are sent to the client and are stored together (in the same place, localStorage, sessionStorage, one in former, one in latter - I don't think it matters to the questions how we decide to store them on the client), if an attacker manages to steal the access token, then it is safe to assume he would also find a way to steal the refresh token from the same client since they are most likely stored together. I don't understand why most implementations and answers I find online mention sending both tokens to the client since its basically like putting all eggs in the same basket.
(A big part of my confusion comes also from the fact that those answers and implementations don't mention anything about storing the tokens in HttpOnly cookies, which I'd think would be a common practice if we want to prevent tokens getting leaked, so I'm getting a feeling I'm missing something)
-- My second question would be:
Would it be a correct solution then to persist the access and refresh tokens upon issue in an "accessT <-> refreshT"(like a key=value pair) table on a server, so that only one token is ever sent to the client - the access token? And when that access token expires the process of "refreshing" would be the following:
ResServer = resource server
AuthServer = authorization server
The request with the expired token is sent to the ResServer.
ResServer checks and sees that the access token has expired.
ResServer then sends a request to the AuthServer to look up the refresh token by the access token in the table mention above.
If AuthServer finds a refresh token by using the expired access token as a key - good, AuthServer generates a new access token.
AuthServer then responds to the ResServer with that new access token.
Having received a positive response, ResServer proceeds on with it's usual flow for authorized users.
^^ This seems to me to be a more rational way of keeping the refresh token safe - making it serve its primary function, which is why I don't understand why most other implementations on the web always mention sending both tokens to the client.
-- And my third question is:
Not having much experience implementing microservices, I am confused about why we would ever prefer to implement this token back and forth approach, when, from what I understand, the entire point of tokens is that they are supposed to be a stateless solution(well, the refresh token is always kept on the server regardless of implementation, which confuses me even more about that "stateless" part). Doesn't it make more sense to just use cookies that basically serve the same function, but are easier to implement, secure by default("Secure", "HttpOnly" flags), and, as it appears to me, are much easier to revoke in can they are leaked?
Thanks you for taking your time to read this entire post, I appreciate your help.
Regarding your first question:
The advantage of having two tokens is not that you can store one of the tokens more securely. The advantage is that if the Resource Server gets compromised, it does not allow lateral escalation. For this to make sense, your access tokens must be bound to specific resource servers.
As an example, assume you have two resource servers ResA and ResB. Then your Authentication server would allow you to obtain one access token for each of these servers, and one refresh token (that allows refreshing both access tokens). If resource server A gets compromised (or the network path between the client and that server), then the access token to that server will expire at some point, and the attacker will not be able to access resource server B with the access token issued for resource server A. At the same time, only the legitimate user is able to refresh their tokens, since they only provide the refresh token to the AuthServer, such that a compromised or malicious resource server never sees at.
That leads directly to your second question:
Your proposed model prevents key rollover. If a resource server gets compromised, all its tokens are eternally compromised, unless the Authentication Server voids all refresh tokens. Voiding refresh tokens would lead to users being logged out of all resource servers (even those who are not compromised).
As an example, consider the following scenario: Tour authentication provider is a large public service, such as "Sign in with Google", with thousands of resource servers using this service. Now one of those resource servers gets compromised, and attackers steal the authentication tokens.
In the commonly employed auth-refresh token pattern, the auth tokens will expire, which means that the service will be inaccessible for attackers as soon as the used vulnerability is fixed + the time it takes for tokens to expire (since the attackers could not get hold of the resource tokens), without the need for the AuthServer to do anything. Additionally, the AuthServer does not need to keep track of the issued tokens, if it uses cryptography to sign the tokens with a private key only known to the auth server, as it (and all resource servers) can trivially verify token authenticity by validating against a public key (please also see the end of my answer).
In your proposed approach, the AuthServer (which is Google in this example) would have to void all refresh tokens OR they would have to selectively delete all auth-refresh token pairs for the affected resource server from the key-value store. That key-value store will be gigantic, since it has to contain EVERY auth token ever issued, for any service that uses "Sign in with Google", and apart from storage costs, this delete operation will take quite some time.
Regarding your last question:
You can store access tokens in Cookies. There is a bunch of advantages to that (including the Secure and HttpOnly flags that you mentioned). It has two disadvantages: If you want to implement something like a CLI client that runs outside of a browser, you would have to implement Cookie handling. The other disadvantage is the CSRF risk as Cookies are automatically sent on every request. Using local storage prevents this, as an external website cannot access the local storage of your website to extract the token.
In the end it comes down to the concrete scenario, if Cookies or Local Storage + Custom Header are the preferable solution.
However, I think you have a misconception regarding statefulness:
Access and Refresh tokens do not need to be stored on the server. Instead, the Auth Server signs the Token Contents with a cryptographic private key, before sending them to a client. In doing so, the AuthServer includes an expiration date in the token, which is included in the signed content.
To validate the token, the Resource Server (or the AuthServer) checks if the signature comes from the AuthServer's private key, and then checks if the expiration date has passed. In particular, the resource server does not need to communicate with the AuthServer, apart from obtaining its Public Key from time to time. This makes this solution scale really well for very large deployments. See the Microsoft Azure docs, which do a great job on explaining the difference between Auth and Refresh tokens.
What you are alluding to are traditional session ids, which are stored on the server until they expire. Thats obviously a much simpler solution, and works well for smaller, more monolithic applications. It just does not work for hyper scalers.

Implementing public API keys with microservices

For most client applications and UI approaches JWTs seem to be a good way to carry tokens for an OAuth based approach. This allows decoupling of a User/Auth service and the services that are actually being accessed.
Given this architecture
My question is: in the case of public APIs (ie Github or Slack) where a bearer key is generated with specific roles. How is that key authorized in a microservice architecture? Do those types of keys just require that the Auth service gets queried with every request?
Could an API gateway mitigate this? I would like to understand if a solution exists where there is minimal communication between services. Thank you!
Normally, this is solved using scopes. The scopes are permissions given to a user to do certain operations,for example there will be a scope for read a repository, another for update it, another one for delete etc..
These scopes are tied to the token and normally are requested by the user himself or added automatically depending on the user type. And the same as the authentication process, they could be included in the token itself coded as a claim in a jwt or they could be requested or checked by calling an oauth server when one operation is requested.
The advantages of include them in jwt is that there is not need to call an external server every time an operation is requested so there is a lower latency and less bandwith is required, also you remove a point of failure. Obviously if this solution is used the token must be properly signed or even encrypted to avoid possible manipulations.
However it has also drawbacks, and the most dangerous one is that the token cannot be revoked because this information cannot be included in the token and the service that check if the token is valid only can access the data contained in the token itself. Because of this, this kind of tokens are normally issued with a little expiry time so in case of the token is stolen, the validity of it will be very limited

In token-based authentication, how does the application server know which tokens are valid?

I'm trying to understand cookie vs token-based authentication. I get the basics - cookies have to be stored in the server (as well as the client) to be verified each time, whereas tokens only have to be stored on the client-side. The server simply decodes any incoming tokens and verifies the request.
What I don't understand is, how does the server know whether any decoded token is valid, if a list of valid tokens isn't being stored anywhere in the server?
https://dzone.com/articles/cookies-vs-tokens-the-definitive-guide
User enters their login credentials.
Server verifies the credentials are correct and returns a signed token.
This token is stored client-side, most commonly in local storage - but can be stored in session storage or a cookie as well.
Subsequent requests to the server include this token as an additional Authorization header or through one of the other methods mentioned above.
The server decodes the JWT and if the token is valid processes the request.
Once a user logs out, the token is destroyed client-side, no interaction with the server is necessary.
To be specific - I'd like to know how #5 works. Thank you.
A full answer to your question would be very long, but here is my attempt at a brief one. The server also happens to be the entity which issues the JWT in the first place. As such, it possesses a key which it used to sign each outgoing JWT. As a result of this, when the server receives an incoming JWT, it first tries to open/unlock that JWT using its private key. If the JWT were tampered with in any way, the server might not be able to open it properly, and it would result in an exception. As an example of one sanity check the server would perform against an incoming JWT, it would observe the checksum of the JWT, would not pass in the case of tampering.
Once the server has opened the JWT and deemed it to be valid, the next thing it would likely check would be the exp claim, one of possibly several claims which are contained within the JWT. The exp, or expiry, claim, records for how long the JWT is valid. Should a user present a stale JWT, the server would immediately reject the JWT as being invalid.
So far, we have been discussing checks the server may perform using no state, that is, relying only on the state contained within the JWT itself. In reality, most of the time the server would in fact be storing some state of its own. As an example of why this might be necessary, consider the edge case of a user who logs out of the site or app. In this situation, his phone or browser would still be bearing a JWT with a valid exp expiry. In order to prevent the user from continuing to use this JWT, the server might maintain a blacklist of JWT which it will not honor, even if the exp and checksum pass inspection. So, a third step after unlocking the JWT and checking exp might be to make sure that the JWT does not appear on the blacklist.
A good JWT implementation can limit the amount of server side state to something very small, but typically the server would actually maintain some state of its own.

How to get identity in API using OpenID Connect

I'm trying to follow OpenID Connect best practices. For the simple scenario of calling API from application the OpenID Connect suggest to pass the Access Token (which is not included user identity), and if the API in some points need the user identity it should call /userinfo endpoint of OpenID Connect provider.
So the question is: Is it the best way to get the user identity in API?
Assume I have an end point named CreateOrderForCurrentUser() so each time any user call this api I need to call the /userinfo endpoint, it seems too much cost for calling an api.
Why I don't pass the Identity token to the API?
Or Why I don't put some identity claims in Access token?
Should I use HOK Token instead of Access token?
Any idea please.
It seems here is kind of same as my question: Clarification on id_token vs access_token
And he respond in comments: https://community.auth0.com/t/clarification-on-token-usage/8447#post_2
Which as my understanding means: put some identity claims in Access token (Custom Claims) and rely on that in the API.
But still it doesn't make sense. The OIDC insist to not use Access token as Identity and now we are going to add identity claims inside Access Token. Could any one clarify that?
ID_Token is used for your client app tells the app who you are , the audience of the ID Token is the id of your client app , with access token , API/resource knows whether authorized to access the API and perform specific actions specified by the scope that has been granted.
By default , it will include user identifier in access token(sub claim) , so you should know which user when calling CreateOrderForCurrentUser function . You could customize the access token to include more user related claims if needed . But i would suggest to simplify the access token , and you could use access token to acquire user information by invoking user's API endpoint .
I asked the same question in Auth0 Community and there is a discussion about it that might be helpful for others who have the same issue.
I copy the same answers here:
markd:
You are correct that you should not use an access token as proof of identity, but before you get to your API you should have already authenticated the user and received an id_token for them. If you have already authenticated the user via OIDC, as far as I know there’s nothing wrong with adding custom claims to the access token to pass data to your API. Your API could also use the client credentials grant type to pull data from Auth0.
Me:
I’m looking for the best practices. I want to be sure adding identity claims to the access token and rely on that in API does not broke any thing and is based on best practices or maybe the best practice is always call the /userinfo endpoint in API and don’t rely on Access token identity claims.
The API doesn’t know about the authentication process and don’t care about that. Any one any how pass the signed Access token to the API, it would be accepted. Now in API point of view is that proper way to rely on identity claims in Access Token? I have doubts. But I would be happy if we could ignore calling the /userinfo end point each time.
jmangelo:
I can share some (hopefully) informed views on this subject, but please do take them with a grain a salt and question stuff you disagree with or you don’t consider clear enough. When it comes with software the devil is on the details and in the security landscape it’s even more true so you need to consider best practices as what will likely be recommended for the majority of the scenarios and also what will likely be less risky; it does not mean that nothing else is possible.
For example, although the recommendation is indeed to use access tokens in requests to API’s this does not mean that there isn’t a specific scenario where technically it would also be okay to send an ID token instead.
Focusing on your particular questions and starting with the last one (3); we should not compare HOK and access tokens because they are not at the same level. In other words, you could question if in your scenario you should use bearer tokens or HOK tokens as this way and using the terminology of your linked page you would be choosing between two token profiles where each give you different characteristics.
At this time, the access tokens issued by the Auth0 service as part of API authorization are bearer access tokens so this question has only one answer if using the Auth0 service.
Jumping to the first question; it’s not that you cannot pass the ID token to the API, it’s just that the scenarios where that would be adequate are much more constrained. For example, an ID token is issued with the client identifier as the audience; it’s common to have multiple client applications so you have just coupled your API to how many client applications you have, because assuming you will validate the audience of the ID token, your API would now need to know the identifiers of every client.
For question (2) which I assume is also interested in why call /userinfo if you can include claims in the access token. I believe this can depend a lot on requirements and/or personal preferences. At this time the only format supported when issuing an access token to a custom API is the JWT format.
The above means that you have a self-contained token that once issued the API can mostly validate independently which is great in terms of scalability because the API does not need to make (frequent) external calls for validation purposes.
However, being self-contained this immediately means that any data you include directly in the token will be considered the truth for the lifetime of the token itself. If instead the API is calling /userinfo or even the Management API directly then you ensure fresh data at the cost of network overhead.
In conclusion, in my personal view the choice between network calls and embedded claims is more tied to the characteristics of the data you are interested in that just from a best practices point of view.
As a final note, even without any addition of custom claims an access token issued by the service in association to a custom API already conveys user identity. In particular, given the access token is a JWT, the sub claim will contain an identifier that uniquely identifies the end-user that authorized the current application to call the API on their behalf.

how to use and store token from oauth2 to do authentication

sorry if this is question is too broad, but I have to ask this since I'm learning web development and I feel if don't ask I won't know.
So, I'm doing authentication using oauth2, and right now I'm already at point where I successfully authenticate user, and now I'm receiving what they call tokens. The question is, how do you use token to authenticate user to your own server?
I'm thinking something like creating a cookie that maps to a token, so when user acts, each time I'll get a cookie and I know that this is user A. Is method like this safe or not? If not, in what way people usually use the token? Although this is only a hobby project, I'd like to be "as real as possible". Any thoughts?
As per my knowledge Oauth2.0 provides InMemoryTokenStore and JdbcTokenStore for persisting tokens. When a request comes from an authenticated user Oauth2.0 will check if it has a valid token already. In case it doesn't it will create one.
Basically usage of tokens depends on the grant-type you are using . Following are the two commonly used grant types -
1) Implicit - The token is send back in the url as a parameter and is included in the subsequent request* in the parameter.
2) Authorization Code - In this case the token is generated and set in the header of the request*.
*the request here is the one which is finally sent to resource server for accessing protected resources.
I think you dont need to create a cookie for storing tokens. In case you are using Authoziation Code grant type which is the default, Oauth2.0 will use session for storing state and code which will be used for retrieving token.