It's a know problem that Instant Flow struggles from confused problem, so you have to check whether access_token you received was given to your application.
I always considered it's not a problem for Authorization Code flow but in this answer it was mentioned it is not so and you have to verify token even in Authorization Token flow.
But honestly I can't figure out a workflow where it's necessary. Like we receive a code and then make direct request for a token (specifying client_secret). I don't understand how we could be forced to use a wrong token in this flow.
The answer that you refer to talks about an access_token delivered to a Resource Server. That is also in general where the "confused deputy" issue applies.
In your post you refer to the Authorization Code delivered to the Client. That is different and does not suffer from the same confused deputy attack as described.
It should be noted though that the Authorization Code grant type may be vulnerable to a related attack ("Authorization Server Mixup") if the Client talks to multiple Authorization Servers (AS) somewhat for the same reason: the Client is not able to detect if the Authorization Code is actually issued by the AS that it thinks it talks to. Registering a Redirect URI that is specific for each AS addresses this.
Related
I have a few concerns with an OpenId Connect strategy that I would like to use and have been unable to find specifics on what the security concerns may be and any glaring issues with it I am overlooking.
Currently, I have an OpenId Connect implementation using Openiddict with Authorization Code flow. For the client, I have a React-Native app using react-native-app-auth.
I see from other questions on SO and from issues posted on the Openiddict repo that the recommended approach to third-party providers (e.g. Google) is: Client -> Auth server -> Google Auth -> Auth server -> Client/Auth server code and token exchange
However, it seems that a better approach from a UX standpoint (when using a SPA or native app) would be to implement something similar to GoogleSignIn on the client and either handle the identity on the server using an IdToken or authorization code from Google. This introduces an issue as the flow previously recommended could not be used as the entire initial challenge and redirect from Auth server to Google Auth has been skipped.
I have seen that this issue is mitigated by not using the authorization code grant and instead implementing a custom assertion grant. This seems to be an alright approach but would require exposing a custom grant and handling the flow differently on the client and server for local and third-party logins.
My proposed solution continues to use the authorization code flow and instead of adding a custom grant type the client could just pass a third-party identifier "Google" and the token or authorization code in the additional parameters of the OIDC authorize request. The authorize endpoint could then detect the provider and token, perform token validation, create a user or principal from it, and create an authorization code to send back to the client for the code/token exchange. This flow would look like the following:
1. Get the id token from the provider Client -> GoogleSignIn -> Client
2. Pass token to auth server and initiate code / token exchange Client -> Auth Server -> Auth server Verify Google IdToken (JWKS, issuer, audience, provider specific validation, etc...) or exchange auth code -> Auth server -> Client/Auth server code and token exchange
One downside to this approach would be the additional hops to verify the token on the server side. If the token was returned from GoogleSignIn, they themselves said that it could be trusted. https://developers.google.com/identity/protocols/oauth2/openid-connect#obtainuserinfo
I see that it is generally recommended to place the auth server between the client and the third-party but in this process the server is still between the client and auth server but only after the initial exchange from the client and third-party.
Questions,
In general am I missing something with this flow?
In this case would it be necessary to verify the token on the server side?
Is there some better way to approach this that I have completely overlooked?
Am I making this too complicated and UX should not be this much of a concern?
Instead of adding the provider and token to the additional parameters would it make more sense to pass it in the body of a post request? I don't see the issue with passing it via query string but that's also part of the reasoning for the authorization code grant from my understanding.
Apologies in advance for anything I have missed or omitted for brevity that should have been included.
Thanks.
ARCHITECTURE
I'm not sure I understand the UX problem - your existing architecture feels really good. If you want to login directly to Google, just send an acr_values=google query parameter in the authorization redirect, to bypass any authentication selection screens. The exact value will depend on how Openiddict represents the Google authentication option, and some providers use a non-standard parameter such as idp. Have a closer look at the OIDC request parameters.
A key OAuth goal is that the Authorization Server (AS) - Openiddict in your case - shields your apps from all of the provider differences and deals with their nuances and vendor specific behaviour. Your apps then also only receive one type of token, and only ever use simple code. As an example, the Curity AS supports all of these options, none of which requires any code in applications.
APPAUTH AND UX
If a user is already signed in then it can, as you say, look unnatural to spin up the system browser and them it is dismissed immediately.
A common option is to show the consent screen or an interstitial page to keep the user informed - and the user clicks one extra button. This can also be useful for getting password autofill to work. My code example and blog post shows how this might look, though of course you can improve on my basic UX.
OFFLINE ACCESS
I find this term misleading, since refresh tokens are most commonly used when the user is there. Are you just asking how to deal with tokens in a mobile client? Aim for behaviour like this:
Standard messages for API calls with access tokens in an authorization bearer header
Standard refresh token grant messages to refresh access tokens - eg as in this code
Note also that mobile apps can save tokens to encrypted secure mobile storage that is private to the app. This can improve usability, eg by avoiding logins every time the app is restarted. You should think through scenarios such as stolen devices and token lifetimes though.
I have seen different solutions when building JWT-based authentication systems between react and node. There are many examples, and many of them use different headers.
What is the difference between headers
Authorization
x-auth-token
x-access-token
and when should they be used? For example, in this answer is explanation that Authorization would be the one to be used. However, as stated in another answer here which is linking to here it states that "The Authorization header is usually, but not always, sent after the user agent first attempts to request a protected resource without credentials."
Which leads to conclusion that when making the request for some protected page behind login, one should not use Authorization header at once, only after it has first been rejected.
Thus, what is the "correct" way of doing the checks, and with which protocol?
For example, should one start with x-auth-token in header when logging in with client -> server, and to requests after that use x-access-token, and if failed then use Authorization token?
I know, typically only one of them is used, and in many cases it seems that Authorization is the correct way, adding that already in first attempt not only after the first one has failed. And I can make the application work regardless.
But out or curiosity and in sake of correct coding, what is the difference with those, is there more to use, and what is "the right way" to do the autehtication process?
I believe that this and this other answer might give you a nudge in the right direction:
Authorization is the primary header used by clients to authenticate against peers in HTTP as foreseen in RFC 7235.
[...]
Please note that with X-Auth-Token being an unregistered header, it is subject to no formal specification and its presence and content is always tied to a respective application. No general assumptions can be made on it.
And in the other answer:
The best HTTP header for your client to send an access token (JWT or any other token) is the Authorization header with the Bearer authentication scheme.
Hence, I believe that the "international convention" (if I may) appears to be to use the Authorization header, as the x-access-token is not standard and unregistered, so I'm guessing it's better for code readability to use an already known standard.
Furthermore, even the team behind JWT recommends using the Authorization: Bearer <token> scheme:
Whenever the user wants to access a protected route or resource, the user agent should send the JWT, typically in the Authorization header using the Bearer schema.
However, I understand your confusion: several tutorials around the internet seem to be using the x-access-token to send JWT tokens.
EDIT I think you might find it useful to read the relevant MDN Docs on HTTP Authentication - Authentication Schemes.
This question might be considered as "too broad" or "good practice", but I guess there might be some pieces of RFC that could answer it.
I am currently developping my OIDC server and I am facing a situation I am not sure how to deal with.
A user has been doing a regular authorization_code flow with a web application. In the end the web application has a valid ID token. Now for some reasons the web application forget this token soon after, and the user is running the authentication flow once more:
Should the OP serve the previous ID token, as it is still valid? Or are there some security issues here?
If not, should the OP ask again for the user consent, or consider it already has it?
I think you can find your answer here: https://openid.net/specs/openid-connect-core-1_0.html#Authenticates. Also take note on the wording here: https://openid.net/specs/openid-connect-core-1_0.html#TokenResponse, saying "ID Token value associated with the authenticated session".
My interpretation is: The ID token can be seen associated to an authenticated session that the OP might have, depending on the implementation. So yes, the OP is allowed to serve the same ID token, unless the prompt parameter of the Authentication Request requires reauthentication or consent.
If the Client always wants/needs explicit authentication and/or consent, the prompt parameter can be used for that purpose.
I have been analyzing security process in 3gpp specs and the registration process in the spec. explained with that flow. The flow represents the registration of a client to the server..
I am not a security specialist and i do not understand why we send Oauth2 token in step 1. Doesn't the access token send after the registration? I know that the access token used for authorization if the client known. I know that is a weird topic and I tried to explain it briefly i hope you understand if you dont you can always ask me.
I've been reading a fair bit on Microservices recently, and especially around AuthN and AuthZ. For the most part, this all makes a lot of sense, and I can see how it all should work.
For what I'm playing with, I going with delegated authorization - so I'm to be passing tokens around from client to service, and then passing the same token on from service to service. I also have an endpoint on the OAuth2 Service that will accept a token and return the details of the token - the User ID, the Start and End of the validity period, the scopes that the token is valid for, etc.
The problem that I'm running into here is - in order to correctly issue a token, there needs to be some communication with the User Service to ensure that the User that the token is for is actually valid. And in order to verify a Token, there needs to be some communication with the User Service to ensure that the User is still valid. And yet, in order to safely communicate with the User Service to get details about a User, a Token is needed that gives permission for this access.
I assume there is some standard practice on how to solve this circular dependency between the OAuth2 and User Service, but I've not seen any mention of it at all. Is this a common problem? Or have I just missed something obvious?
(Note - for now I'm only implementing Client Credentials Grant and Resource Owner Password Credentials Grant, since I'm only playing around to see how it all works and they're easier to call with cURL. I don't know that this makes any difference though)
Yeah, that's a bit of a chicken and egg problem. Not sure how much control you have over the authorization server, but one way of solving this issue is to secure the call to the user info service using client certificates.
Another is to combine the user info service and authorization server into one service and eliminate the need for the call all together.