B2C - Impersonation Flow - azure-ad-b2c

I'm testing the impersonation flow and I'm a bit confused regarding how it should work.
In the JWT the sub claim contains the ID of the impersonator and not the one being impersonated. I was kinda expecting this to be the latter, to avoid any special handling on the API side.
Let's say I want the user ID of the impersonated user in the impersonatedUser claim. Is the recommended way of handling this in the API to 1st check for the impersonatedUser claim (someone is being impersonated) and then use sid (no impersonation) if the former isn't present? What is the recommended way of doing this?
Example JWT created by the policy:
[Header].{
"exp": 1662552679,
"nbf": 1662549079,
"ver": "1.0",
"iss": "https://foo.b2clogin.com/39b9ad06-299d-43da-a960-5e07d3ca9c06/v2.0/",
"sub": "0eebe778-5934-48f6-84a6-bf921f467877", <-- This is the ID of the impersonator
"aud": "64cb0c7e-678d-477c-8efc-a011c3614e58",
"acr": "b2c_1a_impersonation",
"nonce": "defaultNonce",
"iat": 1662549079,
"auth_time": 1662549079,
"name": "unknown",
"impersonatedUser": "a#customer.com"
}.[Signature]

This impersonation flow follows guidance for token exchange which states you should always maintain who is making the original request. This is why the sub should always be the person making the impersonation. This is an extra security layer for audit and control. This protects against abuse of the one who is doing the impersonation.
This design was explicitly done in this manner - yes you could switch and not follow this guidance, but this doesn't align with this open standard.
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-token-exchange-10

Related

Azure AD B2C Github identity provider does not provide any claims

I want to use the AAD B2C Github identity provider to authorize users in my app. To create a user I need at least get an email from it - but I get nothing. I did set up everything according to docs and I can see in the AAD B2C Users list that Name is set up correctly for a new user, but User Principal Name where email should be is null
Here is JWT answer
{
"typ": "JWT",
"alg": "RS256",
"kid": "X5eXk4xyojNFum1kl2Ytv8dlNP4-c57dO6QGTVBwaNk"
}.{
"exp": 1611879546,
"nbf": 1611875946,
"ver": "1.0",
"iss": "https://apichat.b2clogin.com/4d39cd56-4c18-4bc7-aaa8-36bf91191c8c/v2.0/",
"sub": "dfe38752-113e-4431-b1bd-23dd53119369",
"aud": "341eea81-859c-485c-baea-2cc9f75f6512",
"nonce": "defaultNonce",
"iat": 1611875946,
"auth_time": 1611875946,
"idp_access_token": "c5c79a8f49c44575cf127fc3c64aaa5710a0a465",
"idp": "github.com",
"tfp": "B2C_1_susi_debug"
}.[Signature]
What do I missing?
Added
After some studying, I have a suspicion that the Github provider here either does not have the required scopes or mappings. I don't see any ways to add it so far. Potentially that might be solved by a generic OpenID Connect provider but Github does not support well-known/openid-connect-discovery and I have no option to manually set endpoints in AAD B2C.
So far I don't see any way to connect GitHub to my AAD B2C and get that darn email - why the biggest cloud platform does not fully support the biggest dev repository when they have the same owner is beyond my understanding.
Ok, the solution I found looks like that
Set Display Name and Identity Provider Access Token in Application Claims of your User Flow
On GitHub auth you will get name aka username and idp_access_token aka token
That's allow us to call github user api curl -u username:token https://api.github.com/user
By default user api returns public user profile, which might not have a set email
curl -u username:token https://api.github.com/user/emails will return all user associated emails
We need the primary one
{
"email": "***#gmail.com",
"primary": true,
"verified": true,
"visibility": "public"
}

What is "aio" in Azure JWT token? [duplicate]

