Is it safe to embed an ID token within a JWT token? - azure

I'm new to JWT and authorization of micro-services in general. We are using Azure to do our authentication for an application backed by micro-services. However, we are using a separate home grown micro-service to do RBAC/ABAC authorization. I was thinking that the general scheme to use in order to secure all of the micro-services is to use JWT. My thought was that once authenticated and I have an Azure ID token, that ID token would be passed within a JWT token to my authorization service in order to get an authorization token from my authorization service. It would use the Azure ID token to validate that the user actually authenticated themselves by validating the ID token and the generate my application access token to use from then on. In general, is it safe/secure to pass around an ID token within a JWT payload? Hopefully that all makes sense.

Related

JWT tokens: questions best practices and risk of symmetric keys

First a little background on my use of JWT tokens.
Users (via a web frontend) login to my service through a login HTTP endpoint that includes a username and a password in the request body. Two factor authentication will be added in the future, but can be ignored for now.
The API verifies the login information and issues a JWT token in the response. This token is signed with a symmetric key and includes a userId (UUID) that uniquely identifies the user.
In subsequent API calls, the user includes that token in the Authorization HTTP header as a bearer token. The API verfies the signature of the token and then uses the userId to make sure that the user is authorized by checking the roles of the user (stored in a database).
The token can expire, forcing the user to login again, or they can use a refresh endpoint that verifies the token and issues a new one to bypass logging in each time the token would expire.
What are the best practices for JWT authentication/authorization? Are there flaws with my approach? Is there a risk of using symmetric keys here? I am open to suggestions on better approaches as well.

Google Actions Authentication flow not sending JWT token, how to validate the token provided?

I'm trying to implement OAuth authentication for my google home compliant google-actions backend but I'm not sure on how to validate the token that google is giving me on the authorization header, I was expecting an JWT token but it isn't.
I'm doing my backend on express and node.js with express-jwt to parse the token and jwks-rsa to fetch the encryption key. I've setup my Auth0 tenant loosely based on this guide and it works fine, the login screen shows up and works just fine.
An example of a token google sends me is something along the lines of
authorization:"Bearer msuVRoQGJ_aPqH-zShLq053aAEVmlHqi"
I was expecting google to communicate with Auth0 to exchange a JWT token and then use it to authenticate to my API by sending it as a authorization header. But I don't know what is the bearer token google is sending or how do I validate it.
By default Auth0 will send you an opaque access token when you authorize to a non-Custom API (similar to the one you received). JWT Access tokens are only issued to custom APIs. So in order to get it in JWT format, you will need to create an API in Auth0 and set the API identifier you defined as the audience parameter.
You will issued JWT Access tokens for Custom APIs and you can validate and verify the integrity of it (there is an example on how to do this in Nodejs): https://auth0.com/docs/api-auth/tutorials/verify-access-token

SPA + API + OIDC: How to authenticate an API caller when it's only providing an ACCESS token?

Let's say you are developing a client side JavaScript SPA app (Angular), a backend API for this app (ASP.NET Core in my case) and you use an identity provider that implements Open ID Connect protocol (I'm using IdentityServer4).
Apparently the recommended way for securing the app is to use the OIDC implicit flow between the JavaScript app and the identity provider and if successful the JavaScript app gets an id token and an access token.
Now according to this documentation the JavaScript app is supposed to pass the access token in the headers whenever it calls the API. And I'm not sure what purpose does the id token serve in this case (besides customizing the UI in your JavaScript app)?
But this is the confusing part: The documentation also says you should never use the access token for authentication. But that is the token that my API receives in the request headers, how can it authenticate the user then? If my API receives Post(newRecord), and the API needs to internally fix some audit information on newRecord (i.e newRecord.CreatedBy = CurrentUsername), how can it do that without authenticating the caller??
I think I'm missing a piece of the puzzle. Please any help is deeply appreciated.
Short answer/suggestion
Use Access Token to access API endpoints. From API endpoints, you must use token introspection endpoint to validate token validity (active state) as well as obtain subject who authenticated at authorization server. IdentityServer provide support for this. Documentation is available from here.
Explanation
ID token is intended to be used by receiving client. It will allow your client to authenticate the end user and provide user specific customizations. This is the whole purpose of OpenID Connect (OIDC). On the other hand OAuth 2.0 provide an authorization framework. It replaces user credentials with access tokens, thus improving API access security (compared to basic authentication and storing user credentials everywhere). Hence OIDC is built on top of OAuth 2.0, you get both ID Token and Access token with OIDC flow.
But as you have figured out (and mentioned before), ID token is intended for client. There are could be exceptional cases where ID token get passed between client and a server. This is mainly when both are controlled by same party. But the access token is the key to access API endpoints, correctly.
Access tokens can be an opaque string or JWT. When it's a JWT, API can read and understand the token (self-contained). When it's opaque, only way to validate token at API endpoint is to use token introspection endpoint. If API can validate token validity, then it could grant access (authorize) request. Furthermore, if user details (subject) are available (through JWT or as introspection response), then user specific checks can be executed. This further extends to token scope values. But at the end of the day, you are authorizing the API request and not authenticating the user at API endpoint. That's the highlight. Hope things are clear now.!

