Google's OAuth2 for Desktop Client Documentation says:
Unlike with web clients, the OAuth 2.0 client secret (if used) is assumed not to be confidential.
This makes sense. However, I can't tell any difference between both flows that reflects this assumption: both flows yield an access token and a refresh token (even though the standard OAuth2 philosophy seems to be that you shouldn't hand out refresh tokens to non-confidential clients, and you should use the implicit grant flow instead).
Then what's the difference security-wise between both flows?
(Update: Maybe the latter always prompts for consent, even when the user already gave their consent?)
Related
In Oauth Open ID - Authorization Code grant type flow,
We will call the Oauth service provider with the client_id = '..', redirect_uri='...', response_type='code', scope='...', state='...'.
Then from Oauth Service Provider, we will get the authorization code instead of the token.
Q1. So what is the next step? Do we send the code to the back end where the token request will happen or will we call the Oauth service provider from the browser it self?
Q2. Why do we need this additional calls? what problem it is solving?
Q3 After the token is received, how we use it in a typical web application?
p.s: I have read lot of blogs, but unable to get the whole picture. Could you please help me?
Q1. In 2021 it is recommended to keep tokens out of the browser, so send the code to the back end, which will exchange it for tokens and issue secure SameSite HTTP Only cookies to the browser. The cookies can contain tokens if they are strongly encrypted.
Q2. The separation is to protect against browser attacks, where login redirects take place. An authorization code can only be used once but can potentially be intercepted - by a 'man in the browser' - eg some kind of plugin or malicious code. If this happens then the attacker cannot exchange it for tokens since a code_verifier and client_secret are also needed.
Q3. The token is sent from the browser to APIs, but the browser cannot store tokens securely. So it is recommended to unpack tokens from cookies in a server side component, such as a reverse proxy. This limits the scope for tokens to be intercepted in the browser, and also deals well with token renewal, page reloads and multi tab browsing.
APPROACHES
The above type of solution can be implemented in two different ways:
Use a website based technology that does OAuth work and also serves web content
Use an SPA and implement OAuth work in an API driven manner
Unfortunately OAuth / OpenID in the browser is difficult. At Curity we have provided some resources based on the benefit of our experience, and we hope that this provides a 'whole picture' view of overall behaviour for modern browser based apps:
Code
Docs
I'm trying to allow access to our publicly facing APIs to approved Single Page Applications only.
We currently use OAuth 2.0 to control access to our APIs. The high level scenario is that our users will access our publicly available SPA, provide their username and password, and then be able to use the SPA which in turn will be able to use our APIs.
The current best practice for OAuth 2.0 with SPA is to use the authorisation code grant with a client id but without the client secret, as obviously an SPA cannot keep any secrets.
My question is how can we prevent a third party SPA from accessing our APIs. I.e. they could extract the existing client_id from our SPA and request an authorisation code in the same way as our first party SPA. Assuming they can persuade a user to login they can then access our APIs.
Is the pre-registered redirect URL the only defence in this scenario? If so, does that mean that if we switch to using the resource owner credentials grant for a better user experience (not recommended I know) there would be no protection from third party apps at all?
I've read the various RFCs for OAuth and this page in particular is very useful but doesn't quite answer my question:
https://auth0.com/blog/oauth2-implicit-grant-and-spa/
Indeed the pre-registered Redirect URI is the only defense mechanism in this case of a public Client when using the so-called Implicit grant type. An attacker may trick the user in starting the flow but will not receive the issued token on a Redirect URL that it controls. This is similar to tricking the user into starting any other login flow.
Since the attacker does not obtain a token (it is still delivered on the intended Redirect URI controlled by the Client) he cannot access your APIs, even if he can persuade the user to login.
When the attacker controls DNS things become more dangerous but that goes for a lot of things outside of OAuth 2.0 as well. In general: delivering tokens to an in-browser app is going to suffer from this type of vulnerability regardless of the protocol used.
Switching to Resource Owner Password Credentials has a lot of drawbacks, including one where the attacker can present an app similar to yours to obtain the username/password (which also block you from upgrading to multi-factor authentication as the other grant types would allow you to).
In summary: there is protection against it although not super strong.
FWIW: the latest OAuth 2.0 best practices suggest that tokens should no longer be directly delivered to the Redirect URI but use an intermediate short-loved one-time usage Authorization Code instead to allow the SPA to get its tokens in an XHR call directly from the token endpoint.
OAuth 2.0 spec defines confidential and public clients. https://www.rfc-editor.org/rfc/rfc6749#section-2.1
Here is the prescription according to the OAuth 2.0 spec
Confidential client - Web application - Auth code grant flow.
Public clients - Desktop App, Mobile App, SPA(Single page app) - Implicit flow.
However AD B2C's prescription according to Microsoft documentation is as follows
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-reference-oauth-code
Confidential client - Web application - OpenIDConnect signin (Built on top of auth code grant)
Public clients - Desktop App, Mobile App - Auth code grant flow
Public clients - SPA(Single page app) - Implicit flow
Based on the above inference, we are clear with Web Apps and SPAs, no confusions here.
However for Desktop and mobile apps why is Microsoft suggesting Auth code grant flow instead of implicit flow [even though they are public clients according to Microsoft documentation as well]?
Posting the answer that i received from Microsoft, which i find as more appropriate in this case.
Please refer to https://www.rfc-editor.org/rfc/rfc8252#section-8.2 which says below -
The OAuth 2.0 implicit grant authorization flow (defined in
Section 4.2 of OAuth 2.0 [RFC6749]) generally works with the practice
of performing the authorization request in the browser and receiving
the authorization response via URI-based inter-app communication.
However, as the implicit flow cannot be protected by PKCE [RFC7636]
(which is required in Section 8.1), the use of the Implicit Flow with
native apps is NOT RECOMMENDED.
Access tokens granted via the implicit flow also cannot be refreshed
without user interaction, making the authorization code grant flow --
which can issue refresh tokens -- the more practical option for
native app authorizations that require refreshing of access tokens.
I believe the authorization code flow is being recommended for mobile and native apps so that a refresh token can be issued to these public clients.
The implicit flow does not issue a refresh token to a public client -- this flow requires the public client to send a hidden iframe request.
tldr: Authoirzation code flow is ideal for confidential clients. But it is not limited only for them;
Your perspective on client type and grant is not correct.
Confidential clients are the ones which can protect the client secret. For example, a web application with a secure back-end is one such. But a SPA cannot be considered one as it does not have a way to protect the client secret. SPA runs on a browser and observing the source from browser will reveal such secret if used. Same applies for a mobile app and a windows installed app (native). If you embed the client secret, then it can be obtained by some reverse engineering from the device.
Now about grant type, authorization code grant is suitable for any client which can do a back-channel token request. This token request happens outside the browser. This can be done by a mobile app or a windows app too. Also, there is PKCE specification dedicated to security enhance the flow for such native clients. If you read the spec, you will see that token request's client credentials are required only if client is confidential.
If the client type is confidential or the client was issued client
credentials (or assigned other authentication requirements), the
client MUST authenticate with the authorization server as described
in Section 3.2.1.
But SPA not having a back-end cannot perform the token request mentioned about. It runs on the browser. Thus implicit grant is defined to cater such apps.
I very clearly understand the OAuth2 token exchange flows and roles. What I'm not clear about is how it maps on real world scenarios. If I have a website which acts like a GUI portion (Client) that communicates to the backend rest API (Resource Provider), it requests token from Auth server to authenticate to RP. The token usually carries scopes the describe user's permissions or roles as they would be enforced by the RP. However, the GUI usually needs to make decisions based on which scopes/roles have been granted to the token. On the one side it looks like it should be introspecting the token to figure out this information to "adapt" UI to match user's permissions. On the other, tokens are not required to be readable, they might be opaque. It seems like authorization decisions are being done on both Client & RP, which would seem to indicate client is also a secondary RP? What is the intended pattern for GUI to receive roles/scopes that the user granted it access to?
Are you talking about OAuth2.0 or OIDC or both? You've tagged openid so I'll assume both.
It seems like authorization decisions are being done on both Client &
RP
An OAuth2.0 client is an OIDC relying party. They are the same thing.
If you are using the hybrid grant - i.e. you are using OAuth2.0 with OIDC to get an access_token and an id_token then your id_token will contain information your client (relying party) can use. It is a JWT token and has an information format which you can rely on. It's also transparent.
The access_token on the other hand may be opaque, it may not - either way it is for your client to pass on to your resource server and not to try and use itself.
The access_token should contain scopes related to what your client can access on the resource server (your backend rest API), whereas your id_token should contain claims related to who the user is, when and how he authenticated and any other identity claims about him supplied by the Identity provider / Authorisation server. These claims may allow your client to tailor the GUI as required.
I'm developing a REST API which uses an Access Token for verifying & validating.
There is one scenario where user can obtain the Access Token by providing proper credentials and use the same Access Token from a different machine to access any REST API.
I just wanted to check if there's any downside to allowing such a case?
Assuming we're talking OAuth 2.0: it actually depends on the access token type: a so-called Bearer access tokens can be used by any Client that gets hold of it. Bearer access tokens are used in the majority of OAuth 2.0 deployments today.
Other types of access tokens are emerging (so-called Proof of Possession tokens) that require the Client to prove that they are really the intended presenter. In that case just having the access token on a different machine is not enough. In even more advanced emerging scenario's ("token binding") the token may be bound to the TLS connection so it can never be used by another Client or on another connection.
But as said, for the majority of OAuth 2.0 deployments today, it would be possible to use the Bearer access token from another machine.
The access token should be signed by the server, and shouldn't include any information about the specific client/machine used to access it.
For example, in the OAuth 2.0 password grant flow, the username/password is exchanged for an access token. The token is signed by the issuing token server, and represents that user's authentication and authorization claims. What machine the user is making requests from makes no difference.
So, tl;dr - yes, access tokens are portable between machines. It's not a typical use case (how would the access token get from one machine to another?), but it's perfectly valid.