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

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.

Related

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

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.

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.

Should I use OAuth or JWT?

Im building a REST services for existing product. Now to authenticate these, there needs to be some mechanism. To give specifications, I have a Db which stores userid and password . I have to authenticate using these credentials.
In above should I use OAuth or JWT? I prefer to use JWT to generate token first and pass token along every request.
Also From my understanding, I understand OAuth should be used when you have multiple consumers like games/apps using Facebook login. In my case, I don't have any have multiple consumers.
Please advise
Although it is true that OAuth is an authorization framework, it does help with JWT. JWT is a token specification, meaning, how you manage and issue tokens is largely left undefined. For instance, when your token reaches it's expiration, do you want your user to be abruptly logged out? By default, if you're using tokens with a certain duration, this will happen if you're checking for expired tokens, which you should be doing.
An OAuth Authentication server can serve the purpose of issuing an Access Token in JWT, and a Refresh Token. The access token will be included in every request, and the refresh token can be used when the access token is expired or about to expire to acquire a new access token. This is useful when taking into account the potential need to revoke a users access to your application. If you set a short access token life, then you'll be able to revoke access more quickly by removing their refresh token.
The technologies are different and not directly comparable because they solve different problems and are intended for different uses.

OpenID Connect ID Token: What's the purpose of audience [aud] field validation

I'm trying to implement OpenID Connect Implicit Flow. The frontend Single Page App passes the ID Token down to the backend server (using Authorization header) where I need to validate it.
The documentation requires me to check that I trust the audience of the token (aud & azp fields). I'm struggling to understand the significance of this validation step and what are the security implications of not doing so. Why should I distrust the token if I'm not the intended recipient?
My reasoning is that if I trust the issuer it doesn't matter who was the token issued for. I would expect the claims to be the same for any clientId (is this wrong?). Ideally when I pass the ID Token around my microservices all they should know is what issuers to trust (and use discovery protocol for figuring out the keys).
What is the attack vector if I skip this validation step?
The issuer could be issuing tokens to different applications and those applications could have different permissions. Not checking the audience would allow an attacker to use a token issued for application A at application B and may lead to permission elevation.
To your suggestion: the claims may indeed differ per Client.
Here's another reason: If you check that aud claim only contains your client, it prevents other apps' stolen tokens from being used on your app. If a user's token gets stolen from another app, nobody will be able to impersonate the user on your app because the aud claim will not be correct.
I'm answering this for posterity.
You should check the issuer and if your client_id is the only one in the audience if you are receiving tokens from an external OpenId Provider. One that could have more than your client.
Claims are not global to the OpenID Provider, they can be per-client. A user can have "Admin" role on app-A, gets a token there, then tries to send app-B (your application) the same token hoping that your are not checking to which client it was issued for (its audience).

Exchange IP-STS JWT token for ACS JWT token

I have an azure ACS service, which trusts an IP-STS.
For an active scenario, I first get a JWT token from my IP-STS using username, password credentials. There is Oauth2 endpoint and everything works quite well.
Is it possible to "exchange" this IP-STS token for a JWT token issued by my azure ACS ? If so, is there an example of code that does this. (To make things worse, all my code is in JavaScript (actually TypeScript) but that doesn't really matter).
Update :
I'm working on your hint with the ACS OAuth2 draft 13 endpoint.
I proceed as follows : I ask my custom STS (ThinkTecture STS) to give me a JWT token for the "ACS OAuth2 draft 13 endpoint" realm. This requires an oAuth client id and secret which are global in the TT STS and I assume they are irrelevant. In the TT STS management I have a symmetric key configured for this realm : key1. I receive the 3-part JWT token. The signature on the token is indeed made with key1.
I then pass this token to ACS with client id and secret from a service identity and parameters as specified
var form = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "grant_type", "http://oauth.net/grant_type/jwt/1.0/bearer" },
{ "assertion", rawtoken (the header dot body dot signature form TT STS },
{ "scope", "http://localhost"}
});
Unfortunately I now get
{"error":"invalid_client","error_description":"ACS50027: JWT token is invalid. \r\nTrace ID: b107cda5-393b-4b50-b14a-ebaa0ac41913\r\nTimestamp: 2012-12-05 08:58:10Z"}
I understand JWT is in beta and therefore ACS50027 is not yet documented. The hard part is that there is no known way to debug this. Thanks for nay help.
This is definitely possible, but I don't think any of the existing ACS samples do it so you're slightly in uncharted territory.
The approach I would recommend is to use the ACS OAuth2 draft 13 endpoint (as in this sample, but JWT instead of SAML and IdP instead of service identity). The request would be something like:
grant_type=http://oauth.net/grant_type/jwt/1.0/bearer&assertion=(JWT)&scope=(RP realm).
You'll need the issuer of the JWT to match your registered identity provider, along with an associated signing key, plus rules to pass through or change any claims as necessary and the RP to have a token type of JWT.
Ok, I finally found a way to do this. Your hint was crucial for the success. The (very) tricky part is that the IP-STS uses a symmetric key to sign the JWT token. I had to programmatically (using the odata api) insert this key in the ACS backoffice under the Identity provider. (the managament console does not show this key anywhere) Everything is nearly fine. The only trouble is that the ACS copies the audience ("aud") from the original token, while I request a token for a different audience ("scope"). Any ideas there ?
Nope,
You can't Exchange tokens in ACS. The only possibly viable way of doing so, is if you are able to register your IP-STS as an IdP in ACS (you will be able to do so, if your IP-STS supports WS-TRUST protocol). This will throw you on the passive scenario.
The only possible active scenario way is to get JWT token directly from ACS using Username/Password authentication with Service Identities. Well managing service identities in ACS is not as managing ASP.NET Membership provider, but it has a Management API.
The possible ways for authenticating with a Service Identity is Password, Symmetric Key, X.509 Certificate. So, if you twist enough your original IP-STS, to give you a Symmetric Key as a Claim in its JWT token, you will be able to get JWT token from ACS using Service Identity authenticating with that Symmetric Key.
But, if you already have a JWT token, why you need another one from ACS?
UPDATE
Well, the claims transformations are only option in the "Passive" mode. For active mode, the only way (that I know) is to use Service Identities, thus no claims transformations.
The issue with Passive is that because of security reasons, ACS will create a hidden POST form to POST submit transformed token to your Relying Party Application (RP). So there is no way to Actively get a Passive behavior. What you could do just for the sake for trial, and that will fail because of the passive POST in hidden form is the following:
If you are willing to experiment (and I have not tested and I am totally unaware of the result), you may try simulating wsignin1.0 action providing the original JWT token. You can look at the WS-Federation Passive Requestor Profile, section 3.1 on how to construct a Sign-In request. You can also use Fiddler to fully track a Passive scenario chain of events. The one that you shall try reconstruct is the wsignin1.0 request that goes from the registered IdP back to ACS.
At some point you will have the resulted HTML, which contains a FORM element. That form will have two hidden fields - wa with value of wsignin1.0 and wresult which will contain URL encoded <t:RequestSecurityTokenResponse xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">.... This is what you want.
If you succeed in recreating the original SignIn request to ACS from your IdP, than this will work.

Resources