ChatGPT解决这个技术问题 Extra ChatGPT

What is the purpose of the implicit grant authorization type in OAuth 2?

I don't know if I just have some kind of blind spot or what, but I've read the OAuth 2 spec many times over and perused the mailing list archives, and I have yet to find a good explanation of why the Implicit Grant flow for obtaining access tokens has been developed. Compared to the Authorization Code Grant, it seems to just give up on client authentication for no very compelling reason. How is this "optimized for clients implemented in a browser using a scripting language" (to quote the specification)?

Both flows start out the same (source: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-22):

The client initiates the flow by directing the resource owner's user-agent to the authorization endpoint. The authorization server authenticates the resource owner (via the user-agent) and establishes whether the resource owner grants or denies the client's access request. Assuming the resource owner grants access, the authorization server redirects the user-agent back to the client using the redirection URI provided earlier (in the request or during client registration).

The redirection URI includes an authorization code (Authorization code flow)

The redirection URI includes the access token in the URI fragment (Implicit flow)

Here's where the flows split. In both cases the redirection URI at this point is to some endpoint hosted by the client:

In the Authorization code flow, when the user agent hits that endpoint with the Authorization code in the URI, code at that endpoint exchanges the authorization code along with its client credentials for an access token which it can then use as needed. It could, for example, write it into a web page that a script on the page could access.

The Implicit flow skips this client authentication step altogether and just loads up a web page with client script. There's a cute trick here with the URL fragment that keeps the access token from being passed around too much, but the end result is essentially the same: the client-hosted site serves up a page with some script in it that can grab the access token.

Hence my question: what has been gained here by skipping the client authentication step?

Link in the previous comment is dead. Here's an updated one
I've read all the answers here, but I still don't understand how not requiring a private client secret to get an access token can be secure. Let's say TrustedAppDeveloper releases TrustedPopularApp that let's users give it permissions (say using Twitter oauth) using an implicit grant. If I am EvilAppDeveloper, what's to stop me from making an app that passes TrustedPopularAppId as the client_id in an implicit grant request, and then performing actions (like spamming a feed) on behalf of the user, that now look like they are coming from TrustedPopularApp?
@adevine What would prevent the EvilApp in your scenario from authenticating to Twitter as TrustedPopularApp is that it couldn't receive the callbacks from Twitter, they would always be sent to the URI that was defined when registing the client ID

M
Matt Ke

Here are my thoughts:

The purpose of auth code + token in authorization code flow is that token and client secret will never be exposed to resource owner because they travel server-to-server.

On the other side, implicit grant flow is for clients that are implemented entirely using javascript and are running in resource owner's browser. You do not need any server side code to use this flow. Then, if everything happens in resource owner's browser it makes no sense to issue auth code & client secret anymore, because token & client secret will still be shared with resource owner. Including auth code & client secret just makes the flow more complex without adding any more real security.

So the answer on "what has been gained?" is "simplicity".


Thanks. That's a good point that in the authorization code flow the resource owner never needs to see the access token, whereas in javascript clients that's unavoidable. Client secret could still be kept from javascript clients using authorization code flow, however: after authenticating and obtaining an access token the server side code would then pass the token to the javascript client. What I now see, though, is that implicit grant flow enables the distribution of javascript oauth SDKs, like Facebook's, freeing developers from having to write their own oauth code completely.
I would maybe add that, authorization code flow enables clients to store the tokens and reuse them. In the implicit flow, you don't always have that option and as such, implicit flow is a pragmatic choice between level of security and convenience.
This answers only half, and "what has been lost"?
I don't think this is a comprehensive answer, implicit flow is not intended to gain advantage on simplicity but to compromise security concerns with client-side app. Auth code, together with client_id and client_secret are used to identify trusted clients who can refresh tokens for long time login and for "offline login". However in a client-side app, there is no way to register each client, hence the "simplified" implicit grant type for temporary access to user information
Including the client secret doesn't just make the flow more complex, it makes it less secure. The client secret isn't a secret if it needs to be enumerated within client-side code, and it would therefore be exposed to the internet. If your client ID is only used in implicit flows, this isn't a problem. But if it's also used elsewhere in your platform for refresh token or authorization code grants, then having the corresponding secret exposed is a big problem.
L
Lifu Huang

