Why OAuth2 implicit flow relies on iframes? - oauth-2.0

I saw in a few places that Imlicit flow clients use iframe to get a new token silently, without user interaction. Why is that? Why can't the client just send a GET request to the authorization server and retrieve the token from the returned HTTP 301 response?
I saw iframe mentioned in these places:
https://learn.microsoft.com/en-us/azure/active-directory/develop/reference-third-party-cookies-spas
https://auth0.com/docs/authenticate/login/configure-silent-authentication
I found this post: OAuth2 Implicit Flow - IFrame Refresh Identity. It says that the request sent from iframe carries a cookie with it. Is it not possible to attach such a cookie from a JS request?

Related

OAuth 2.0: why is the access token or temporary code placed in the in the URL fragment (after the #) instead of in the query string?

I am learning OAuth 2.0.
In both code flow and implicit flow (response_type = code or token). The temporary code or access_token is placed in the URL fragment (after the #) instead of in the query string.
According to this doc: https://developer.okta.com/blog/2018/05/24/what-is-the-oauth2-implicit-grant-type:
If the user approves the request, the authorization server will redirect the browser back
to the redirect_uri specified by the application, adding a token and state to the fragment
part of the URL.
For example, the user will be redirected back to a URL such as:
https://example-app.com/redirect
#access_token=g0ZGZmNj4mOWIjNTk2Pw1Tk4ZTYyZGI3
&token_type=Bearer
&expires_in=600
&state=xcoVv98y2kd44vuqwye3kcq
Note the two major differences between this and the Authorization Code flow: the access token is returned
instead of the temporary code, and both values are returned in the URL fragment (after the #) instead
of in the query string. By doing this, the server ensures that the app will be able to access the value
from the URL, but the browser won’t send the access token in the HTTP request back to the server.
What exactly does it mean by
the server ensures that the app will be able to access the value from the URL, but the browser won’t send the access token in the HTTP request back to the server.
?
Of course the code/ access_token value is accessible from the URL.
The Auth server builds up the url and put it in location header of the HTTP response, which is sent back to the user's web browser. The web browser then take values from the response, and send new http requests to the application instead of the Auth server. So, of course the user's web browser is not sending HTTP request back to the server.
It has nothing to do with where the access token is placed in the response (from Auth server back to the user's web browser). The web browser simply starts talking to the application again instead of the Auth server.
This explanation just does not make much sense to me.
The code flow returns an authorization code to the browser in the query string. You then make a POST request to swap the code for tokens.
https://www.example.com?code=xxx&state=yyy
Implicit flow is now deprecated since it can reveal tokens in the browser history or server logs. It dates back to when browsers did not have CORS capabilities to make cross orign POST requests to the Authorization Server.
Data in client side hash fragments does not get sent to servers and the implicit flow used this as a partial mitigation for sensitive data. Eg the zzzz below does not get sent to the web server if you type this in a browser.
https://www.example.com#zzzz
If you are new to OAuth and OpenID Connect, start with code flow + PKCE, and understand these messages.
SWAPPING THE CODE FOR TOKENS
This is often done via a back end component that completes the flow, so that a client secret can be attached (a browser cannot keep secrets). This back end component can then do either of these:
Return access tokens to the browser
Issue secure cookies to the browser
Once done, the front end has a credential with which it can call the main back end (eg APIs), so that the back end knows the user identity.
CODE EXAMPLE
In 2021 the cookie option is considered more secure, but it also requires a more complex flow. All of the complexity involved originates from the browser being a hostile place to execute code - there are lots of security threats there. Here is some example code that uses cookies:
OAuth calls from an SPA
API calls from an SPA

Why or how does an invalid callback url work with Oauth2 in Postman?

All other steps of OAuth2 are clear to me except the concept of the re-direct URL.
I am querying an API end-point (Bitbucket) via Postman. When registering my application with Bitbucket, it asks me for a redirect end-point. I puzzled over this for a while and tried a random URL - https://random-appxxxx.com/
In Postman, if I entered all the info correctly (client id,secret,access-token URL etc.) along with that random URL, it works perfectly and I am not sure why that is. If I understand correctly, the redirect URL (i.e. callback URL) is where the user is directed to after the client application is authorized.
So, how does Postman read the code from the redirected URL - https://random-appxxxx.com/?code={random string} since the authorization server is sending the code to an invalid url ?
For an Auth 2.0 code flow you need to make an Authorization Request and then Access Token Request.
Postman acts as a browser, a redirect response after Authorization Request from the server is the same as a response of a post request after the Access Token Request.
Postman calls the Auth URL you defined and expect a response of redirect to callbackURL?code=auth_code.
Then call the Access Token URL with that auth_code like described in the RFC6749
Postman doesn't need to call the redirect URL because he finish the handshake instead of your server.

Grails spring security rest plugin v1.5.3 - Refresh token flow

I have a REST API implemented using grails v2.5.2 and a client using AngularJS. I am using the JWT authentication that the plugin provides by default.
I've set the token expiration as 3600 and I would like to refresh the access_token automatically (transparently to the user). I know that I have to make a POST to /oauth/access_token with an application/x-www-form-urlencoded and send the refresh_token in order to get a new access_token.
The question I have is:
What is the status code returned by this plugin when the token expires?
I set the log4j and I see it is sending a 401 once the token has expired.
I would expect a 403 instead of a 401 due to the last one is used for invalid login credentials.
I need to know this in order to set up the response interceptor to request a new access_token.
Thank you!

Web API 2 and HttpClient

I have a web api and MVC project,
The web api is deployed at api.domain.com
The MVC app is deployed at domain.com
I recently secured certain methods on the API, it requires authentication (grant type: password).
I want to have the token passed around in the code behind of the MVC app and not javascript, to keep it secure and away from someone sniffing angular js traffic.
I did some research and I should use the HttpClient class. If this is the case how does this client handle refresh tokens? Right now the token expires after 8 hours, I know a refresh token is also issued but does the HttpClient automatically handle this or do I have to write my own logic to check if a request was denied due to an expired token.
Thank you!
I did some research and I should use the HttpClient class. If this is
the case how does this client handle refresh tokens?
The HttpClient class is, as its name suggest, an HTTP protocol client. It knows strictly nothing about OAuth 2.0 and in this respect nothing about refresh tokens. So you should write this logic yourself. Basically the flow you should follow is something along those lines:
Send an HTTP request t othe target endpoint using the HttpClient and including your existing OAuth Bearer token in the Authorization header field.
If the request succeeds then you are good to go. If the request fails with 401, then you should use your refresh token in order to renew your access token and then repeat step 1 with your new access token.
I think using a HttpMessageHandler can help you.
The way this is wired up to an HttpClient is by using the HttpClient constructor that takes a HttpMessagHandler:
1: // Create client and insert an OAuth message handler in the message path that
2: // inserts an OAuth authentication header in the request
3: HttpClient client = new HttpClient(new OAuthMessageHandler(new HttpClientHandler()));
The HttpClientHandler is the default “network” handler provided by HttpClient that actually sends the request and received the response from the network.
Refer this for complete detail: https://blogs.msdn.microsoft.com/henrikn/2012/02/16/extending-httpclient-with-oauth-to-access-twitter/

Add headers to a link in angular

I have an angular app that I need to redirect outside to a server side html page, so I thought I could just use a standard <a> tag with target='_self' to redirect the angular app to my server side page. This actually works fine, however, I have a rails backend that checks for auth token before serving up any content.
This requires a auth token to be sent in the header of the http request which I am setting in a cookie, and angular grabs automatically with the $http service for ajax requests, but I can't seem to get the same thing to happen on a standard link.
Can/How do you add an auth token to a normal link before it is sent off?
When the browser is making the HTTP request and not your JavaScript code, you cannot add a custom header with your token value. See Adding http headers to window.location.href in Angular app for a similar question.
However, if this value is already being sourced from a cookie, can your backend just read that cookie value (or use some filter in the http request chain to transfer the cookie to a header)?

Resources