Adding claims to access token received from B2C custom policy - azure-ad-b2c

I have a problem where I need the access token received from a custom policy B2C flow to contain certain claims, for example email. I have one flow for local login (email + password) and that gives me a correct access token, it contains email. However, my other flow for social IDP does not give an access token with any extra claims. An access token from Facebook looks something like this:
{
"typ": "JWT",
"alg": "RS256",
"kid": "IiippFxxxxxxxxxxxxxxxxxxqVEz16tNMOR0"
}.{
"iss": "https://xxxxxxxxxxxxxxx.b2clogin.com/a861612f-xxxxxxxxxxxxxxxx-34e14528d/v2.0/",
"exp": 1671466114,
"nbf": 1671462514,
"aud": "b0823952xxxxxxxxxxxxxxxx363b7bdfe0a",
"sub": "c1aceafd-xxxxxxxxxxxxxxxf4f1a0a83a7",
"idp": "facebook.com",
"tid": "a861612fxxxxxxxxxxxxxxxxxxxce534e14528d",
"nonce": "73eee291-xxxxxxxxxxxxxf6-85818e3efdab",
"scp": "user.read",
"azp": "b0823952-xxxxxxxxxxxxxxx2363b7bdfe0a",
"ver": "1.0",
"iat": 1671462514
}.[Signature]
While the access token from a local sign in looks like this:
{
"typ": "JWT",
"alg": "RS256",
"kid": "IiippFPBuNxxxxxxxxxxxxxxxxxxxPDWO9qVEz16tNMOR0"
}.{
"iss": "https://xxxxxxxxxxxxxxxx.b2clogin.com/a861612f-xxxxxxxxxxxxxxxxx14528d/v2.0/",
"exp": 1671546543,
"nbf": 1671542943,
"aud": "b0823952xxxxxxxxxxxxxxxx363b7bdfe0a",
"sub": "c1aceafd-xxxxxxxxxxxxxxxx1f4f1a0a83a7",
"userIdentities": [
{
"issuer": "https://oidc.test.xxxxx.com",
"issuerUserId": "1xxxxxxxxxxxxx9"
},
{
"issuer": "linkedin.com",
"issuerUserId": "xxxxxxxxxx"
},
{
"issuer": "facebook.com",
"issuerUserId": "xxxxxxxxxxxxx"
}
],
"email": "my#email.com",
"name": "My name",
"given_name": "My",
"family_name": "Name",
"idp": "Local",
"tid": "a86161xxxxxxxxxxxxxxxxxxxx4e14528d",
"nonce": "e080be59xxxxxxxxxxxxxxxxxxxx5bfa353bd601",
"scp": "user.read",
"azp": "b0823952xxxxxxxxxxxxx3b7bdfe0a",
"ver": "1.0",
"iat": 1671542943
}.[Signature]
I know that there's several kinds of tokens and it is the access token I need, not ID token or refresh token. The access token from the custom policy flow will be automatically injected into my API calls by MSAL interceptor in the frontend.
None of my specified OutputClaims in my Custom policy are present in the access token. I have also tried adding optionalClaims in my applications manifest in Azure portal like this:
"optionalClaims": {
"idToken": [],
"accessToken": [
{
"name": "email",
"source": "user",
"essential": true,
"additionalProperties": []
}
],
"saml2Token": []
},
I've also tried mail instead of email, and User instead of user.

Related

Azure AD authorization token from userid and password flow does not contain roles