It's there for security reasons, not for simplicity.

You should consider the difference between the user agent and the client:

The user-agent is the software whereby the user ("resource owner") communicates with other parts of the system (authentication server and resource server).

The client is the software which wants to access the resources of the user on the resource server.

In the case of decoupled user-agent and client the Authorization Code Grant makes sense. E.g. the user uses a web-browser (user-agent) to login with his Facebook account on Kickstarter. In this case the client is one of the Kickstarter's servers, which handles the user logins. This server gets the access token and the refresh token from Facebook. Thus this type of client considered to be "secure", due to restricted access, the tokens can be saved and Kickstarter can access the users' resources and even refresh the access tokens without user interaction.

If the user-agent and the client are coupled (e.g. native mobile application, javascript application), the Implicit Authorization Workflow may be applied. It relies on the presence of the resource owner (for entering the credentials) and does not support refresh tokens. If this client stores the access token for later use, it will be a security issue, because the token can be easily extracted by other applications or users of the client. The absence of the refresh token is an additional hint, that this method is not designed for accessing the user resources in the absence of the user.


I see my browser has logged into my google account for months. So is google use access token on browser or an access token with a long expiration time? what difference in usage between access token with a long expiration time and access token? any other client can catch the access token and use it when resource owner is not present.
I assume you mean the difference between refresh token and access token with long expiration time? The refresh token should not be saved in insecure scenarios, but you can save your access token, though (e.g. in the browser's local storage). The security is achieved by keeping the lifetime of your access token as low as possible, though still comfortable for your users (e.g. you can log out them automatically after x minutes of inactivity). If you use long-life access tokens, you practically make refresh tokens obsolete.
Thanks for your explanation but I have another confusion too. I don't understand why we need "Authorization Code" flow. We can reach the same result on the server by implicit flow (access_token) and a refresh token. It looks the only security consideration of implicit flow is that access_code should have short life so it can't be used on server to server. OK, but the refresh token solves this problem. Why we should use an auth_code flow and request access_token by that token on a server to obtain access_code whilte we can achieve the same result with refresh_token?
"the token can be easily extracted by other applications" How?
@MohammadNikravan look for the answer in stackoverflow.com/q/13387698/355438
J
JW.

The usual explanation is that the Implicit grant is easier to implement when you're using a JavaScript client. But I think this is the wrong way to look at it. If you're using a JavaScript client that requests protected resources directly via XMLHttpRequest, the Implicit grant is your only option, although it's less secure.*

The Authorization Code grant provides additional security, but it only works when you have a web server requesting the protected resources. Since the web server can store the access token, you run less risk of the access token being exposed to the Internet, and you can issue a token that lasts a long time. And since the web server is trusted, it can be given a "refresh token", so it can get a new access token when the old one expires.

But -- and this is a point that's easy to miss -- the security of the Authorization code flow works only if the web server is protected with a session, which is established with user authentication (login). Without a session, an untrusted user could just make requests to the web server, using the client_id, and it would be the same as if the user had the access token. Adding a session means that only an authenticated user can access the protected resources. The client_id is just the "identity" of the JS webapp, not authentication of said webapp.

It also means that you can end the session before the OAuth token expires. There's no standard way to invalidate an access token. But if your session expires, the access token is useless, since nobody knows it but the web server. If an untrusted user gained access to your session key, they would only be able to access the protected resources for as long as the session was valid.

If there's no web server, you have to use the Implicit grant. But this means that the access token is exposed to the Internet. If an untrusted user gains access to it, they can use it until it expires. This means they'll have access to it for longer than with an Authorization Code grant. So you may want to consider making the token expire sooner, and avoid giving access to more sensitive resources.

*EDIT: More recently, people are recommending that you avoid using the Implicit grant, even on web apps without a server. Instead you can use the Authorization Code grant configured with an empty secret, along with PKCE. The auth-code grant avoids storing the access token in your browser history, and PKCE avoids exposing it if someone hijacks the redirect URL to steal the auth code. In this case you would need the server to avoid returning a refresh token, since your client probably can't store it securely. And it should issue an access token with the same limitations mentioned above.


C
Community

It boils down to: If a user is running a browser-based, or "public", (JavaScript) web app with no server side component, then the user implicitly trusts the app (and the browser where it runs, potentially with other browser-based apps...).

There is no 3rd-party remote server, only the resource server. There is no benefit to an authorization code, because there is no other agent besides the browser acting on behalf of the user. There is no benefit to client credentials for the same reason. (Any client can attempt to use this flow.)

The security implications, however, are significant. From https://www.rfc-editor.org/rfc/rfc6749#section-10.3:

When using the implicit grant type, the access token is transmitted in the URI fragment, which can expose it to unauthorized parties.

From https://www.rfc-editor.org/rfc/rfc6749#section-10.16:

A resource owner may willingly delegate access to a resource by granting an access token to an attacker's malicious client. This may be due to phishing or some other pretext...


what do you mean by "public", (JavaScript) web app with no server side component? How can there be an web application without server?
@ZammyPage, this would be what is often called a Single Page App (SPA). The entirety of the app is served up from a static resource. Javascript in the app then dynamically accesses whatever resources it needs, on whatever resource servers it can access. There is no server that generates the content of the client: the javascript in the client modifies the DOM as needed to represent the resources it has accessed.
There is a simple but meaningful benefit: If you store server logs and you're using the authorization code flow, all codes will very likely be invalid if the logs leak. If you're storing access tokens though you can impersonate user sessions directly.
t
tzuchien.chiu

I'm not sure that I understand correctly the answer and Dan's comment. It seems to me that the answer has stated some facts correct but it does point out exactly what OP asked. If I understand correctly, the major advantage of the implicit grant flow is that a client like JS app (e.g Chrome extension) doesn't have to expose the client secret.

Dan Taflin said:

...in the authorization code flow the resource owner never needs to see the access token, whereas in javascript clients that's unavoidable. Client secret could still be kept from javascript clients using authorization code flow, however..

Perhaps I misunderstood you, but the client (JS app in this case) must pass the client credential (client key and secret) to the resource server in the authorization code flow, right ? The client secret cannot be "kept from JS".


I realize this is an old question but this is a better answer than the accepted one. The reason Implicit Grant exists is that a javascript client cannot keep a secret, and therefore cannot be authenticated. So the authorization server has to rely solely on the redirect uri registration and user agent for security. You pass authorization tokens only to the user agent, and only at a specific redirect uri, theoretically preventing interception (because a malicious user who does not own the domain of the redirect uri cannot execute code in the user agent at that uri).
Indeed the accepted answer confused me. Made me think I misunderstood what the client_secret is! This answer and the above comment are spot on.
C
Community

While Implicit Grant was designed to support apps that could not protect a client secret including client-side JavaScript apps, some providers are implementing an alternative using Authorization Code without a Client Secret instead. The OAuth 2.0 IETF RFC-6749 was published in 2012 and current recommendations some recent discussions are from 2017.

2017 discussion on the IETF OAuth mailing list is available from these implementers:

Redhat: https://www.ietf.org/.../oauth/current/msg16966.html

Deutsche Telekom: https://www.ietf.org/.../oauth/current/msg16968.html

Smart Health IT: https://www.ietf.org/.../oauth/current/msg16967.html

Read more here:

https://aaronparecki.com/oauth-2-simplified/

https://aaronparecki.com/oauth-2-simplified/#single-page-apps

Implicit was previously recommended for clients without a secret, but has been superseded by using the Authorization Code grant with no secret. ... Previously, it was recommended that browser-based apps use the "Implicit" flow, which returns an access token immediately and does not have a token exchange step. In the time since the spec was originally written, the industry best practice has changed to recommend that the authorization code flow be used without the client secret. This provides more opportunities to create a secure flow, such as using the state parameter. References: Redhat, Deutsche Telekom, Smart Health IT.

Moving to Auth Code without Client Secret from Implicit Grant is also mentioned for mobile apps here:

https://aaronparecki.com/oauth-2-simplified/#mobile-apps


I think you want to be careful with this recommendation. This was recommended in the guidance for native apps, rather than spas. Unfortunately there is no good guidance on SPAs as documented in many of the online discussions, forums and even oauth-wg mailing list.
The recommendation to move to auth code without secret from implicit grant is a recommendation for both SPAs and mobile apps, but my excerpt above is specific to SPAs. The referenced article uses similar text for both SPAs and mobile apps, but with the language "browser-based apps" "mobile and native apps" in the respective text. Also the references for Redhat, DT, Smart Health IT, are specific to SPAs and not included in the note for mobile apps. I've added a deep link to SPAs in the answer to make this easier to find. Please post some links to the discussions you mention.
A fairly recent (2018) oauth-wg discussion can be found here ietf.org/mail-archive/web/oauth/current/msg18020.html. RFC 8252 is for native apps as the title suggests "OAuth 2.0 for Native Apps". The references to Redhat, DT, Smart Health IT are responses to a mailing list discussion, not an rfc, working draft, etc...
P
Pace

In the implicit flow if the user's browser is corrupted (evil extension / virus ) then the corruption gets access to the user's resources and can do the bad stuff.

In the auth flow the corruption can't because it doesn't know the client secret.


H
Hans Z.

in addition to the other answers it is also important to realize that the Implicit profile allows for a front-channel only flow as opposed to the Authorization Code flow that requires a call back to the Authorization Server; this becomes evident in OpenID Connect which is an SSO protocol built on top of Auth 2.0 where the Implicit flow resembles the pretty popular SAML POST binding and the Authorization Code flow resembles the less widely deployed SAML Artifact binding


C
Community

https://www.rfc-editor.org/rfc/rfc6749#page-8

Implicit The implicit grant is a simplified authorization code flow optimized for clients implemented in a browser using a scripting language such as JavaScript. In the implicit flow, instead of issuing the client an authorization code, the client is issued an access token directly (as the result of the resource owner authorization). The grant type is implicit, as no intermediate credentials (such as an authorization code) are issued (and later used to obtain an access token). When issuing an access token during the implicit grant flow, the authorization server does not authenticate the client. In some cases, the client identity can be verified via the redirection URI used to deliver the access token to the client. The access token may be exposed to the resource owner or other applications with access to the resource owner's user-agent. Implicit grants improve the responsiveness and efficiency of some clients (such as a client implemented as an in-browser application), since it reduces the number of round trips required to obtain an access token.


M
Mike Schwartz

I think Will Cain answered this when he said " There is no benefit to client credentials for the same reason. (Any client can attempt to use this flow.)" Also consider that the redirect_uri for implicit flow maybe "localhost"--no callback is made from the Authorization Server for the implicit flow. As there is no way to pre-trust the client, the user would have to approve the release of user claims.


C
Community

The Implicit Grant allows for obtaining tokens from Authorization Endpoint with a GET. This means the authorization server does not have to support CORS.

If that is not a concern and there are no other issues related to the authorization server been inflexible (e.g. refresh tokens are not optional, for some reason) then authorization code flow is the preferred one, even for public clients, according to recent industry trends and to at least this (current) instance of an official draft.

Historically there were other reasons to implement the implicit flow but it seems they are currently outweighed by security advantages the authorization code grant provides, including:

option to deliver and use the tokens over a back-channel for confidential clients

not exposing tokens in the browser history for public clients

interrupting an unauthorized flow before tokens are issued - with PKCE, for "all kinds of OAuth clients"


I
Ilya Serbis

I've just faced with some article about OAuth 2.0. Author states that the reason behind the Implicit flow is that JS apps were very restricted in there requests:

if you wonder why the implicit type was included in OAuth 2.0, the explanation is simple: Same Origin Policy. Back then, frontend applications were not allowed to send requests to different hosts to get the access token using code. Today we have CORS (Cross-Origin Resource Sharing).

https://medium.com/securing/what-is-going-on-with-oauth-2-0-and-why-you-should-not-use-it-for-authentication-5f47597b2611