We are working on the use-case where we need to use authorization using OAuth Grant Type JWT Bearer Flow.
At a high level, what we know is that the grantype( grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer) should be passed along with the jwt assertion for obtaining the access token.
Questions :
1. What kind of use-case fits for this kind of grant type ?
2 .Who would create a jwt assertion ? Is it something custom, that should be implemented based on the successful authentication of a user.
3.What are the validations that should be done on JWT assertions and access tokens?
Can anyone explain the whole flow with sample.
This grant type flow can be used for the following cases:
The JWT is issued by the client itself: this claim iss (issuer) and sub (subject) refer to the client ID. As the subject is the client, it can be compared to the Client Credentials grant type flow. This is very useful for clients that don’t want to expose their credentials.
The JWT is issued by a trusted third party (trusted by the authorization server): in this case the subject could be the client itself, another client or a end user.
The section 3 of the RFC7523 is quite clear regarding the claims to check:
The iss: the issuer of the token (client or trusted 3rd party)
The aud: should contain at least the authorization server. For case 2., should also contain the client ID
The sub: the subject corresponds to the resource owner
The exp: expiration time
If present, other claims such as the iat, nbf, jti or custom claims should be checked and understood.
The signature of the JWT depending on the issuer.
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.
I am using a variant of the in-memory clients defined in the reference IdentityServer4 demo project and after I log into the Identity Server and get redirected, the URI is such that the id_token and access_token are the same exact JWT.
Is this a sensible behavior? Why would you want the id_token and access_token to be the same, ever? Maybe if you don't care about the access_token?
Not sure what you mean same exact JWT. But both access token and ID token can come as JWT tokens.
One good example is OAuth flow of Azure AD. According to the document successful token response return an access token and an id token (yes, Azure does send one for OAuth auth. code flow) both in JWT format (reference). But their contents could be different. For example, one could be a signed JWT and other could not be.
Reason for the usage of JWT is due to self-contained nature of them. For example, token validations can be done easily from client application end as well as protected API end.
Usually if both access token and ID token are JWTs they could be differ by claims. For example audience claim ("aud") could be different depending on intended audience of token.
I'm building a system with OIDC and OAuth 2.0 (using Auth0), and I'm unsure how to properly use the id_token and access_token. Or rather, I'm confused about which roles to assign to the various services in my setup.
I have a fully static frontend-application (single-page app, HTML + JS, no backend) that ensures that the user is authenticated using the implicit flow against Auth0. The frontend-application then fetches data from an API that I am also building.
Now, which is right?
The frontend SPA is the OAuth client application
My API service is an OAuth resource server
...or:
The frontend and my API service are both the client application
If both my frontend and backend API can be considered to be the client, I see no real harm in using the id_token as the bearer token on requests from my frontend to my backend - this is appealing because then I can simply verify the signed token on the backend, and I have all the information about the user that I need. However, if my API is considered a resource server, I should probably use the access_token, but then I have to connect to Auth0's servers on every API request to both verify the token, and get basic user info, won't I?
I've read this which seems to suggest that the access_token is the only valid token for use with my API. But like I said, I'm not sure about the roles of the individual services. And using the id_token is tempting, because it requires no network connections on the backend, and contains information I need to extract the right data.
What is the right way to go about this?
I like this Medium post about the difference, all cred to this author.
https://medium.com/#nilasini/id-token-vs-access-token-17e7dd622084
If you are using Azure AD B2C like I am you can read more here:
https://learn.microsoft.com/en-us/azure/active-directory-b2c/openid-connect
ID Token
You will get id token if you are using scope as openid. Id token is specific to openid scope. With openid scope you can get both id token and access token.
The primary extension that OpenID Connect makes to OAuth 2.0 to enable End-Users to be Authenticated is the ID Token data structure. The ID Token is a security token that contains Claims(claims are name/value pairs that contain information about a user) about the Authentication of an End-User by an Authorization Server when using a Client, and potentially other requested Claims. The ID Token is represented as a JSON Web Token (JWT)
{
"iss": "https://server.example.com",
"sub": "24400320",
"aud": "s6BhdRkqt3",
"nonce": "n-0S6_WzA2Mj",
"exp": 1311281970,
"iat": 1311280970,
"auth_time": 1311280969,
"acr": "urn:mace:incommon:iap:silver"
}
The above is default JWT claims, in addition to that, if you requested claims from service provider then you will get those as well.
An id_token is a JWT, per the OIDC Specification. This means that:
identity information about the user is encoded right into the token
and
the token can be definitively verified to prove that it hasn't been
tampered with.
There's a set of rules in the specification for validating an id_token. Among the claims encoded in the id_token is an expiration (exp), which must be honored as part of the validation process. Additionally, the signature section of JWT is used in concert with a key to validate that the entire JWT has not been tampered with in any way.
Access Tokens
Access tokens are used as bearer tokens. A bearer token means that the bearer (who hold the access token) can access authorized resources without further identification. Because of this, it's important that bearer tokens are protected. If I can somehow get ahold of and "bear" your access token, I can pretend as you.
These tokens usually have a short lifespan (dictated by its expiration) for improved security. That is, when the access token expires, the user must authenticate again to get a new access token limiting the exposure of the fact that it's a bearer token.
Although not mandated by the OIDC spec, Okta uses JWTs for access tokens as (among other things) the expiration is built right into the token.
OIDC specifies a /userinfo endpoint that returns identity information and must be protected. Presenting the access token makes the endpoint accessible.
http://openid.net/specs/openid-connect-core-1_0.html
https://connect2id.com/learn/openid-connect#cool-id-token-uses
https://developer.okta.com/blog/2017/07/25/oidc-primer-part-1
Your frontent is your OAuth client application, once it stores the token it can take actions on the OAuth flow. And your API service is resource server, because it accepts the access_token issued by your identity server.
Also I would say that your id_token stands for the identification of the logged user and may contain sensitive data for your app. The access_token is standing as your credential to access a resource.
At the end you will use an access_token to request a resource, and then if you need specific data from the logged in user (resource owner), you may request the ID token from the token endpoint.
In my opinion, the first approach is correct. Your SPA is the client application and your APIs are resource servers.
I would suggest you limit the use of id_token till your SPA only. You can use the basic information present in the id token (like username and email) to display user information within your UI. If you can generate access tokens as JWTs too then your API can validate the access tokens without going to the Identity provider. You can include roles (or similar) in your access token to get authorization information in your access token.
I was also wondering if I need to talk to the IdP on every request if I'm using the tokens received from the IdP. I ended up with the following setup:
Only the backend talks to the IdP, the frontend does not.
Upon the IdP callback the backend issues a JWT for the frontend.
User session and frontend-backend communication is managed entirely by my app using the JWT token.
Check this article: OAuth2 in NestJS for Social Login (Google, Facebook, Twitter, etc)
and this repo: https://github.com/thisismydesign/nestjs-starter
and this question: OAuth2 flow in full-stack NestJS application
The id_token is an cryptographically encoded token for authentication. The OP (the auth provider) is the one that generates it and the RP (relying party or the resource) will eventually re-present the token to the OP to counter validate when handed over by the client. In short the id_token is tied to authn workflow.
The access_token enables resource access. It does subsume the userinfo i.e., the id_token or any other principal on whose behalf the access is being requested. So this token includes both user claims plus claims to groups that are authorized. In short the access_token is tied to your authz workflow.
The OAuth2 JWT Profile introduces the possibility to use JWTs both as authorization grant and as client authentication.
The JWT client authentication feature is independent of a certain grant type, and can be used with any grant type, also the client credentials grant.
However, using the JWT grant type seems to do exactly the same as using the client credentials grant with JWT client authentication, except that the syntax is slightly different.
In both cases the client contacts the token endpoint to get an access token:
POST /token.oauth2 HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=[JWT]
vs
POST /token.oauth2 HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=[JWT]
A slightly different perspective on the great answer by Josh C: as it happens both the client authentication and the grant credentials can be expressed as JWTs but the semantics behind them are different.
It is about separation of concerns: clients authenticate with a credential that identifies them i.e. they are the so-called subject whereas they use grants that were issued to them i.e. they are the so-called audience. Or as version 12 of the draft spec (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-jwt-bearer-12) says:
The JWT MUST contain a "sub" (subject) claim identifying the
principal that is the subject of the JWT. Two cases need to be
differentiated:
A. For the authorization grant, the subject typically
identifies an authorized accessor for which the access token
is being requested (i.e., the resource owner or an
authorized delegate), but in some cases, may be a
pseudonymous identifier or other value denoting an anonymous
user.
B. For client authentication, the subject MUST be the
"client_id" of the OAuth client.
Probably very little. The way a client is identified and the way auth grants are requested are two different notions in OAuth, so the questions address those notions separately:
Can a client authenticate with an authorization server using a JWT? Yes.
Can a client make a grant request using a JWT? Yes.
The spec seems to hint that the separation is simply a design decision, deferring to policy makers to find what scenarios are valuable to them:
The use of a security token for client authentication is orthogonal to and separable from using a security token as an authorization grant. They can be used either in combination or separately. Client authentication using a JWT is nothing more than an alternative way for a client to authenticate to the token endpoint and must be used in conjunction with some grant type to form a complete and meaningful protocol request. JWT authorization grants may be used with or without client authentication or identification. Whether or not client authentication is needed in conjunction with a JWT authorization grant, as well as the supported types of client authentication, are policy decisions at the discretion of the authorization server.
One concrete possibility: The separation could allow for an authorization server to set up different policies along client types. For example, in the case of a public client (like a mobile app), the server should not accept the client creds grant type. Instead, the server could accept the JWT grant type for public clients and issue a token of lesser privilege.
Other than that, I would suppose that the design simply offers a degree of freedom for clients and servers to pivot around--keep this part of the existing handshake the same while migrating this part--as the need arises.
I have been reading this spec for using JWT (JSON web tokens) with OAuth.
In 2.1 and 2.2, it says that JWTs can be used as Authorization Grants or Client Authentication.
From my understanding, authentication is to identify something (this user is who he claims to be) and authorization is to check if a user is allowed to do what he requested.
JWT as authorization grant makes sense, because the request is implicit identified by being signed. Most APIs that support this method uses JWT as an authorization grant. See salesforce and google.
This is where it gets confusing for me. Why is it that there need for JWT Authentication as a separate thing? Under what situations/use cases will there be a need for JWT Authentication?
1. JWT as Authorization Grant
In this case the client obtained a JWT in some unspecified way that it can present to the Authorization Server on the token endpoint to obtain an access token (and optional refresh token) on behalf of the party who issued the JWT. This may be the end-user (or Resource Owner) himself but the JWT can also be signed by a trusted 3rd-party in general (other users or organizations). This can apply to public as well as confidential clients.
Note that this substitutes the more regular Authorization Code Grant where the code is tightly bound to the Authorization Server with a more flexible mechanism where grants (JWTs) can potentially be issued by 3rd parties so that enables a federated system that works across administrative boundaries.
The JWT would be short-lived and for one-time use only.
2. JWT as Client Authentication
In this case the client presents a JWT to the on the token endpoint as part of a flow for an arbitrary grant type (possibly even the JWT Authorization Grant!) that requires interaction with the token endpoint; a typical example is the Authorization Code grant where the client receives a code as consented by the Resource Owner that needs to be exchanged for an access token (and optional refresh token) at the token endpoint and the client authenticates itself with the JWT.
This implies/defines/requires a confidential client and the JWT substitutes the more regular (and difficult to manage) client secret.
The JWT would be long-lived and used many times.