Should backend require a "user_id" along with the Refresh Token? - oauth-2.0

Is it safer to have the client send an additional field like their "user_id" alongside their Refresh Token? This way the server could retrieve data using both fields, making it harder for a malicious user to target any refresh token (since they'd have to match a specific pair).
I feel like I remember reading something similar on the oauth2 rfc.

Related

How can I identify a user correctly during a refresh_token grant?

I have a central 'hub' containing the data for multiple organisations, each of which contain multiple users. Organisations and users are grouped together, along with 'client_credentials', under a 'Project'.
The user can authenticate using the 'password' grant type, and they obtain access & refresh token, as per the OAuth2 spec. Both are JWT.
The issue I have is correctly attributing the refresh token withe the relevant user in the 'correct' way so that I can issue a JWT access_token with the correct content.
When requesting the original tokens, I pass and validate both the client credentials and the user's username/password. Two identical (other than expiry time) tokens are generated containing the user_id and other bits. One for access, one for refresh.
So when validating the refresh token, I see (unless my understanding is wrong) a few ways of making this happen:
On the initial request, store the refresh_token against the user's database record, and do a lookup based on the association with the client credentials as well as this stored token. OR:
Generate the new access token from the unpacked refresh_token, just with a new expiry date - meaning I don't need to actually persist these things.
In some ways, the first approach seems ok, apart from my reluctance to perform database queries using any type of password/token, as typically I'd never index these fields.
And in other ways, the second approach seems ok as it doesn't actually require me to persist sensitive tokens unless I explicitly want to mark it for revocation - but it does somewhat require that the access_token and refresh_token are kept pretty much the same.
Any steer on which is the 'correct' approach, or does anyone have any alternatives?
Using the Password Grant type, you are generating/receiving two tokens: Access Token and Refresh Token. These tokens should be stored securely either in a memory table in your application or in a database. If you are using an autoscaling or fault-tolerant design, you need to use a database.
Once you have the tokens, you create an opaque random number (usually 128-bit, sometimes 64-bit), let's call it AUTH_ID. The tokens plus expiration are indexed by this AUTH_ID. You store the AUTH_ID in the client browser's session or return with the tokens. If there is a design already in place, then you will need to create a method to search the database to match the tokens passed to you. If the user does not actually require tokens, give them the AUTH_ID instead.
When the client makes a request to you, extract the AUTH_ID from the client session and lookup the tokens. If a token will soon expire, refresh it and store the new token. Then continue with the client's request.
The contents of a Refresh Token is implementation-specific. This means that if you want to rely upon information about a Refresh Token (or an Access Token) you must store that information alongside the token. Some tokens are Signed-JWT, some are Opaque.

OpenID Connect, oAuth2 - Where to start?

I am not sure which approach I should be taking in our implementation and need some guidance.
I have a REST API (api.mysite.com) built in the Yii2 Framework (PHP) that accesses data from mysite.com (database). On mysite.com our users will be able to create Connected Apps that will provision a client id + secret - granting access to their account (full scope?).
Based on my research, the next step seems to be setting up something to actually provide the bearer tokens to be passed to the api - I have been leaning towards oAuth2, but then I read that oAuth2 does not provide authentication. Based on this I think I need OpenID Connect in order to also provide user tokens because my API needs to restrict data based on the user context.
In this approach, it is my understanding that I need to have an Authentication Server - so a few questions:
Is there software I can install to act as an OpenID Connect/oAuth2 authentication server?
Are there specific Amazon Web Services that will act as an OpenID Connect/oAuth2 Authentication Server?
I am assuming the flow will be: App makes a request to the auth server with client id + secret and receives an access token. Access token can be used to make API calls. Where are these tokens stored (I am assuming a database specific to the service/software I am using?)
When making API calls would I pass a bearer token AND a user token?
Any insight is greatly appreciated.
your understanding is not very far from reality.
Imagine you have two servers one for Authentication, this one is responsible for generating the tokens based on a Authorization Basic and base64 encoded CLientID / ClientSecret combo. This is application authentication basically. If you want to add user data as well, simply pass username / password in the post body, authenticate on the server side and then add some more data to the tokens, like the usernames, claims, roles, etc
You can control what you put in these tokens, if you use something like JWT ( Json Web Tokens ) then they are simply json bits of data.
then you have a Resource server, you hit it with a Authorization Bearer and the token you obtained from the Authorization one.
Initially the tokens are not stored anywhere, they are issued for a period of time you control. You can however do something else and store them in a db if you really want to. The expiration is much safer though, even if someone gets their hands on them they won't be available for long! In my case I used 30 minutes for token validity.
Now, you haven't specified what languages/frameworks you are looking into. If you use something like dot net then look into IdentityServer, version 4 is for Dot net core, 3 for anything below.
I also have a pretty long article on this subject if you are interested:
https://eidand.com/2015/03/28/authorization-system-with-owin-web-api-json-web-tokens/
Hopefully all this clarifies some of the questions you have.
-- Added to answer a question in comments.
The tokens contain all the information they need to be authenticated by the resource server correctly, you don't need to store them in a database for that. As I already said, you can store them but in my mind this makes them less secure. Don't forget you control what goes into a token so you can add usernames if that's what you need.
Imagine this scenario, you want to authenticate the application and the user in the same call to the Authorization Server. Do the OAuth2 in the standard way, which means authenticate the application first based on the client id / client secret. If that passes then next do the user authentication. Add the username or userid to the token you generate and any other bits of information you need. What this means that the resource server can safely assume that the username passed to it in the token has already been validated by the authentication server otherwise no token would have been generated in the the first place.
I prefer to keep these two separate myself, meaning let the AS ( Authorization Server) to deal with the application level security. Then on the RS (Resource Server) side you have an endpoint point like ValidateUser for example, which takes care of the user validation, after which you can do whatever you need. Pick whichever feels more appropriate for your project I'd say.
One final point, ALWAYS make sure all your api calls ( both AS and RS are just apis really ) are made over HTTPS and never ever have any important information transmitted via a GET call which means the URL can be intercepted. Both Headers and POST body are encrypted and secure over HTTPS.
This should address both your questions, I believe.

IdentityServer3 - Add token inside token for custom grant type (act-as schema)

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.

Returning a refresh token with the resource owner flow

I have created an authentication server that implements OAuth 2 for authorization and it also provides local password authentication using the resource owner flow.
At the moment I always return a refresh token along with the access token which was an acceptable thing to do when I first implemented the feature. However now I need to implement a remember me feature in the client that uses the server. I could always just save the refresh token in the client when the user ticks the remember me checkbox but the token would still exist on the server and be usable even though the user didn't want it to.
What I want to do is simply pass a parameter along with the request that tells me whether I should create a refresh token or not.
So my question is. Is there some standard or recommended way of doing this using the fields provided in the spec or is it acceptable to simply add a parameter to the request to handle this use case?
AFAIK, there is no standardized way to choose whether to issue a refresh token or not.

ASP.NET MVC 3 Web API - Securing with token

I'm trying to find the simplest way of implementing token based authentication for a number of ASP.NET MVC actions.
The Api controllers sit alongside a web app, so I need to be able to specify which actions/controllers are subject to Api authentication.
I already have a membership provider that is used for forms authentication so I'd like to reuse this to validate the user and build the returned token.
I've read several articles on implementing OAuth, but most seem really complex. I've seen several examples of using an API key, but I want to request a token and then pass it back as a parameter not necessarily as a value in the HTTP header.
Essentially process needs to be:
User requests token from auth action passing in username and
password.
Service returns enc token
User passes enc token to future calls as a parameter to auth
What's the typical way this is done, does the client (say ajax call) need to compute a hash of the user name/pass in 1)? or plain text ok over TLS/SSL?
Any advice appreciated.
What are you concerned about with what you described?
The process you described seems viable. Typically systems will have an expiration on how long the token will be valid for, after which they need to get a new token. There are many variations for expiration though (fixed time, sliding time, etc..).
To your question regarding the username / password, the client shouldn't hash them. Just make sure they are transmitted via a secure method (SSL).

Resources