Openid Connect : sharing id token between relying parties - oauth-2.0

Suppose we have 3 Relying Parties with 1 OpenID Provider (= Identity Provider). If a user wants to sign-in in the first application, he will be redirect to the identity Provider (via the Authorization Code Flow) and the first application will have at the end of the flow an id token and access token.
If the user, 10 minutes wants to sign-in to the second relying party, he will be automatically redirect to the IDP (via the Authorization Code Flow) and the IDP will recognize the user by the cookie. So the IDP will not ask the user to authenticate and at the end of the flow, the second Relying Party will have a ID Token & access token.
My question : can you confirm that the ID Token & Access Token of the second Relying Party will be different of the ID Token & Access Token of the first Relying Party ?

Yes they should be different.
In ID tokens the aud claim should contain the relying party app for whom the token is intended for.
In the access token there is usually something like a client_id claim so the Relying Party could identify which client this token was issued to - although this isn't guaranteed.
See the JWT spec for details of OpenID Connect JWT tokens.

Related

Why client authentication is NOT mandatory with Authorization Code Grant and Implicit Grant in OAuth2.0

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.

OAuth and OpenID connect uses

I've began to take interest in the OAuth 2.0 specification and am not sure if what I've understood so far is correct.
OAuth is an authorization protocol while OpenID Connect is an authentication protocol which extends OAuth.
The first deals with authorizing access to a 3rd party resource, by a client application. Example you are building some app and would like to use some other application (which is not yours to own) features (resources).
On the other hand OpenID connect, deals with authorization, authorizing some human entity by verifying his/hers identity to, for example, access a specific resource that only him/her alone has access to. Example you're a banking application and allow users to access their account but first they need to confirm their identity with an Authorization Provider.
So is it safe to say that Authorization is destined to application interaction while Authentication for human interaction ?
Your understanding on OAuth and OpenID Connect is correct. When OAuth was introduced, it define a way to obtain access tokens, which the holding party can used against an endpoint protected by OAuth access tokens. This allowed identity details to be stored in a central location (authorization server aka identity servcer) and that central location to maintain token obtaining process (which include human authentication too).
While access token are used to grant access (authorize), OpenID Connect introduced ID token that get transmitted along with access token. The ID token is there to be consumed by the client application, which is used to authenticate the end user.
Token obtaining require authentication at authorization server. Depending on the token obtaining flow (aka OAuth grant), this authentication will involve the human user. It is also possible to follow a flow which does not involve a human user. Such flow only produce an access token. And OpenID Connect can only be used when human user is involved.
Q : So is it safe to say that Authorization is destined to application interaction while Authentication for human interaction ?
If your application (client) involves and end user, then that user can involved in token obtaining flow. And you can obtain access token as well as ID Token. Then you use ID token for end user authentication. And access token is used to connect with another endpoint.
If your application does not involved an end user (ex:- A service), then you will use OAuth to obtain access token, which used against another endpoint.

OAuth2 Roles in OIDC