I am getting access tokens using both implicit grant and username/password flows with the same user, tenant, and application. The problem is the username/password token does not contain the roles and I am unable to verify it. Is there a way I can get a token like the implicit grant flow using the username/password flow? Examples of each are below
implicit Grant Token
{
"aud": "https://<removed>",
"iss": "https://sts.windows.net<removed>",
"iat": 1664909167,
"nbf": 1664909167,
"exp": 1664913508,
"acr": "1",
"aio": "<removed>",
"amr": [
"pwd"
],
"appid": "<removed>",
"appidacr": "1",
"ipaddr": "<removed>",
"name": "Test User",
"oid": "<removed>",
"rh": "<removed>",
"roles": [
"Task.Role1",
"Task.Role2"
],
"scp": "scope1 scope2",
"sub": "<removed>",
"tid": "<removed>",
"unique_name": "testuser#<removed>",
"upn": "testuser#<removed>",
"uti": "<removed>",
"ver": "1.0"
}
Username/Password Token
{
"aud": "00000003-0000-0000-c000-000000000000",
"iss": "https://sts.windows.net/<removed>/",
"iat": 1664909419,
"nbf": 1664909419,
"exp": 1664913431,
"acct": 0,
"acr": "1",
"aio": "<removed>",
"amr": [
"pwd"
],
"app_displayname": "test-api1",
"appid": "<removed>",
"appidacr": "0",
"idtyp": "user",
"ipaddr": "<removed>",
"name": "Test User",
"oid": "<removed>",
"platf": "14",
"puid": "1003200237B425C1",
"rh": "<removed>",
"scp": "User.Read profile openid email",
"sub": "<removed>",
"tenant_region_scope": "NA",
"tid": "<removed>",
"unique_name": "<removed>",
"upn": "<removed>",
"uti": "<removed>",
"ver": "1.0",
"wids": [
"<removed>"
],
"xms_st": {
"sub": "<removed>"
},
"xms_tcdt": 1659020050
}
EDIT...
Below are the scopes in the app
This is the curl command used for the username/password flow. If I specify the scopes in the app, e.g. scope=scope1 scope2, then I get an invalid grant error AADSTS65001: The user or administrator has not consented to use the application with ID. I do not get an error with scope=.default
curl --location --request POST 'https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=<userID>' \
--data-urlencode 'password=<Password>' \
--data-urlencode 'client_id=<ClientID>' \
--data-urlencode 'scope=.default'
More Edits...
So, this is interesting. I am now getting the auth token with the following code instead of using postman. #azure/msal-node returns both the auth and id tokens. The auth token is the same that is returned from postman and does not contain the roles, however, the id token contains the roles. Why would the auth token not contain the roles and what can I do to fix this?
const msal = require("#azure/msal-node");
const msalConfig = {
auth: {
clientId: "<client id>",
authority: "https://login.microsoftonline.com/<tenant id>",
}
};
const pca = new msal.PublicClientApplication(msalConfig);
const usernamePasswordRequest = {
username: "<username>",
password: "<password>",
};
pca.acquireTokenByUsernamePassword(usernamePasswordRequest).then((response) => {
console.log("response:", response);
}).catch((error) => {
console.log(error);
});
ID token returned from the above code
{
"aud": "<application ID>",
"iss": "https://login.microsoftonline.com/<tenant id>/v2.0",
"iat": 1664986457,
"nbf": 1664986457,
"exp": 1664990357,
"name": "Test User",
"oid": "<removed>",
"preferred_username": "<removed>",
"rh": "<removed>",
"roles": [
"Task.Role1",
"Task.Role2"
],
"sub": "<removed>",
"tid": "<removed>",
"uti": "<removed>",
"ver": "2.0"
}

Access Token Question in Azure Functions Authentication

I followed the link Enable Azure Active Directory in your App Service app for setting up AAD authentication for my Azure Functions. For calling the Azure Functions, I tried using the token obtained as First case: Access token request with a shared secret, and I got error status 401 "You do not have permission to view this directory or page." This access token is from the Uri https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token. In testing I found if I request the token from the Uri https://login.microsoftonline.com/{tenantId}/oauth2/token, it works. Why is that?
The token from https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token is decoded as follows.
{
"typ": "JWT",
"nonce": "klkSaiUS7yT5KMshYVJZAkyu5AuDV14yEQLEkxiz2o4",
"alg": "RS256",
"x5t": "huN95IvPfehq34GzBDZ1GXGirnM",
"kid": "huN95IvPfehq34GzBDZ1GXGirnM"
}.{
"aud": "https://graph.microsoft.com",
"iss": "https://sts.windows.net/{tenantId}/",
"iat": 1597615459,
"nbf": 1597615459,
"exp": 1597619359,
"aio": "E2BgYOD6EGiutPFpxY67vVocPgv3AAA=",
"app_displayname": "app Displayname",
"appid": "{appId GUID}",
"appidacr": "1",
"idp": "https://sts.windows.net/{tenantId}/",
"oid": "{GUID}",
"roles": [
"User.ReadWrite.All",
"Group.ReadWrite.All",
"User.Invite.All",
"TeamMember.ReadWrite.All",
"Team.ReadBasic.All",
"GroupMember.ReadWrite.All"
],
"sub": "{GUID}",
"tenant_region_scope": "NA",
"tid": "{tenantId}",
"uti": "lA__6UDggU6QYEGdX0t_AA",
"ver": "1.0",
"xms_tcdt": 1590621751
}.[Signature]
The token from https://login.microsoftonline.com/{tenantId}/oauth2/token is decoded as follows.
{
"typ": "JWT",
"alg": "RS256",
"x5t": "huN95IvPfehq34GzBDZ1GXGirnM",
"kid": "huN95IvPfehq34GzBDZ1GXGirnM"
}.{
"aud": "00000002-0000-0000-c000-000000000000",
"iss": "https://sts.windows.net/{tenantId}/",
"iat": 1597615470,
"nbf": 1597615470,
"exp": 1597619370,
"aio": "E2BgYOAS8fUOUly15/PahOer9u1iBQA=",
"appid": "{appId GUID}",
"appidacr": "1",
"idp": "https://sts.windows.net/{tenantId}/",
"oid": "{GUID}",
"sub": "{GUID}",
"tenant_region_scope": "NA",
"tid": "{tenantId}",
"uti": "3wr4Ulqcs0ueW77ZacF4AA",
"ver": "1.0"
}.[Signature]
I am aware that two tokens have different audiences, and have added both to "Allowed Token Audiences" in Azure Functions' AAD authentication.
Please help me to understand this. Really appreciate.