I have an Azure AD application and have generated two client secrets. I can get a JWT access token using each secret (via client_credentials grant) but can I also see from the JWT token via which client secret it was requested?
If I inspect the JWT tokens I get back, some payload fields are always the same (aud, iss, etc) and some are always different (iat, nbf, aio, etc) but there is no info as far as I can tell that identifies the client secret that was used.
Here's an example payload:
{
"aud": "https://graph.microsoft.com",
"iss": "https://sts.windows.net/e402c5fb-58e9-48c3-b567-741c4cef0b96/",
"iat": 1516886787,
"nbf": 1516886787,
"exp": 1516890687,
"aio": "Y2NgYEjJqF0stqv73u41a6ZmxPEvBgA=",
"app_displayname": "TravelAgencies",
"appid": "ee8cf944-bf6f-42cf-ae30-6060412416a1",
"appidacr": "2",
"e_exp": 262800,
"idp": "https://sts.windows.net/e402c5fb-58e9-48c3-b567-741c4cef0b96/",
"oid": "bc430bc6-d9fb-4fa0-87e5-8b8803fcb222",
"sub": "bc430bc6-d9fb-4fa0-87e5-8b8803fcb222",
"tid": "e402c5fb-58e9-48c3-b567-741c4cef0b96",
"uti": "1TgusyfGtECjErT0Kv4PAA",
"ver": "1.0"
}
On a related note: what are the aio, e_exp and uti fields for? I can't find any information on them.
You can't see through which client secret has the token been issued. What is the reason for asking through which secret it was?
Regarding provided claims - you can check here and here what the different claims mean. For exampe the iat, nbf are just dates - when the token was issued and the validity begin time.
For some of the claims, like aio there is no documentation. But there is no claim to show you which secret was used.
From https://learn.microsoft.com/en-us/azure/active-directory/develop/id-tokens
aio An internal claim used by Azure AD to record data for token reuse. Should be ignored.

Google Endpoints JWT Limited JWT claims pass-thru

Is there a way to request specific JWT Claims to show up in the "X-Endpoint-API-UserInfo" header in a Google Cloud Endpoints oauth scenario?
As background, I have successfully had Google Cloud Endpoints validate my JWT token from Azure Oauth, however the data passed through in the header by Google Cloud Endpoints is limited and does not adequately contain enough information from the original Claims.
The claims provided by Azure can be found here: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-code.
For example
{
"aud": "2d4d11a2-f814-46a7-890a-274a72a7309e",
"iss": "https://sts.windows.net/7fe81447-da57-4385-becb-6de57f21477e/",
"iat": 1388440863,
"nbf": 1388440863,
"exp": 1388444763,
"ver": "1.0",
"tid": "7fe81447-da57-4385-becb-6de57f21477e",
"oid": "68389ae2-62fa-4b18-91fe-53dd109d74f5",
"upn": "frank#contoso.com",
"unique_name": "frank#contoso.com",
"sub": "JWvYdCWPhhlpS1Zsf7yYUxShUwtUm5yzPmw_-jX3fHY",
"family_name": "Miller",
"given_name": "Frank"
}.
However, Google Cloud Endpoints only returns 3 fields (issuer, id, and email) as specified here: https://cloud.google.com/endpoints/docs/openapi/authenticating-users.
As you can see, there is misalignment in the fields, and perhaps some fields that would be valuable to have access to in the endpoints.
At this moment, X-Endpoint-API-UserInfo won't contain any additional info from claims than those documented (i.e. issuer, id, and email), however, the original JWT token itself is passed-through, so you can still extract the additional claims form there.

How do you validate Outlook REST API tokens?

