Beta

Create a tenant

A new tenant starts with its own users, OAuth settings, audit history and logs. You are its first Tenant Admin.

BTL Admin

The implicit grant

Imagine the photo editor at editor.example as it would have been built in 2012: a single page of JavaScript with no backend at all. It needed an access token for the photo API, and the obvious way for a page like that to get one was the implicit grant.

Choosing a flow listed it among the flows to avoid. Seeing how it worked, and why it once seemed reasonable, explains why its replacements look the way they do.

How it worked

All domains and tokens in these examples are fictional. The editor sent your browser to the authorization endpoint with response_type=token:

https://auth.photos.example/authorize
  ?response_type=token
  &client_id=photo-editor
  &redirect_uri=https%3A%2F%2Feditor.example%2Foauth%2Fcallback
  &scope=photos.read
  &state=demo-attempt-25

There is no PKCE challenge, because there would be no code to redeem. After you signed in and approved, the authorization server sent the access token straight back in the redirect:

HTTP/1.1 302 Found
Location: https://editor.example/oauth/callback#access_token=demo-implicit-token-25&token_type=Bearer&expires_in=3600&state=demo-attempt-25

The token sits after the #, in the URL's fragment. Browsers do not send the fragment to the server when they load a page. The browser requested /oauth/callback from editor.example without it and received the editor's page. That page's script then read the fragment from the browser's current address, checked state, and kept the token in memory or in browser storage. The specification did not allow a refresh token in this response.

The editor's page sends your browser to the authorization endpoint with response_type=token. After you sign in and approve, the authorization server redirects the browser to the editor's callback with the access token in the URL fragment. The browser requests the callback page from the editor's site without the fragment and receives a page with a script. The script reads the token from the fragment, checks state, and keeps the token. It then calls the photo API with the token. No code is exchanged and the client never authenticates. The editor's page sends your browser to the authorization endpoint with response_type=token. After you sign in and approve, the authorization server redirects the browser to the editor's callback with the access token in the URL fragment. The browser requests the callback page from the editor's site without the fragment and receives a page with a script. The script reads the token from the fragment, checks state, and keeps the token. It then calls the photo API with the token. No code is exchanged and the client never authenticates.
The access token arrives in the redirect itself. The fragment never reaches the editor's server; the page's script reads it in the browser.

Compare this with the authorization code flow. There is no token request, no client authentication, and no proof that the party receiving the token was the one that asked. The only thing tying the token to the editor is the registered redirect URI.

Why it existed

In 2012, a page's script could not count on being able to send a request to another origin, such as the authorization server's token endpoint, and read the response. Cross-Origin Resource Sharing (CORS), the mechanism Browser applications described, was still being standardized and was not available in every browser people used. A code exchange needs exactly that request. The editor had no backend to make it instead, and as a public client it had no credential to authenticate with anyway.

The implicit grant worked around all three problems. The token arrived through a navigation, which browsers had always allowed across origins, and the fragment kept it out of the editor's own server logs. RFC 6749 presented it as a simplified flow for clients running in a browser, while warning that its convenience should be weighed against its security costs, especially where the authorization code grant was available.

What went wrong

Putting the token in a URL exposed it to everything that handles URLs. The full address, fragment included, went into browser history. Any script on the callback page, including analytics and advertising code, could read it. Browser bugs occasionally leaked fragments through referrer headers. A token meant to pass only from the authorization server to the editor went through several places never designed to hold credentials.

Nothing bound the token to the client that received it. Suppose an attacker obtained a token for your photos, perhaps through a malicious application you once approved. They could start a sign-in at a legitimate application that used the implicit grant, then replace the token in the returning fragment with the stolen one. The application could not tell: the state value was its own, and the token worked at the API. This access token injection was most damaging for applications that treated receiving a valid token as proof that a particular person had signed in, a misuse RFC 6749 itself warned against.

Without refresh tokens, the editor had to send you back to the authorization server whenever its token expired. To avoid interrupting you, applications repeated the authorization request in a hidden iframe and relied on your session cookie at the authorization server to approve it silently. That depended on browsers sending the authorization server's cookies inside a frame on another site, which browsers have since restricted, as Browser applications explained. And because the token was handed over in a redirect, there was no standard way to bind it to a key the client held, so the sender-constrained tokens described in Advanced OAuth could not help.

Current guidance

The reasons for the workaround have gone. Browsers support CORS, so a page's script can call a token endpoint that allows it, and PKCE gives a public client a proof for each attempt without needing a secret. A browser application can run the authorization code flow with PKCE itself, as Browser applications described, or leave tokens to a backend for frontend.

The OAuth 2.0 Security Best Current Practice, RFC 9700, says clients SHOULD NOT use the implicit grant, or any other response type that returns an access token in the authorization response, unless access token injection is prevented and the leakage paths are mitigated. Meeting those conditions takes more machinery than simply using the code flow. For the clients that relied on the implicit grant most, a later best current practice removes even that path. RFC 10017, on browser-based applications, says browser-based clients MUST NOT use the implicit grant and that the authorization server MUST issue their access tokens only from the token endpoint. OAuth 2.1, the working group's consolidation of OAuth 2.0 and its later guidance, leaves response_type=token out entirely.

Existing implicit integrations still run in many places, often in applications nobody has needed to touch for years. Migrating older integrations looks at how to find them and move them without breaking the people who depend on them.

Try it in the Lab

PUT IT INTO PRACTICE

Check your understanding

Try these questions before moving on. If an answer isn't right, use the feedback and try again.

0 of 2 answered correctly

Enable JavaScript to answer these questions and save progress in this browser.

QUESTION 1 OF 2In 2012, why did a browser-only application such as the photo editor use the implicit grant instead of exchanging an authorization code?

QUESTION 2 OF 2An attacker swaps a stolen access token into an implicit grant response for a legitimate application. Why might the application accept it?

We value your privacy

We use cookies and similar technologies to enhance your browsing experience, and analytics to understand our traffic. By clicking "Allow All", you consent to optional analytics. Cookie Policy

Learn identity