Azure OAuth2 Code Flow, groups claim is not in access token, but in id token

I added groups claim to both access and id tokens.
image: groups claims added to both token on portal
I also confirmed they are defined in the manifest and groupMembershipClaims = SecurityGroup:
"groupMembershipClaims": "SecurityGroup",
"optionalClaims": {
"idToken": [
{
"name": "groups",
"source": null,
"essential": false,
"additionalProperties": []
}
],
"accessToken": [
{
"name": "groups",
"source": null,
"essential": false,
"additionalProperties": []
}
],
"saml2Token": []
},
When I fetch the tokens.
The groups claim is in the id token, but not in the access token. Is this an ADD bug? I have spent hours in googling and trying. Nothing worked for me so far.
Access Token
"oid": "ab7160f43-3595-4b82-abad-3a750ds95b039",
"platf": "3",
"puid": "100322000B4FFA971",
"scp": "openid profile email",
"sub": "Dd9iRENxMc6sFSOLpqvW-dfLQGgDDUiBvuk4M9PsVus8",
"tid": "2ed2c5sdf-19e7-4eb3-bfb7-eb26560fb1cc",
"unique_name": "xxxxxxxxxxx",
"uti": "D9cxwcvwRUCqmuLTbdd4IOAA",
"ver": "1.0",
"wids": [
"62e90394-69f5-4237-9190-012a177145310",
"9b895d92-2cd3-44c7-9d02-a6ac2d5eag2c3",
"c4e39bd9-1100-46d3-8c65-fb16d0da0071f"
],
"xms_st": {
"sub": "KH969M9F0-jgY2_dA89JzIkvDnt-OsBqltYKxnZv1qc"
},
"xms_tcdt": 1587429781
}.[Signature]
Id token
"iat": 1590181245t,
"nbf": 15901821456,
"exp": 15901855353,
"groups": [
"636c4e93-0a20-419a-9294-df537346bcda3",
"837c721c-83e6-4e20-8a35-2545d53043b28",
"95d05d16-f75a-415a-9c22-846b361777bcd",
"e1c42670-0726-4e5d-a9bd-8be2cc8776c55",
"d324302a-470c-4236-b818-c7706f840dc3",
"ba6f4d61-3927-452e-b2fe-90a5486033537"
],
"idp": "xxxxxx",
"sub": "KH969M9dF0-jgY2_dA89JzIkvDnH-OsBqltYKrxnZv1qc",
"tid": "2ed2tc5df-19e7-4e2b3-bfsb7-eb26a560fb1cc",
"uti": "D9cxwcvwRUCqmruLTb4IOAA",
"ver": "2.0",
"wids": [
When you say you want groups in the access token, that only applies to access tokens meant for that app. The access token you show is probably not meant for your app, but another API, that has not defined that it wants groups in the token.
If you need group info in the front-end application, get them from id token.
If you need them in back-end, you need to acquire a token for your API, and define that you want groups in the access tokens for that API.
You define the API the token is for with the resource/scope parameter when acquiring a token.
If you are using v1 endpoint, you define the client id or app ID URI as the resource.
If you are using v2 endpoint, then you use the scopes defined in the Expose an API tab of the API app registration.

user_role not returned by AD OIDC

Posting this question on behalf of a customer:
We are trying to integrate Kubernetes OIDC authentication with Azure AD.
According to the documentation in order to use User groups we need to pass the following option to the Kubernetes API service:
--oidc-groups-claim user_roles
Api service uses user_roles to look up the group names of the groups the user is a member of in the JWT returned by Azure AD.
However, when we decode the JWT returned by Azure AD, we can't find any field called user_roles in the returned JWT. The decoded JWT looks like this (redacted):
{
"aud": "spn:XXX",
"iss": "https://sts.windows.net/XXX/ ",
"iat": XXX,
"nbf": XXX,
"exp": XXX,
"acr": "1",
"aio": "XXX",
"amr": [
"pwd",
"mfa"
],
"appid": "XXX",
"appidacr": "0",
"family_name": "Foo",
"given_name": "Bar",
"groups": [
"gid1",
"gid2"
],
"ipaddr": "XXX",
"name": "Foo Bar",
"oid": "XXX",
"onprem_sid": "XXX",
"scp": "user_impersonation",
"sub": "XXX",
"tid": "XXX",
"unique_name": "XXX",
"upn": "XXX",
"uti": "XXX",
"ver": "1.0"
}
As you can see there is no user_role field present in the returned JWT. Is there anything we are missing ie. should we enable some settings in the Azure AD that will get the Azure return user_role populated with the group names the user is a member of?
JWT we are hoping to get should look something like this (please note the user_role field):
https://github.com/kubernetes/kubernetes/issues/33290#issue-178672086
{
"iss": "XXX",
"aud": "XXX",
"exp": XXX,
"jti": "XXX",
"iat": XXX,
"nbf": XXX,
"sub": "mmosley",
"user_role": [
"admin",
"users",
"approvers"
],
"email": "XXX"
}
Any help or pointers would be greatly appreciated.
First,as I known, AAD id_token only supports role claim, NOT user_role. It can be added into id_token by adding appRoles property of the AAD application manifest.
And bit in theconfig is needed to match the audience from tokens retrieved by the Azure AAD.
Second,--oidc-groups-claim should not use user_role claim. According to my understanding, it should be groups which match the groups claim in id_token.
Also, you can refer to this blog and this sample to Integrate Kubernetes RBAC with Azure AD.
See more details about RBAC authentication for Kubernetes in this document.

Microsoft Graph API get groups for user gives privileges error

Requirement:
We would like to query the groups of a user via Microsoft’s Graph API with the following request:
https://graph.microsoft.io/en-us/docs/api-reference/v1.0/api/user_getmembergroups
In our case the response looks like this:
{
"error": {
"code": "Authorization_RequestDenied",
"message": "Insufficient privileges to complete the operation.",
"innerError": {
"request-id": "a230a67e-8ef1-4f88-aa19-2c5b983c3de4",
"date": "2017-01-04T16:29:55"
}
}
}
(Note: the GET https://graph.microsoft.com/v1.0/me/ is working fine and returns the user data)
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"id": "e23976a1-8bd9-4cca-a410-e095d2c2022d",
"businessPhones": [],
"displayName": "XXXX Vad",
"givenName": "XXXX",
"jobTitle": null,
"mail": null,
"mobilePhone": null,
"officeLocation": null,
"preferredLanguage": null,
"surname": "Vad",
"userPrincipalName": "XXXX.vad_outlook.com#EXT##XXXXvadoutlook.onmicrosoft.com"
}
Environment:
Application created on apps.dev.microsoft.com with the following parameters:
o Application Id: 412386c3-8fa3-4000-9039-748111407XXX
o Delegated Permissions: [ User.Read ]
This application is visible on ‘Azure Portal / AAD / Enterprise applications’ and the user with a group ‘BASIC’ is added to this application
An example of an access token obtained from AAD:
{
"aud": "https://graph.microsoft.com",
"iss": "https://sts.windows.net/b9df6a2d-9150-45f9-abf0-9c30f9e527c7/",
"iat": 1483548390,
"nbf": 1483548390,
"exp": 1483552290,
"acr": "1",
"aio": "AQABAAEAAADRNYRQ3dhRSrm-4K-adpCJhEVX2WEl4aboghl6AXaqOVcbaQPl1yYg1X1D2r4cNxBYmPvUiTKE9bB6wwpNSBKeD2OZXhrzdE3FPddCzbaTo84X8aSoKFaAt2vysYSv1HdChNXBPbfrVlA6YBuSwVwEIAA",
"altsecid": "1:live.com:00037FFEC5917401",
"amr": [
"pwd"
],
"app_displayname": "XXX test",
"appid": "412386c3-8fa3-4000-9039-748111407XXX",
"appidacr": "0",
"email": "XXXX.vad#outlook.com",
"family_name": "Vad",
"given_name": "XXXX",
"idp": "live.com",
"ipaddr": "165.225.80.95",
"name": "XXXX Vad",
"oid": "e23976a1-8bd9-4cca-a410-e095d2c20XXX",
"platf": "3",
"puid": "10037FFE9D51DXXX",
"scp": "User.Read",
"sub": "sCDfsIUynhm4GdgPIe8hYguyNbbc7IBjZeKLd1UDXXX",
"tid": "b9df6a2d-9150-45f9-abf0-9c30f9e52XXX",
"unique_name": "live.com#XXXX.vad#outlook.com",
"ver": "1.0"
}
What am I doing wrong or what’s missing? Any help is appreciated.
You have to have admin consent right now to pull groups. They changed the required permissions a while back.
https://blogs.msdn.microsoft.com/aadgraphteam/2015/03/18/update-to-graph-api-consent-permissions/

Resources