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.
Related
If you request a token from the server (with the same credentials and within the lifespan of an old token) should it either:
return a fresh token every time
return the same token with a shorter lifespan
something else / depends on
Is it depending on whether you use a refresh token?
Can you please reference the OAuth 2 RFC in your answer ?
The OAuth 2.0 Authorization Framework is a framework that allow a Resource Owner to CONSENT to allow DELEGATION of their permissions to access a Resource Server to another party (OAuth Client).
The Authorization Request is performed by the OAuth Client and is fulfilled by the Authorization Server only after obtaining CONSENT from the Resource Owner by the Authorization Response (which includes a Access Token).
The Access Token is a Bearer Token with a limited lifetime.
The refresh Token, if used, by the client to requests a new access token by authenticating with the authorization server and presenting the refresh token. The client authentication requirements are based on the client type and on the authorization server policies.
The "same" Access Token is never returned or reused by the Authorization Server.
Reading and following the Security Considerations with any Authentication or Authorization Protocols is a must. Most breaches are caused by implementation errors rather than protocol errors.
You should Tell us what you have tried and show logs or results and Read:
https://stackoverflow.com/help/how-to-ask
According to RFC6749 Chapter 4.1.1: https://www.rfc-editor.org/rfc/rfc6749#section-4.1.1
In the specification of Authorization Request for Authorization Code grant,
Only client_id is required for Authentication. Since client type could be public, then that means anyone can get the Authorization Code, and then use it in Access Token Request - https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3. Here you only need to supply client_id (Which is public), Authorization Code (Which can obtain with NO authentication), redirect_uri and grant_type (Not for authentication/authorization purpose), and then you will be able to obtain an access token!
My question is, why there is NO any mandatory authorization/authentication procedure for this type of grant, then what is the purpose of having this type of grant? Same thing in Implicit grant.
The client authentication is not mandatory only for the clients that are registered as public client like Mobile Native Application. The Mobile Application can not hold client secret securely, hence it is not mandatory in authorization code grant and implicit grant. The client application like web application which can hold client secret securely in the server, such clients should be registered as confidential client. The clients that are registered as confidential client should present both client id and secret for client authentication.
OAuth2 server issues an authorization code after user authentication and after user approving consent with delegating rights to the client (identified by client_id). The auth code is then sent as a parameter to a client's registered redirect URI. So I don't know what you mean by "anyone can get the Authorization Code".
Public clients should be used with PKCE OAuth2 extension. Which serves as a one-time password. So even if an auth code get stolen, it cannot be exchanged for tokens without knowing the code_verifier parameter of the token endpoint.
If an attacker creates a malicious application using someone else's client_id (pretending to be the client), the auth code will still be sent to the client's redirect URL. If the attacker gets hold of this URL handler, then it's probably a problem beyond the scope of the OAuth2 protocol.
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.
OAuth 2.0 specifies two client types:
public (client_id)
confidential (client_id:client_secret)
and section 2.2 says:
The client identifier is not a
secret; it is exposed to the resource owner and MUST NOT be used
alone for client authentication.
While it is clear to me that public clients are primarily used for the implicit flow, there is more to this than it seems. When performing the auth code flow, we first request the authorization endpoint with our client_id, no secret required. Then, after getting the user's consent and the authorize code, we request the token endpoint. According to spec, we are able to request this endpoint without a client_secret:
client_id
REQUIRED, if the client is not authenticating with the
authorization server as described in Section 3.2.1.
If the client type is confidential or the client was issued client
credentials (or assigned other authentication requirements), the
client MUST authenticate with the authorization server as described
in Section 3.2.1.
...
The authorization server MUST:
...
o ensure that the authorization code was issued to the authenticated
confidential client, or if the client is public, ensure that the
code was issued to "client_id" in the request,
So basically this section says that we are able to request this endpoint without a client secret. Now, it doesn't say anything about refresh tokens other than that those may be included in the request.
Refreshing an access token mentions:
Because refresh tokens are typically long-lasting credentials used to
request additional access tokens, the refresh token is bound to the
client to which it was issued. If the client type is confidential or
the client was issued client credentials (or assigned other
authentication requirements), the client MUST authenticate with the
authorization server as described in Section 3.2.1.
So basically we're allowed to refresh the access token without client authentication.
Now, what confuses me is that the implicit flow does not allow issuing of refresh tokens:
The authorization server MUST NOT issue a refresh token.
It doesn't say explicitly why we can't do that, only that we're not allowed to. My reasoning is that this isn't allowed because the client can't be trusted. But since the authorize code flow is allowed for public clients, why do we actually need the implicit flow, if the same thing can be achieved with a public client, plus getting a refresh token?
I'd be very glad if someone could clarify this.
You are allowed to request/refresh access token without client secret at your own risk. Or we can say it depends on your security requirements. The spec only clarifies client authentication for confidential clients, basically if the client is confidential. it MUST be authenticated by the server.
For public clients, the spec says:
The authorization server MUST NOT issue client passwords or other
client credentials to native application or user-agent-based
application clients for the purpose of client authentication.
So public clients can't even have a secret to be authenticated with. And then the spec also says:
When client authentication is not possible, the authorization server
SHOULD employ other means to validate the client's identity -- for
example, by requiring the registration of the client redirection URI
or enlisting the resource owner to confirm identity. A valid
redirection URI is not sufficient to verify the client's identity
when asking for resource owner authorization but can be used to
prevent delivering credentials to a counterfeit client after
obtaining resource owner authorization.
Also you may look at PKCE.
Get back to your question, I think you are misunderstanding:
According to spec, we are able to request this endpoint without a client_secret.
Not quite right, you must authenticate confidential client and you can't authenticate public client using a client secret (it does not have one).
The authorization server MUST NOT issue a refresh token.
I think it is all matter of security. In implicit grant, we are operating under a presumably unsafe environment. Exposing refresh token could harm your system, since we already expose access token in this grant type (Please read security consideration for access token).
But since the authorize code flow is allowed for public clients, why do we actually need the implicit flow, if the same thing can be achieved with a public client, plus getting a refresh token?
They are meant for completely different use cases. From https://oauth.net/2/grant-types/implicit/
The Implicit grant type is a simplified flow that can be used by public clients, where the access token is returned immediately without an extra authorization code exchange step.
It is generally not recommended to use the implicit flow (and some servers prohibit this flow entirely). In the time since the spec was originally written, the industry best practice has changed to recommend that public clients should use the authorization code flow with the PKCE extension instead.
Lastly, I suggest you to play with this site to get a better understanding of different grant types.
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.