I need to implement a single sign on of a user, which can get services from several different services.
When there was only a single service, the user could log in from the client side, send the request to a backend, gets a URL back to a JWT token issuer server, from which he can get a token which he sends back to the BE and he is now authenticated.
What is now changing, is that he needs to get more services. Each service has its own frontend and backend, but everyone are using the same issuer. Meaning there are both services with FE and BE, and also there is another general BE for the authentication.
What is the correct flow to authenticate in the scenario? Can the general BE issue a token for the client for each of the required services? Or should the BE respond the client with the services's BE url and let the client itself send an authentication token response from each service? Or something else?
I assume you mean OpenID Connect, since OAuth2.0 is not used for authentication and does not require the use of JWTs. Also, in your scenario there are not multiple resources, but multiple clients / relying parties.
Using the OpendID Connect Implicit flow, the issuer will eventually send an id token (JWT) to the user's browser. This JWT can be used to authenticate to a service. Each JWT will contain an aud (audience) claim to identify the service it should be used for.
Using the Authorization Code flow, the issuer will eventually send an authorization code to the user's browser. The user will send the code to a service, and the service will send the code plus its client id to the issuer in exchange for an id token (JWT) and an access token.
In both cases, the service identifies the end user using the iss (issuer) claim, and verifies the JWT by checking the signature, expiry and audience.
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.
So my understanding of OAuth2 from a mobile client is:
Mobile client redirects page to get user auth using client id
Resource holder responds back with an auth_code
auth_code is exchanged for an access_token and refresh_token
In the above, if you have a web service that is acting to support your mobile app, you permanently store the access_token and refresh_token, which will allow you to continue to access the user's data, provided they haven't revoked your permissions.
So the question I had was: should the auth_code be sent to the service, and exchanged there for the tokens? Or should the client exchange the auth_code, and send the resulting tokens to the service? Does it not matter, or is it perhaps different for different implementations? I'm assuming the client secret is only stored on the service, and my understanding is that is needed to exchange a refresh_token for a new access_token, but I wasn't sure about the auth_code.
The client secret is needed also when requesting the tokens using the authorization code.
The client can request the tokens directly or delegate that to the service - there is not a hard and fast rule saying you should do one or the other.
I'd say if the service is going to use the tokens probably delegating to the service makes most sense - so the tokens stay there. If the client is going to use the tokens both approaches are valid.
I am working on a mobile application that uses an api built with ASP.NET web api framework. We decided to use ACS alongside a custm STS as a mechanism to secure the api.
We are using a custom STS because we need to authenticate users against our own identity store.
The information flow is as follows:
Mobile app calls the custom STS with user credentials.
User is authenticated against our own identity store.
Once user is authenticated an authorization code is retrieved from ACS and used to retrieve an SWT access token.
Token is returned to mobile app.
Mobile app embeds access token in authorization header and fires request to API
HTTP module in API validates the access token and data is returned if the token is valid.
Everything is done over SSL as we are using oAuth 2.0.
The problem with oAUth 2.0 is that it is at risk from man-in-the-middle attack as the SWT token issued by ACS is a raw token and not encrypted in any way. It is however, signed using a 256bit symmetric key.
We are using swt tokens because we are using an http based approach and the token fits nicely into the auth header of an http request.
Microsoft have provided some ACS security guidelines in the following post:
http://msdn.microsoft.com/en-us/library/windowsazure/gg185962.aspx
we currently implement 2 of these as we check the issuer and the audience i.e that the token was issued by our trusted issuer (ACS) and that the token was issued for the correct audience (our api).
our scenario is based on the following article:
http://msdn.microsoft.com/en-us/library/hh446531.aspx
as such WIF is not used to handle incoming tokens. WIF is only used in claims processing.
given the above mentioned scenario is there anything else that we could be doing to improve the implementation we have to secure our rest based api?
any and all comments/criticism/suggestions welcome.
Thank you.
I think you're already taking the correct approach. The most important thing is to verify if the token is signed by ACS. Never share your ACS secret key with anyone else. If they don't know the key, they cannot forge the signature.
Also do not store confidential information in the token (such as password, credit card number, etc.). You should expect the token may be obtained by someone else, but no one can forge a token with the correct signature.