OAuth2: query string vs. fragment - oauth-2.0

Just noticed that in OAuth2 when the requested grant type is: "code" the callback contains it in the query string parameters (after '?'). However, when the grant is "token" it is passed as a fragment (after '#').
This looks to be part of a spec (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-26#section-4.2)
What could be a rationale behind such decision?
Thanks,
Piotr

When your browser gets redirected by a website to a URL with a query parameter, the query string is also part of the request that your browser now sends to the host. Fragments are only evaluated locally by your web browser and not included into the request to the host.
In case of the Authorization Code Grant, where you typically have a web application, that directly talks to a provider, sending the data to the host is exactly what you need:
The web application redirects your browser to the provider where you log in.
The provider now tells your browser a callback URL of the web application and appends an authorization code. This code has to be sent to the web application, so it is included as a query parameter into the request to the callback URL.
The web application now itself talks to the provider in the background and verifies with the authorization code that he is indeed allowed to query the provider for an access token.
In case of the Implicit Grant, you typically have some Javascript application directly running in your browser. There's no need to pass any authorization code to the host and in most cases there's also no need to send the access token to the host, as the JS in the browser can directly talk to the provider. This way you could e.g. create a website on a server that uses information queried from another provider with consent from the user where the server never gets access to any confidential data of the user. (In case of a trusted website, that doesn't send the access token to the server.)

Related

Requesting an authorization code through a backchannel

According to the OAuth2.0 spec and the way it is implemented in OpenIddict 3.1.1, an authorization code should be retrieved by performing a GET request to the authorization endpoint. This will then redirect the user to a login page (if needed) and ask for explicit authorization from the user.
It is, however, also possible to configure a client application to use an implicit consent type, where the user does not need to explicitly give permission to the application.
My question builds on this: If I know that the user is already signed in (I have a valid access token), would it be possible to request an authorization code for a different application through a backchannel POST request (using the authorization header to specify that I have access to do this) instead of having to go through the browser for this flow?
As far as I can see in OpenIddct 3.1.1, the authorization code is generated in some middleware that handles signin results. This seems to make it difficult for me to generate such an authorization code in a custom endpoint designed for my desired scenario mentioned above.
The reason I'm wondering about this at all is because I'm building a desktop application for which I'll open a browser for the initial login, but after that I need to request an authorization code for a custom server back-end and I'd prefer not having to open the browser once more just for this purpose, since I know the user is authenticated (and authorized) to request this authorization code anyway. I would of course send the all the required information in this backchannel POST request (client_id, code_challenge, challenge_method, scopes...)
EDIT:
The reason I need a second access token is because:
I have 4 systems:
Desktop application
Custom Server
Resource Server
Identity Provider
The desktop application is the one that is directly used by the user, and it will request an access token through the regular auth_code flow from the Identity Provider. This desktop application will then request resources in the resource API, for which it needs an access token. This process is working as standard.
Now I also want the Custom Server application to request resources from the resource server. Normally you would use client credentials for this, because it is server to server, but the resources are owned by the user, so I'd want an access token specifically for these resources.
For this I now start a second auth_code flow on the desktop application to request an authorization code for the Custom Server. I then send this auth_code back to the Custom Server, which exchanges it for an access token. This works, but I would prefer if I didn't have to start a full on auth_code flow on the desktop application for this second process, as I know that the user is authorized to request this auth_code, and the consent type for the Custom Server is implicit in this case.

How it happen. Identity Server4 User Login page redirection. Purpose of Redirect Urls

I am quite new to Asp.net core identity and Identity Server 4. I am following online training course on implementing Authentication using Open Id Connect with asp.net core and Identity server 4.
If I further illustrate my solutions having Asp.net core mvc web application as client. Another asp.net core mvc web app as IDP (Identity Server4) and another asp.net core mvc web api as resource server.
For un-authenticated Users Login page on IDP is appearing. Problem for me is how does client web (asp.net core web app) knows user is not authenticated? My guess is when user first time access web app access token is not presenting on authorization header so authentication middleware knows this is not authentication request and redirect request to IDP Is it correct?
Then user redirect to Logic view of Account Controller how that redirection configured on IDP (I mean here is how exactly redirect to Account controller login page)?
Furthermore what is purpose of RedirectUris(https://localhost:44326/signin-oidc) configure on IDP. and how it works
By the way in here I am using Authorization Code flow and IdentityServer4.Quickstart.UI AccountController comes from there.
Either you know what api needs authentication, therefore, if you don't have this token available anywhere, you shall redirect the user to the oauth server. Once this one redirects back on your application, you will find the token in the url (a parameter of it if my memory is good). This token will have to be saved in memory for later usage or in your application db (standard browser feature). Then you can make a call to the api using this token that you stored.
If you don't know what api needs authentication or if your token is expired, you make the call to the api anyway, and then you get an 403 error (not authorized). Any 403 error should make the client application decide to redirect the user on the authentication portal to get an new token.
As you use code flow, I suppose you must develop a react, angular or any spa application. So I advice you to use oidc-client. It is a javascript library that is developed by the same guys who developed identity server. It makes the client very simple to develop when dealing with oauth authentication.
Here a more detailed description of the process and check/variable that are done/used:
The client application (javascript/html5) makes a call to the resource server without any token in the authentication http request header
The resource server (your api server) tries to get the token in the header
doesn't exists. This means the request is not authenticated.
The resource server return an 403 error to the client before even making any controller call or even authorization checks (roles and such)
The client catches this 403 error, and then knows that a token is necessary for this call.
The client stores the url of the request that failed and its post (if applicable) in the application db
The client redirects the browser to the authentication server url, by transmitting the client id (the identifier of the javascript/html5 application for the authentication server), the scope (what set of resource that should be used by this client application in the context of this authentication request) and the url where the authentication server should reidrect the user back once he is authenticated.
The authentication server asks the users to authenticate (in any way you can imagine, but most of time it is by asking him a login and a password)
if the user is recognized by the authentication server (password that matches the login), this one will check if the return url (the url that was transmitted by the client application for it to be used to redirect the user on the right page once he is authenticated) is in the list of granted return urls for this client application (the RedirectUris you are wondering about). The point of this is to ensure that the the issued token is not transmited to an ungranted application (like a external javascript/html5 application hosted in china that could find a way to suck some data from your api server that only your user can know about and submitting it to a russian api server without the user even noticing it)
it also checks if this client application (not the user... here it's to ensure that a specific client javascript/html5 application can access a set of resources) can use the scope that is requested.
if checks are ok, the authentication server issues an access_token by signing it with its private key.
the authentication server redirects the user on the initially transmitted return url, by setting the access_token in the url as a parameter.
the client application get this parameter and stores it somewhere (anywhere you want, but most of time in the application db and in memory)
the client application get the url that stored for the call to be done again, but with the access_token in the authentication header this time
the api server (or resource server) receives the http request again
finally find an access_token and checks if the it was actually issued by the authentication server (using its public key) since it is the only tiers that is trusted to issue a token.
then it can trusts what is in the token: the user id that is mentionned inside, scopes (set of features) that are allowed to be accessed, etc...
then it calls the controller and returns the response. If the token is expired, (a simple date that is in the token) it doesn't make any call to the controller and return a 403.
FYI, anything that is in the token can be trusted if its signature has been done by then authentication server. This system prevents the man in the middle security breach. Meaning: a guy who got a token by spying the network activity, changes what is inside this token so that he can make any call he want against your api server. Any changes that is made in this token will be detected because the signature (some sort of encrypted hash) won't match the new content anymore. And this signature, if everybody can check it in the world with the public key, only one tiers can issue it with its private key: the authentication server.
I tried to make it as complete as possible and yet still understandable for a newbie in oauth that you claim to be. Hope this helps.

OAuth2 Sending Client secret in authorization step

I'm building a web app that uses the Oauth2.0 protocol. I have registered my app with the authorization server and received my client id and client secret.
I'm now working on Authorization part and specifically using the Authorization Code grant type. In that process i'm sending the user to the authorize endpoint with the following query parameters:code, client_id, redirect_uri, scope and state. (omitting the client_secret)
The problem that i'm dealing with is i'm getting an error back saying I need to provide the client_secret as well.
I was under the impression the client_secret is not needed at this part and shouldn't be sent in this request but rather when the client sends the authorization code (along with id & secret) to obtain the access token.
So my question is, Is it wrong (against oauth 2 protocol) that the authorization server requires the client secret to be sent in the request for the authorization code?
I am not 100% sure of this, but I did some research myself and what I found is that is not a real problem not to keep the "client secret" a secret. The only possibility of someone malicious being able to get through the Authorization specs is prevented by some facts:
1. Client need to get authorization code directly from the user, not from the service
Even if user indicates the service that he/she trusts the client, the
client cannot get authorization code from the service just by showing
client id and client secret. Instead, the client has to get the
authorization code directly from the user. (This is usually done by
URL redirection, which I will talk about later.) So, for the malicious
client, it is not enough to know client id/secret trusted by the user.
It has to somehow involve or spoof user to give it the authorization
code, which should be harder than just knowing client id/secret.
2. Redirect URL is registered with client id/secret
Let’s assume that the malicious client somehow managed to involve the
user and make her/him click "Authorize this app" button on the service
page. This will trigger the URL redirect response from the service to
user’s browser with the authorization code with it. Then the
authorization code will be sent from user’s browser to the redirect
URL, and the client is supposed to be listening at the redirect URL to
receive the authorization code. (The redirect URL can be localhost
too, and I figured that this is a typical way that a “public client”
receives authorization code.) Since this redirect URL is registered at
the service with the client id/secret, the malicious client does not
have a way to control where the authorization code is given to. This
means the malicious client with your client id/secret has another
obstacle to obtain the user’s authorization code.
// copy paste of hideaki answer
Concluding
OAuth2 specify that you need to inform your secret into a request if your application is a server-side based app (different than a single-page application or mobile) which does not make its source code available. However, if you can't control your base code, like in an native mobile application, you should look for another solution.
References
OAuth2 Documentation
Bear similar stack question
Simplifying OAuth2

What is the difference between the OAuth Authorization Code and Implicit workflows? When to use each one?

OAuth 2.0 has multiple workflows. I have a few questions regarding the two.
Authorization code flow - User logs in from client app, authorization server returns an authorization code to the app. The app then exchanges the authorization code for access token.
Implicit grant flow - User logs in from client app, authorization server issues an access token to the client app directly.
What is the difference between the two approaches in terms of security? Which one is more secure and why?
I don't see a reason why an extra step (exchange authorization code for token) is added in one work flow when the server can directly issue an Access token.
Different websites say that Authorization code flow is used when client app can keep the credentials secure. Why?
The access_token is what you need to call a protected resource (an API). In the Authorization Code flow there are 2 steps to get it:
User must authenticate and returns a code to the API consumer (called the "Client").
The "client" of the API (usually your web server) exchanges the code obtained in #1 for an access_token, authenticating itself with a client_id and client_secret
It then can call the API with the access_token.
So, there's a double check: the user that owns the resources surfaced through an API and the client using the API (e.g. a web app). Both are validated for access to be granted. Notice the "authorization" nature of OAuth here: user grants access to his resource (through the code returned after authentication) to an app, the app get's an access_token, and calls on the user's behalf.
In the implicit flow, step 2 is omitted. So after user authentication, an access_token is returned directly, that you can use to access the resource. The API doesn't know who is calling that API. Anyone with the access_token can, whereas in the previous example only the web app would (it's internals not normally accessible to anyone).
The implicit flow is usually used in scenarios where storing client id and client secret is not recommended (a device for example, although many do it anyway). That's what the the disclaimer means. People have access to the client code and therefore could get the credentials and pretend to become resource clients. In the implicit flow all data is volatile and there's nothing stored in the app.
I'll add something here which I don't think is made clear in the above answers:
The Authorization-Code-Flow allows for the final access-token to never reach and never be stored on the machine with the browser/app. The temporary authorization-code is given to the machine with the browser/app, which is then sent to a server. The server can then exchange it with a full access token and have access to APIs etc. The user with the browser gets access to the API only through the server with the token.
Implicit flow can only involve two parties, and the final access token is stored on the client with the browser/app. If this browser/app is compromised so is their auth-token which could be dangerous.
tl;dr don't use implicit flow if you don't trust the users machine to hold tokens but you do trust your own servers.
The difference between both is that:
In Implicit flow,the token is returned directly via redirect URL with "#" sign and this used mostly in javascript clients or mobile applications that do not have server side at its own, and the client does not need to provide its secret in some implementations.
In Authorization code flow, code is returned with "?" to be readable by server side then server side is have to provide client secret this time to token url to get token as json object from authorization server. It is used in case you have application server that can handle this and store user token with his/her profile on his own system, and mostly used for common mobile applications.
so it is depends on the nature of your client application, which one more secure "Authorization code" as it is request the secret on client and the token can be sent between authorization server and client application on very secured connection, and the authorization provider can restrict some clients to use only "Authorization code" and disallow Implicit
Which one is more secure and why?
Both of them are secure, it depends in the environment you are using it.
I don't see a reason why an extra step (exchange authorization code
for token) is added in one work flow when the server can directly
issue an Access token.
It is simple. Your client is not secure. Let's see it in details.
Consider you are developing an application against Instagram API, so you register your APP with Instagram and define which API's you need. Instagram will provide you with client_id and client_secrect
On you web site you set up a link which says. "Come and Use My Application". Clicking on this your web application should make two calls to Instagram API.
First send a request to Instagram Authentication Server with below parameters.
1. `response_type` with the value `code`
2. `client_id` you have get from `Instagram`
3. `redirect_uri` this is a url on your server which do the second call
4. `scope` a space delimited list of scopes
5. `state` with a CSRF token.
You don't send client_secret, You could not trust the client (The user and or his browser which try to use you application). The client can see the url or java script and find your client_secrect easily. This is why you need another step.
You receive a code and state. The code here is temporary and is not saved any where.
Then you make a second call to Instagram API (from your server)
1. `grant_type` with the value of `authorization_code`
2. `client_id` with the client identifier
3. `client_secret` with the client secret
4. `redirect_uri` with the same redirect URI the user was redirect back to
5. `code` which we have already received.
As the call is made from our server we can safely use client_secret ( which shows who we are), with code which shows the user have granted out client_id to use the resource.
In response we will have access_token
The implicit grant is similar to the authorization code grant with two distinct differences.
It is intended to be used for user-agent-based clients (e.g. single page web apps) that can’t keep a client secret because all of the application code and storage is easily accessible.
Secondly instead of the authorization server returning an authorization code which is exchanged for an access token, the authorization server returns an access token.
Please find details here
http://oauth2.thephpleague.com/authorization-server/which-grant/
Let me summarize the points that I learned from above answers and add some of my own understandings.
Authorization Code Flow!!!
If you have a web application server that act as OAuth client
If you want to have long lived access
If you want to have offline access to data
when you are accountable for api calls that your app makes
If you do not want to leak your OAuth token
If you don't want you application to run through authorization flow every time it needs access to data. NOTE: The Implicit Grant flow does not entertain refresh token so if authorization server expires access tokens regularly, your application will need to run through the authorization flow whenever it needs access.
Implicit Grant Flow!!!
When you don't have Web Application Server to act as OAuth Client
If you don't need long lived access i.e only temporary access to data is required.
If you trust the browser where your app runs and there is limited concern that the access token will leak to untrusted users.
Implicit grant should not be used anymore, see the IETF current best practices for details. https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-18#section-2.1.2
As an alternative use a flow with response type code; for clients without possibility to securely store client credentials the authorization code with PKCE flow should be your choice.
From practical perspective (What I understood), The main reason for having Authz code flow is :
Support for refresh tokens (long term access by apps on behalf of User), not supported in implicit: refer:https://www.rfc-editor.org/rfc/rfc6749#section-4.2
Support for consent page which is a place where Resource Owner can control what access to provide (Kind of permissions/authorization page that you see in google). Same is not there in implicit . See section : https://www.rfc-editor.org/rfc/rfc6749#section-4.1 , point (B)
"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"
Apart from that, Using refresh tokens, Apps can get long term access to user data.
There seem to be two key points, not discussed so far, which explain why the detour in the Authorization Code Grant Type adds security.
Short story: The Authorization Code Grant Type keeps sensitive information from the browser history, and the transmission of the token depends only on the HTTPS protection of the authorization server.
Longer version:
In the following, I'll stick with the OAuth 2 terminology defined in the RFC (it's a quick read): resource server, client, authorization server, resource owner.
Imagine you want some third-party app (= client) to access certain data of your Google account (= resource server). Let's just assume Google uses OAuth 2. You are the resource owner for the Google account, but right now you operate the third-party app.
First, the client opens a browser to send you to the secure URL of the Google authorization server. Then you approve the request for access, and the authorization server sends you back to the client's previously-given redirect URL, with the authorization code in the query string. Now for the two key points:
The URL of this redirect ends up in the browser history. So we don't want a long lived, directly usable access token here. The short lived authorization code is less dangerous in the history. Note that the Implicit Grant type does put the token in the history.
The security of this redirect depends on the HTTPS certificate of the client, not on Google's certificate. So we get the client's transmission security as an extra attack vector (For this to be unavoidable, the client needs to be non-JavaScript. Since otherwise we could transmit the authorization code via fragment URL, where the code would not go through the network. This may be the reason why Implicit Grant Type, which does use a fragment URL, used to be recommended for JavaScript clients, even though that's no longer so.)
With the Authorization Code Grant Type, the token is finally obtained by a call from the client to the authorization server, where transmission security only depends on the authorization server, not on the client.

can Oauth information flow from client to server then used by the server directly?

Hello
My scenario is the following.
Client Application (on mobile phone) connects to Facebook via normal authentication process.
User gives consent to the application to access profile, gets back authorization code for the user.
With that code, plus application id and secret, the client gets an access token to access the information.
Can the authorization code be passed to a web service, which in turn does a call to Facebook to obtain an access token the same way?
I am not sure that is possible because reading documentation it looks like the access token API requires a redirect uri as a parameter.
Here instead, there would be a web service call waiting to complete.
Hope this is not confusing... :)
thanks in advance
"I am not sure that is possible because reading documentation it looks
like the access token API requires a redirect uri as a parameter."
The spec says
redirect_uri (of the access-token request):
REQUIRED, if the "redirect_uri" parameter was included in the
authorization request ... their values MUST be identical.
technically, the client can pass the server the authorization-code and the "redirect-uri", so the server makes the call with the same redirect-uri as the client, and if you control both ends it might work. However, the tricky part is that the client must also send the server the client-id and the client-secret. And if that happens, it contradicts all the idea of oAuth2.

Resources