I'm building a native Mobile App that connects to a REST API.
I'm looking at this demo oAuth App to use as a guide for my Authentication/Authorisation layer.
When the user comes to the App for the first time I want to provide them with a username and password box.
After they hit submit I want to the App to be supplied with an access token, and a list of permissions (scopes?) that the user is permitted to perform.
I've read lots about the oAuth2 specification but am confused as to which flow to use.
I can't use the Resource Owner Password Credentials Grant because I can't trust the Native App with the Client Secret.
I don't want to use the Implicit Grant, as I don't want to present the user with a "Do you authorise this App?" web window.
I've looked into the JWT Bearer flow, and think it might be what I need as it doesn't require the Client ID/Secret. However I can't find any examples where this flow returns permissions (scopes?) that the user can perform.
Edit #1:
I am confused as to the use of Scope. The specification says-
The authorization server MAY fully or partially ignore the scope
requested by the client, based on the authorization server policy or
the resource owner's instructions. If the issued access token scope
is different from the one requested by the client, the authorization
server MUST include the "scope" response parameter to inform the
client of the actual scope granted.
If the client omits the scope parameter when requesting
authorization, the authorization server MUST either process the
request using a pre-defined default value or fail the request
indicating an invalid scope. The authorization server SHOULD
document its scope requirements and default value (if defined).
From that can my Client request a list of ALL Scopes, and then the Authorization Server give a Response with the ones the User actually has?
Thanks for your help, Tom.
You list two assumptions about OAuth 2.0 flows that are not true:
the Resource Owner Password Credentials Grant can be used with a public client i.e. a native app that doesn't have a client secret
usage of the Implicit Grant does does not imply that it requires explicit consent; that is to the discretion of the Authorization Server implementation; in an enterprise setting or a setting where the same party controls the client and the Authorization Server, that may be omitted
But since the Implicit grant comes with security considerations, for native apps it is typically better to use the Authorization Code grant.
Scopes are a way for the Client to request certain permissions. The Resource Owner can grant the Client permissions that relate to these scopes (explicitly or implicitly). Since the Client will change its behaviour based on what permissions it gets, it is assumed that there's some shared understanding between Client, Resource Server and Authorization Server about what Scopes related to. There's no predefined semantics in the OAuth 2.0 specification, it is up to the implementation.
Related
Roles and terminology used in this question are the same as RFC 6749.
Description of the use-case
I want to allow a trusted OAuth client to ask authorization server to issue an access token on behalf of the resource owner without his consent (and without involving neither him nor his agent in the flow).
Investigations
As far as I know, there is not any grant matching this flow in RFC 6749, Section 4:
Grant
Suitable
Why
Authorization Code GrantRFC 6749, Section 4.1
No
It involves both Resource Owner and User-Agent.
Implicit GrantRFC 6749, Section 4.2
No
It also involves both Resource Owner and User-Agent.
Resource Owner Password Credentials GrantRFC 6749, Section 4.3
No
It might work if we knew the password of the resource owner, but we don't.
Client Credentials GrantRFC 6749, Section 4.4
No, but..
It doesn't involve the Resource Owner or his User-Agent but it's not granting access on behalf of a user.
Token ExchangeRFC 8693, Section 2
No, but..
It requires an initial token (named subject_token) which doesn't exist in my scenario.
Client Credentials
The Client Credentials grant is promising because it allows a client to access protected resources owned by a resource owner without involving him. Although, in my understanding, it's not on behalf of the resource owner. Quoting the RFC 6749, Section 4.4:
The client can request an access token using only its client credentials (...) when the client is requesting access to the protected resources under its control, or those of another resource owner that have been previously arranged with the authorization server (...).
Therefore, with access token returned by Client Credentials grant, it is for instance impossible to assign a sub claim value as defined in RFC 7662, Section 2.2: OAuth 2.0 Token Introspection > Introspection Response (cf. RFC 7519, Section 4.1.2: JWT ).
Token Exchange
This grant has been suggested by #Kaankom. See #Kaankom 's answer.
The RFC 8693 defines how to obtain a security token employing impersonation and delegation. It sounds like the perfect grant for my use-case but this grant requires as input a subject_token parameter which "represents the identity of the acting party." The RFC says:
Typically, this will be the party that is authorized to use the requested security token and act on behalf of the subject.
I don't have this token. However, I could maybe forge a new one (see Solution 5).
Non-standard solutions
Solution 1: A new OAuth grant
RFC 6749, Section 4.5 allow us to implement a new grant type. Similar to Client Credentials, this brand new grant would REQUIRE an additional parameter in his Access Token Request. This parameter would define the resource owner identifier for which the client will act on behalf of the resource owner.
Solution 2: Tweak the Client Credentials grant
Instead of implementing a new OAuth grant (cf. solution 1), we could instead add an optional parameter in existing Client Credentials grant. If specified, the authorization server should validate that the client is allowed to act on behalf of the requested resource owner (specified by the new parameter).
Solution 3: Tweak the Authorization Code grant
Using the Authorization Code grant, we could bypass steps A, B and C as defined in RFC 6749, Section 4.1 and let the client request an access token without having to add a code or a redirect_uri but with its client credentials and an additional parameter which define the resource owner.
Solution 4: Implement it out of OAuth
Browsing the internet, you might find implementations which are bypassing the OAuth mechanism and its access_token. For instance, in article "How to Convert from APIKey to OAuth 2.0 Client Credentials", they are using an extra HTTP header Acting-For on resource server calls.
Solution 5: Token Exchange grant with self-forged token
The Token Exchange grant requires a subject_token but (as far as I know) it doesn't define the policy that the authorization server SHOULD apply based on this token. Therefore, it would be theorically possible for the client to forge an unsigned JWT with the target subject (sub claim) and obtain a signed JWT in return. It looks promising but requires more investigation.
Notes
I intentionally not named the parameter used in solution 1, 2 and 3. However OpenID Connect Core 1.0, Section 3.1.2.1/Section 4 is defining an optional parameter named login_hint which "hint to the Authorization Server about the login identifier the End-User might use to log in". However sub might be another good proposal.
The Use Case you described sounds like impersonation.
Take a look at this: RFC 8693 - Token Exchange
You've not really described the use case / requirement, though I will describe something that may be in line with your use case and give you some ideas. Perhaps thinking more in terms of claims and API aauthorization will solve your problem in a standard way?
CORPORATE ASSETS USE CASE
Sometimes the assets don't belong to the end user and an entity has permissions to operate on a subset of users:
An investment bank may be able to update certain details for its employees in a wider trading system
A doctor's surgery may be able to update medical details for its patients in a system that contains nationwide data
In OAuth terms the bank / surgery would use the client credentials grant, and be identified by either a client ID or possibly a custom claim in the token issued.
If bank A tried to use their access token to update details for a trader at bank B, it would fail API authorization and they would receive an HTTP response with status 404, meaning data not found for caller.
It would not be natural though for bank A to get an access token for Jane Doe when updating that record, since that is not the caller identity. At an auditing level:
The Authorization Server would indicate that a token was issued to bank A
The API would indicate that the record for Jane Doe was updated by bank A.
The API could have many intricate domain specific rules around which type of data updates are allowed. These are usually managed in the API logic, while the access token contains only key caller identity information that the API can digitally trust before applying rules.
For more on this topic see our Claims Best Practices article.
Introduction
The following answer describes the flow, grant and parameters that may be used to allow a trusted OAuth client to obtain an access_token without the prior resource owner consent. This method is using the Token Exchange grant (defined in RFC 8693) in an impersonation scenario where the client would have to forge an unsecured subject_token and exchange it for a secured access_token. This method assumes that the authorization server produces and consumes JWT (RFC 7519). It would not work with opaque token.
Sequence Diagram
Step 1: Forge the initial JWT
In this first step, the client forges an initial unsecured JWT token (RFC 7519, Section 6). This JWT MUST contain at least the subject (sub) claim with, as value, the resource owner or another subject that the client want to impersonate.
Step 2: The client requests to exchange the initial unsecured JWT for a secured access token
The client exchanges the JWT forged in step 1 for a secured access token. According to RFC 8693 Section 2.1, the client sends a Token Exchange request with the following headers/parameters:
the Authorization header contains the client credentials (client id and client secret), following the Basic Authentication scheme.
the body parameter grant_type specify the grant type we want to use: token_exchange
the body parameter subject_token contains the JWT forged in step 1
the body parameter subject_token_type specify the subject token type we forged: an access_token (which is actually a JWT)
This is the bare minimum that the client MUST send. Although it SHOULD probably specify the audience, the target resource server and the list of scope.
Step 3: The authorization server returns the access token
According to its policy, the authorization server identifies the client as trusted and therefore allows to generate an access_token with unsecured subject_token in input. The subject defined in the subject_token (sub claim) is recycle in the generated access_token.
The authorization server will also add an Actor claim (act) according to RFC 8693, Section 4.1. The value of this claim is a JSON object with another sub key and the client id as value.
Step 4: The client requests a resource
In this example, the client requests a "personal" resource (/my/resource) with the access token. The sub claim inside the JWT is used to identify the "my" aka the subject.
Step 5: The resource is returned with an impersonation of the subject
That's it.
Disclaimer
I never implemented or tested this solution. It obviously requires a few changes in your authorization server and its policy. No security audit has been performed. Be careful with this flow. Confirmation from OAuth experts should be required prior to implementation.
From my understanding: -
The scopes that an oauth client can obtain are registered against the client on the Authorization Server .
The grant types that a client can use are registered against the client on the Authorization Server .
Resources are configured to allow requests containing access tokens that are associated with certain scopes.
Is there a mechanism in vanilla OAuth where the grant type in addition to the scopes are used when restricting an endpoint?
For example, given Client A with scopes=organizations, images and grant types=client credentials, auth code:
(at token creation)
For Client A to obtain an access token for ‘organizations’ scope, only client credentials grant type can be used.
For Client A to obtain an access token for ‘images’ scope, only auth code grant type can be used.
Or (when the resource endpoint it calls)
When the /organisation endpoint is called with an access token containing the expected ‘organization’ scope, only allow the request if the client credentials grant type was used to obtain the access token (fail if any other grant type was used).
When the /images endpoint is called with an access token for containing the expected ‘images’ scope, only allow the request if the auth code grant type was used to obtain the access token (fail if any other grant type was used).
As far as I know scopes are only limited by what is registered for a client.
The only way I can think of achieving the above would be to have two client registrations (e.g. b, c) for the same actual client (A) and configure client ‘b’ for client credentials grant type and organizations scope and client ‘c’ for auth code grant type and images scope.
Update
One option would be along OIDC lines to add a roles scope which would mean that the roles claims would be added to the access token. The access token could then be inspected to see whether the role is a third party (client credentials grant) or user (auth code grant).
I would still be interested to know if there is anything specifically built into oauth to restrict by grant type.
Tokens don't generally record grant information, and really the requirement is to be able to control access per application and based on the caller's rights.
I would always configure different OAuth Clients for different grant types - since these are different logical clients and can never share a session.
A few possible options:
OPTION 1. Use multiple APIs each with a different audience and configure different audiences for different OAuth Clients if that is supported by your Authorization Server
OPTION 2. An API endpoint can potentially check the client ID in access tokens against a list of allowed client IDs - though this is not a good long term option
OPTION 3. Use OAuth just to identify the caller and then look up rights for the caller that are stored and managed in your application data. This is almost always the best long term option.
OAuth only provides high level mechanisms for authorization and when you get into deeper domain specific authorization (eg what a role means or rules such as checking sufficient funds) it will not help you.
I like your idea of using roles, and from experience I would manage them like this:
Do high level OAuth authorization first via scopes etc
Identify the caller from the token's claims
Look up the caller's role(s) in your application data
Enforce the role's authorization rules in your API logic
Our team is starting to build out a SMART on FHIR (SoF) application. SoF uses OAuth2 access_tokens to represent authorizations. Our app is using the code grant to get a token (https://oauth2.thephpleague.com/authorization-server/auth-code-grant/).
I'm pretty new to OAuth2 (used to SAML) and have been reading up on the standard. I think we may be conflating what the access_token is intended to represent.
Is the intent in OAuth2 that the access_token represents the permissions the resource owner (end user) has granted to the client (web application) to perform on their behalf?
Or is the intent to rely that the resource owner (end user) is allowed to preform certain operations?
For example say the auth token request has a scope called 'contacts-update'. If we get an access_token back with this scope, does that mean the user has allowed the application to attempt to update contacts (on their behalf) or does it mean that the user has the underlying requirements (they are in the update contacts role) to be able to update contacts?
As you wrote, the OAuth2 access token represents a permission delegation from a resource owner to a client (application), so the client can perform operations on behalf of the resource owner. That's also why there is a consent page - the user agrees on giving the application permissions (scopes) it requested.
Sometimes, people want to use OAuth2 as a central authentication server and a permission configuration for their applications. They want each application to see all permissions the user has configured for it. Then it doesn't make sense for application to ask for specific scopes, but to configure the OAuth2 server to return all relevant for that application (identified by a client_id). But I don't think this is the intended way of usage and the OAuth2 specification doesn't cover this scenario.
OAuth2 can also be used for authentication only, if it supports OpenID Connect extension. Then applications can ask for ID tokens. ID token proves identity of a user and the permissions are handled in each application separately.
Why would anyone use OAuth 2 with this kind of grant? I mean, if the client already has the name and password of the Resource Owner, why not just authenticate as the Resource Owner using whatever authentication vehicle is used by the Resource Server?
I do not understand the rationale here. Can someone explain it?
As the spec mentions, the Resource Owner Password Credentials grant is for migration purposes and applicable only in scenario's where (typically) the Client and the Authorization Server are controlled by the same party, https://www.rfc-editor.org/rfc/rfc6749#section-1.3.3:
The resource owner password credentials (i.e., username and password)
can be used directly as an authorization grant to obtain an access
token. The credentials should only be used when there is a high
degree of trust between the resource owner and the client (e.g., the
client is part of the device operating system or a highly privileged
application), and when other authorization grant types are not
available (such as an authorization code).
It allows for utilizing a standard token and protocol on the leg between Client and Resource server (e.g. OAuth 2.0 Bearer Token), whilst using a "to-be-deprecated" way of getting a token between Client and Authorization Server. https://www.rfc-editor.org/rfc/rfc6749#section-10.7:
The resource owner password credentials grant type is often used for
legacy or migration reasons. It reduces the overall risk of storing
usernames and passwords by the client but does not eliminate the need
to expose highly privileged credentials to the client.
This grant type carries a higher risk than other grant types
because it maintains the password anti-pattern this protocol seeks
to avoid. The client could abuse the password, or the password
could unintentionally be disclosed to an attacker (e.g., via log
files or other records kept by the client).
Additionally, because the resource owner does not have control over
the authorization process (the resource owner's involvement ends when
it hands over its credentials to the client), the client can obtain
access tokens with a broader scope than desired by the resource
owner. The authorization server should consider the scope and
lifetime of access tokens issued via this grant type.
The authorization server and client SHOULD minimize use of this
grant type and utilize other grant types whenever possible.
I will provide another point of view.
OAuth 2.0 is a great protocol for common web applications. Some applications, however, use much stronger authentication / authorization mechanism. For these cases, it makes sense to allow token establishment using a strong method. An example of such application can be a banking API - it can use classic OAuth 2.0 flow on web (using bank's website) and strong data signatures using protocols like PowerAuth 2.0 (I am an author of this solution) for native mobile or desktop apps.
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.