Why use an idp issued id_token -- versus a custom session cookie?

I'm struggling to understand when to use a session cookie, or just use the IdP issued token as a bearer token.
Is the primary advantage of using an IdP issued token that you get a standards based mechanism for tokens (including ensuring non-tampering, as the JWT is signed)?
As opposed to using a proprietary vendor mechanism of converting it to a claim identity, and then to a custom session cookie (as per owin middleware)?
Doesn't the custom cookie approach have an advantage that one can add non-ipd issued claims (eg: from a system db)?
What other key advantage does using an idp issued id_token have over a cookie based session approach?
Is it maybe that a bearer token approach would not need caching on the server, so that one can re-use it to call 3rd party services that have a different audience value? Whereas the token would be lost if we used a cookie? (I'm reaching, I know, as I don't yet understand how calling 3rd party services works).
The Id token is meant for your user-facing app as proof of who the user is.
It is then up to your app how you choose to authenticate the user on future requests.
While technically you could just store the Id token and use that, as you mentioned, it cannot be extended since it is digitally signed.
Which for most our projects is no good.
At least in regular Azure AD (not sure about B2C), you cannot use the Id token to get an access token for another API.
In there, you would have to get an authorization code in addition to the Id token at the time of sign in,
and exchange that for an access token (which you then cache server-side).
If you use the Id token as an authentication token for your app, keep in mind that Id tokens issued from the token endpoint (when exchanging an authorization code in normal Azure AD) are not signed (I guess since you receive them as a response to your request + over HTTPS).
Only the Id token you get in the redirect back to your app is signed in normal AAD.
I am not sure if this applies to B2C as well.

OpenID Connect - should the id token be sent to the protected resource in this case?

Lets say I have a web API that a native application needs to make requests to. This API needs to authenticate who the user is that's making these requests via the native app. OpenID Connect seems to be the right choice since it is about authentication rather than authorization with OAuth.
The native app sends the users credentials to the IDP and gets back an access token (for authorization) and an id token (for authentication). From what I understand of OIDC, the access token would be sent to the API but the id token is only for the native client app. That doesn't make sense to me because it's the API that cares about who the user is, not the native app.
So why isn't the id token also passed to the protected resource (aka the API)? If you don't pass the id token to the API, what guarantees that the access token is secure and can be used to authenticate the user? Otherwise it would seem to lose the benefit of using OIDC over OAuth.
The OIDC Specification is designed in a way that ID tokens are always for Clients (Native app) and Access tokens are for resources (APIs). The ID tokens are always JWT tokens, but the Access tokens can be of different type.
The purpose of Access token is not to authenticate but to Authorize (Delegated Authorization). If, for some reason, the resource server wanted to know about the user, it can call the user-info endpoint.
The security/validity of token exchange can be validated in several ways:
Using encryption/signature with Public/Private key model where Authorization server encrypts / signs the access token with its private key and resource server decrypts / verifies with the public key.
Using token introspection endpoint to validate the claims, validity of the token etc..
Other attributes like AUD , AZP help in validating the issued access tokens.
Some OIDC providers use ID_Tokens to access API's - this is different to the model suggested by OIDC specification
This article has detailed explanation about these scenarios.

Resources