In OAuth2 protocol, Client (RP in terms of OIDC) application obtains an access token, which enables it to use different services (Resource server role) on behalf of a Resource Owner.
On the other hand, in the OpenID Connect protocol, Client obtains 2 tokens (access and id token). Now this Client can use the access token to fetch user claims from the UserInfo endpoint.
Does OP (Authorization server) play role of a Resource Server here (in terms of OAuth2), and Client fetches user data on behalf of a user?
How is ID token used by the Client? Does Client pass this ID token to the Resource Owner's user agent (Browser) and then, user agent stores this token to enable SSO (cookie)?
Does Client (e.g. different one than the one that obtained the ID token) has to verify the token every time user accesses it (call OP to verify it), or Client does this only first time it gets accessed by this token and then creates security context which enables it to eliminate this request for verification at OP every time? In this case, how could this security context be implemented?
What is the access token used for, except for fetching user claims and why is it sent along with ID token, when Client could use ID token to access UserInfo endoint?
First of all you must understand the purpose of tokens. Access token is a token that is good enough to access a protected resource on behalf of the end user. It is defined by OAuth 2.0 authorization framework. Now having an access token does not authenticate the end user. it simply authorize the client application to access a resource. OpenID Connect introduce the ID Token. Now this token is to be consumed by your client application. Protocol define how this to be done and if valid, your client application can authenticate the end user.
Q: Does OP (Authorization server) play role of a Resource Server here (in terms of OAuth2), and Client fetches user data on behalf of a user?
Partially correct. According to the protocol document, userinfo endpoint acts as OAuth 2.0 protected resource.
The UserInfo Endpoint is an OAuth 2.0 Protected Resource that returns Claims about the authenticated End-User. To obtain the requested Claims about the End-User, the Client makes a request to the UserInfo Endpoint using an Access Token obtained through OpenID Connect Authentication.
Q: How is ID token used by the Client? Does Client pass this ID token to the Resource Owner's user agent (Browser) and then, user agent stores this token to enable SSO (cookie)?
As mentioned previously client must validate the id token and based on that it can authenticate the end user. ID token is not connected with SSO.
Q:Does Client (e.g. different one than the one that obtained the ID token) has to verify the token every time user accesses it (call OP to verify it), or Client does this only first time it gets accessed by this token and then creates security context which enables it to eliminate this request for verification at OP every time? In this case, how could this security context be implemented?
If you are using ID token to be consumed from a protected endpoint, then token receiving party should validate it before accepting it. One may choose to create a session after a proper token validation (session must not extend the life time of the token).
Q: What is the access token used for, except for fetching user claims and why is it sent along with access token, when Client could use ID token to access UserInfo endoint?
Access token is the token your should use to access OAuth 2.0 protected resources. Once the endpoint received it, endpoint can validate the access token against token introspection endpoint exposed by the authorization server (Protocol definition of introspection). And with Openid Connect, defining of userinfo endpoint let any party with valid id token to consume it.
I don't see how you can be confused about that if you've read the RFCs.
You want to think of identity as a "resource" service? fine, but the authentication for this service is different than for RPs, so what's your point?
The Client exists in the User Agent (we're talking about SPAs, right?). If the ID token is in the Client, then it's in the UA (the reverse is not true). If you're thinking of server-side clients, then there is no need to forward the ID token to the UA, unless you want the UA to pass it on to another Client (e.g. for SSO). There are SSO schemes that use the ID token for convenience, but that's not the stated purpose of the ID token.
The whole point of JWS is that you don't need to call the OP to verify a token. You just verify the signature. That may be done by any Client, whether they're the original recipient of a token, or they get it later. Furthermore, the ID token is not meant to authenticate the user. Using it for SSO requires some other form of security, such as storing a related secret in an HTTP-only cookie that will not be seen by the Client. Anyway, even if you use the ID token for SSO, then the ID token is sent only in the login request. After that, the Client will get its own access token for authentication and will not use the ID token again.
The access token is typically short-lived (which means the Client has to contact the OP regularly, which allows the OP a chance to revoke access). The access token is sent with every authenticated request, so it should be small (i.e. not contain user information that is not useful for authentication).

Clarification on id_token vs access_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.

OAuth2 Login (Not Authorization)

I have implemented an OAuth2 register workflow (in Java) according to rfc6749
I'm using GitLab as OAuth2 Provider.
After the user granted access to my application for his account, I get an OAuth Token (along with refresh token and other stuff), I am able to make API requests on behalf of the user, so this is working fine.
This way I can get the users e-mail adress which I use to create an internal user.
My questions are:
Is it practice to issue a token that is generated by my application for the user (along with the OAuthToken) or should I just use the token that has been issued by the OAauth Provider? (My App also has local auth with bearer tokens). This token will be used for further API - CLIENT communication (stored in Angular2 local storage as bearer)
How to do login only? When a OAuth User accesses my web service, how do I know that this user is a OAuth User and which OAuth Token belongs to him? How can the user login without providing e-mail or password? (The user has no password) I guess I have to redirect him to the OAuth Provider again, but I don't want my user to grant access everytime he logs in.
Answer 1:
Though you can use the token provided by OAuth provider, you SHOULD NOT use it considering the risk that may arise exposing it to the public.
Instead you should securely save the token provided by OAuth provider into the database and use another token for authentication of further api calls. (you could use JWT)
Answer 2:
There are two types of systems
Which always uses OAuth provider for identifying user. (Ex. Tinder)
Which provides both OAuth Login and Traditional login/signup. (Ex. Quora, Instagram)
If you want your application to follow 2nd approach, you should ask the user to create password for the first time when the user logs in using OAuth provider.
This will allow the user to log into your application by both methods, traditional as well as OAuth
To identify users of your application, you should either use HTTP session or issue your own tokens. Do not use tokens generated by the OAuth2 provider - they are meant to be used just by your backend (in role of an OAuth2 client).
To use an external authentication in your application, you probably want to use OpenID Connect, not a bare OAuth2. OpenID Connect extends OAuth2 and it's meant for authentication instead of the rights delegation. Then you use an implicit flow (instead of authentication code grant) with scope=openid, your frontend app (HTML+JavaScript) gets an ID token signed by the OAuth2 provider. After successful signature verification, your backend can trust that the client is the one described in the ID token (in its "sub" field). Then you can either keep using the ID token or generate your own token.

Resources