Reputation: 20678
With the "Implicit" flow the client (likely a browser) will get a access token, after the Resource Owner (i.e. the user) gave access.
With the "Authorization Code" flow however, the client (usually a web server) will only get an authorization code after the Resource Owner (i.e. the user) gave access. With that authorization code the client then makes another call to the API passing client_id and client_secret together with the authorization code to obtain the access token. All well described here.
Both flows have the exact same result: an access token. However, the "Implicit" flow is much simpler.
The question: Why bother with "Authorization Code" flow, when "Implicit" flow seems to work just fine? Why not just use "Implicit" for webserver?
It's more work both for the provider and the client.
Upvotes: 375
Views: 92385
Reputation: 651
Talking about the Authorization Code Grant-type we have more security, by removing privileged access to the end resource for the Client (User-agent or a Website), where the client (owner of the website) is pretending to be you using your Authorization code, and also to avoid CRSF by hackers using XSS on your browser (website vulnerabilities), which could happen if used Implicit method.
The key ingredient is the client-id which goes in the first request made to the Auth Server. You can think of Auth Code steps as a signature verification.
Moreover, even after finished with the Authorization code steps in acquiring an Access token, ultimately, the access_token ends up in the hands of the client. At that point there is no need to have a client-id for signature verification anymore with the Auth Server. So, I am not sure if Authorization Code method is also perfectly safe (from the client itself). Which is why you see the Auth Server asks you for Consent even after providing the login credentials. Meaning you trust the client with your Access Tokens.
Upvotes: 0
Reputation: 5838
For Googlers:
Conclusion
Metaphor
Upvotes: 22
Reputation: 1136
In "Implicit" flow the client (likely a browser) will get a access token via browser redirection (a GET operation). Browser based communication is not safe and your client secret or token can be intercepted or stolen.
In "Authorization Code" flow, the client (usually a web server) does only get an authorization code, again via browser redirection (a GET operation). Then the server exchanges this code with token by making a (non-browser) POST call to the authorization server. Server includes client secret only for token access call.
Note - According to oauth best practices, "clients SHOULD NOT use the implicit grant (response type "token") or other response types issuing access tokens in the authorization response".
Hope this helps.
Upvotes: 8
Reputation: 3201
From the OAuth spec:
4.2. Implicit Grant
The implicit grant type is used to obtain access tokens (it does not support the issuance of refresh tokens) and is optimized for public clients known to operate a particular redirection URI. These clients are typically implemented in a browser using a scripting language such as JavaScript.
Since this is a redirection-based flow, the client must be capable of interacting with the resource owner's user-agent (typically a web browser) and capable of receiving incoming requests (via redirection) from the authorization server.
Unlike the authorization code grant type, in which the client makes separate requests for authorization and for an access token, the client receives the access token as the result of the authorization request.
The implicit grant type does not include client authentication, and relies on the presence of the resource owner and the registration of the redirection URI. Because the access token is encoded into the redirection URI, it may be exposed to the resource owner and other applications residing on the same device.
So what we can consider:
This is for public OAuth i.e. when client not needed to be registered and doesn’t have it’s own client secrets. But what auth server checks redirect url and this is actually enough for security.
The Access token occurs in browser’s address bar so user can copy the url and send to someone else and it also becomes logged as the user i.e. it’s something like Session fixation. But the browser make an additional redirect with replacing history to remove hash fragment from the url. It also possible to a hacker to stole the access token by sniffing a HTTP trafic but this can be easily protected by HTTPS. Some malicious browser extensions can have an access to urls from address bar but this is ultimately bad situation like broken HTTPS cert. And even Auth code flow can’t help here ether. So what I can see is that passing access token via hash fragment of url is absolutely safe.
The separation of ephemeral access token and refresh token are useless when using a HTTPS and to be honest not so useful even on raw HTTP. But the fact that client via implicit flow can’t receive the refresh token is also nonsense.
Thus I think we should introduce a new grant flow “safe implicit” which works strictly over https, allows refresh token (or we should get rid off them at all), and is preferable than Auth Cose grant flow
Upvotes: 6
Reputation: 1737
For us, our clients wanted to be able to authenticate with our app on their phones once, and not have to log in again for weeks at a time. With code flow, you get a refresh token along with your access token. Implicit flow does not give you a refresh token. The access token has a relatively short expiration, but the refresh tokens can have up to a 90 day expiration. Whenever the access token expires, the client and server code can use that refresh token to get a new access token plus refresh token, all behind the scenes, without any user intervention whatsoever. A refresh token can only be used once. You cannot do this with Implicit Flow. If you're using Implicit Flow, and your user doesn't interact with your app for over an hour, they will have to log in again when they come back. That was not acceptable in our use case, and Code Flow supports our use case securely.
This works and is secure because refresh tokens can be revoked. If a customer says they lost their phone or their laptop or a hacker got on to their desktop, we can simply revoke all of the refresh tokens for that user. During the entire process, no Personally Identifiable Information (PII) ever touches our code - namely the user's password.
Code flow is awesome, but it does take more work. MS does not have an Angular library to handle it currently, so I had to write one. If you are interested I can help you with it.
Upvotes: 5
Reputation: 12384
tl;dr: This is all because of security reasons.
OAuth 2.0 wanted to meet these two criteria:
Details below:
The implicit flow is only possible in a browser environment because of security reasons:
In the implicit flow the access token is passed directly as a hash fragment (not as a URL parameter). One important thing about hash fragment is that, once you follow a link containing a hash fragment, only the browser is aware of the hash fragment. Browsers will pass the hash fragment directly to the destination webpage (the redirect URI / the client's webpage). Hash fragment have the following properties:
This makes it possible to pass an Access Token directly to the client without the risk of it being intercepted by an intermediary server. This has the caveat of only being possible client side and needs javascript running client side to use the access token.
The implicit flow also has security issues that requires further logic to workaround/avoid for instance:
In the authorization code flow it is not possible to pass an access token directly in a URL parameter because URL parameters are part of the HTTP Request, therefore any intermediary server/routers by which your request would pass (could be hundreds) could be able to read the access token if you are not using en encrypted connection (HTTPS) allowing what's known as Man-in-the-middle attacks.
Passing the access token directly in a URL param could in theory be possible but the auth sever would have to make sure the redirect URI is using HTTPS with TLS encryption and a 'trusted' SSL certificate (typically from a Certificate Authority that is not free) to be sure that the destination server is legitimate and that the HTTP request is fully encrypted. Having all developers purchase an SSL certificate and properly configure SSL on their domain would be a huge pain and would slow adoption down tremendously. This is why an intermediary one-time-use "authorization code" is provided that only the legitimate receiver will be able to exchange (because you need the client secret) and that the code will be useless to potential hackers intercepting the requests over unencrypted transactions (because they don't know the client secret).
You could also argue that the implicit flow is less secure, there are potential attack vectors like spoofing the domain upon redirect - for example by hijacking the IP address of the client's website. This is one of the reasons why the implicit flow only grants access tokens (which are supposed to have a limited time use) and never refresh tokens (which are unlimited in time). To remedy this issue, I advise you to host your webpages on an HTTPS-enabled server whenever possible.
Upvotes: 390
Reputation: 22333
My answer is: you can't implement Implicit flow in a safe and simple manner with the web-app server.
Web-app authorization process involves user interaction so Authentication Server should redirect user's browser back to the web-app's target page after user authentication and consent (I don't see any other way to pass user back to the web-app after some interaction with Authentication Server).
So token should be passed to web-app using redirect URL, right?
As @NicolasGarnier explained in his answer and comments there is no way to pass token as an URL fragment - it will not reach web-app server.
And passing token as an URL param of the redirect URL would be unsafe even under HTTPS: if the target page (let it be "greetings page") contains resources (images, scripts, etc) this resources will be obtained by browser through the series of HTTP(S) requests (each of which have Referer
HTTP header containing exact URL of the "greetings page" including URL parameters). This is the way token can leak.
So it seems there is no way to pass token in redirect URL. That's why you need second call (either from Authentication Server to the Client (but to which URL?) or from Client to the Authentication Server (the second call in Authorization Code flow))
Upvotes: 8
Reputation: 11232
The Implicit Flow makes the whole flow pretty easy, but also less secure.
As the client application, which is typically JavaScript running within a Browser is less trusted, no refresh tokens for long-lived access are returned.
You should use this flow for applications that need temporary access (a few hours) to the user’s data.
Returning an access token to JavaScript clients also means that your browser-based application needs to take special care – think of XSS Attacks that could leak the access token to other systems.
https://labs.hybris.com/2012/06/05/oauth2-the-implicit-flow-aka-as-the-client-side-flow
Upvotes: 18