This is a duplicate of how to validate token using outlook rest api, but that received no answers so I'm asking again.
I have managed to authorise a user and receive an access token. I will use the sandbox as an example.
I have decoded the access token and got the following:
Header
{
"typ": "JWT",
"alg": "RS256",
"x5t": "MnC_VZcATfM5pOYiJHMba9goEKY",
"kid": "MnC_VZcATfM5pOYiJHMba9goEKY"
}
Payload
{
"aud": "https://outlook.office.com",
"iss": "https://sts.windows.net/c512ffd1-581d-4dc0-a672-faee32f6387c/",
"iat": 1458918504,
"nbf": 1458918504,
"exp": 1458922404,
"acr": "1",
"amr": [
"pwd"
],
"appid": "32613fc5-e7ac-4894-ac94-fbc39c9f3e4a",
"appidacr": "1",
"family_name": "Dehenne",
"given_name": "Denis",
"ipaddr": "137.117.9.62",
"name": "Denis Dehenne",
"oid": "28328486-e820-4c98-a1cf-e8b35456313a",
"puid": "10033FFF89319A48",
"scp": "Calendars.Read Contacts.Read Mail.Read",
"sub": "XfYUvqiIreYX9wF-909Yf7Hodiwg6ClTwWOc75WmX7o",
"tid": "c512ffd1-581d-4dc0-a672-faee32f6387c",
"unique_name": "DenisD#oauthplay.onmicrosoft.com",
"upn": "DenisD#oauthplay.onmicrosoft.com",
"ver": "1.0"
}
Signature
gtpjf40FxEN8cTX22Mk-Da1n_sKtIUGAmzyYkuhkCskR5y1j4uuenf4ejJxeRwtqIIRWN5w1zOfvFZ2XqXreeSpSCZU-CJCoHIicchChUbyq4iIEcWZr29LbnpDkCyqB8LzoA3rEHUxhZYwHnWIHmkrD4XbMN4CW31bdNQwP0YgXvIucLe_tv80Eu4jDiZsqfCh91DFIb7bv6mbPXiTYMtV6OEdXeHLh--vFvZRRm--atSkKrZHFPT1no2B0YAC8w0kEYWPHyM-TbGni6WjIc7ZGSuDNmkHJfIKndcoFzlVJubV2ntKJhWrXfee490oj3GJi-lkNkFLfa9_VDIYu0w
Inside the Exchange identity token mentions something about metadata and self-signed X509 certificates, but those tokens include fields that don't exist of the ones I am getting.
The header states that the token is signed with RSA. I want to validate the token and for that I need the public key of the signing certificate. Where would I get the certificate? Do I even need to validate the token?
The token is issued by Microsoft Azure, not by Outlook or the Outlook REST API. I added the azure tag for you. According to the subtopic Validating Tokens:
At this point in time, the only token validation your apps should need to perform is validating id_tokens. In order to validate an id_token, your app should validate both the id_token's signature and the claims in the id_token.
We provide libraries & code samples that show how to easily handle token validation - the below information is simply provided for those who wish to understand the underlying process. There are also several 3rd party open source libraries available for JWT validation - there is at least one option for almost every platform & language out there.
It goes on to give more specifics. Like to get the signing key data:
You can acquire the signing key data necessary to validate the signature by using the OpenID Connect metadata document located at:
https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration

Using JWT audience field for authorization roles

I'm considering using the JWT audience field to implement role-based authorization in my app.
So I'd have ServiceA which requires 'RoleA' audience to be present, ServiceB requires 'RoleB' etc. Then when I issue the JWT, I include the appropriate audience(s).
Relevant section from the JWT draft spec:
The aud (audience) claim identifies the recipients that the JWT is intended for. Each principal intended to process the JWT MUST identify itself with a value in the audience claim. If the principal processing the claim does not identify itself with a value in the aud claim when this claim is present, then the JWT MUST be rejected... The interpretation of audience values is generally application specific.
So it appears that would work but since I'm new to JWT I'm wondering: is role-based authorization an appropriate use case for the audience field? Or should I roll my own logic using a payload with custom roles array etc?
Thanks
I understand audience rather then list of consumers/applications who can authorize the user.
In my application I put roles into own array in the payload. For example like that.
{
"sub": 1234567890,
"exp": 9876543210,
"name": "John Doe",
"roles": ["USER", "EDITOR"]
}
On the server I am authorized using spring security and user loaded from "sub".
And on the client I can use these roles to show proper buttons and fields.

Resources