Azure ADB2C Claims in an Azure Static Web App - azure-ad-b2c

I am a little stumped on getting claims to pass from Azure AD B2C to my Static Web App.
According to this page. All I need to do is go to Application claims, choose the ones I want and click on save.
I have all of them checked.
I registered an application in my ADB2C tenant. Then configured an OpenID Connect Provider in Azure Static Web Apps.
I can sign in to my App using users in the ADB2C Tenant. I have a page that I set up to get the claims and all I get is this.
This is my App Manifest
{
"id": "947e0f27-54f8-4fd7-8d47-7138ec829e49",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": null,
"appId": "25a72c46-1be1-445e-9ed1-fbf89732c9ea",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2022-08-16T17:23:28Z",
"description": null,
"certification": null,
"disabledByMicrosoftStatus": null,
"groupMembershipClaims": null,
"identifierUris": [],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": "https://seanwoodwardwebb2c.b2clogin.com/seanwoodwardwebb2c.onmicrosoft.com/B2C_1_signupsignin1/oauth2/v2.0/logout",
"name": "SWA Test",
"notes": null,
"oauth2AllowIdTokenImplicitFlow": true,
"oauth2AllowImplicitFlow": true,
"oauth2Permissions": [],
"oauth2RequirePostResponse": false,
"optionalClaims": {
"idToken": [],
"accessToken": [],
"saml2Token": []
},
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [
{
"customKeyIdentifier": null,
"endDate": "2023-02-16T18:23:56.247Z",
"keyId": "886381a9-74d8-4176-8921-e34299f52b13",
"startDate": "2022-08-16T17:23:56.247Z",
"value": null,
"createdOn": "2022-08-16T17:24:00.1757229Z",
"hint": "4pA",
"displayName": "Dev"
}
],
"preAuthorizedApplications": [],
"publisherDomain": "seanwoodwardwebb2c.onmicrosoft.com",
"replyUrlsWithType": [
{
"url": "https://jwt.ms",
"type": "Web"
},
{
"url": "https://gentle-water-027065a10.1.azurestaticapps.net/.auth/login/adb2c/callback",
"type": "Web"
},
{
"url": "https://gentle-water-027065a10-staging.centralus.1.azurestaticapps.net/.auth/login/adb2c/callback",
"type": "Web"
},
{
"url": "https://gentle-water-027065a10-dev.centralus.1.azurestaticapps.net/.auth/login/adb2c/callback",
"type": "Web"
}
],
"requiredResourceAccess": [
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "37f7f235-527c-4136-accd-4a02d197296e",
"type": "Scope"
},
{
"id": "7427e0e9-2fba-42fe-b0c0-848c9e6a8182",
"type": "Scope"
}
]
}
],
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADandPersonalMicrosoftAccount",
"tags": [],
"tokenEncryptionKeyId": null
}
This is my code base https://github.com/woodman231/az-swa-b2c-demo
I have a sneaky suspicion that I need to modify this app registration to some degree, but I am not sure what I might need to do. Also I am not sure if ADB2C is not providing the claims, or if the claims are being dropped with the SWA proxy. Any help would be appreciated.
Part of me believes that this could be an issue with the SWA Proxy. Because if I run my SignupSignIn Policy with this app registration and use https://jwt.ms as the Reply URL...
I do get all of the claims. So why are the claims not showing up in the /.auth/me endpoint?
According to this page all I need to do is provide the client id and client secret from my app registration as well as the wellknown openid config document. The wellknown one that I am supplying is the one associated with my adb2c policy, and not just the generic one for my tenant so you would think that would be more specific and detailed. So if the claims are provided by the jwt, why are the claims not being copied when going to /.auth/login/<PROVIDER_NAME_IN_CONFIG>/callback, and thus not available at /.auth/me?

Related

MSAL (Desktop & Mobile) not using proper redirect_uri

I have registered an App in Azure AD with the following manifest :
{
"id": "<ID>",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": null,
"appId": "<app id>",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2021-10-18T15:35:56Z",
"certification": null,
"disabledByMicrosoftStatus": null,
"groupMembershipClaims": null,
"identifierUris": [],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": null,
"name": "app-func-myapp-client",
"oauth2AllowIdTokenImplicitFlow": false,
"oauth2AllowImplicitFlow": false,
"oauth2Permissions": [],
"oauth2RequirePostResponse": false,
"optionalClaims": null,
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [],
"preAuthorizedApplications": [],
"publisherDomain": "mydomain.com",
"replyUrlsWithType": [
{
"url": "https://login.microsoftonline.com/common/oauth2/nativeclient",
"type": "InstalledClient"
}
],
"requiredResourceAccess": [
{
"resourceAppId": "<app id>",
"resourceAccess": [
{
"id": "<id>",
"type": "Scope"
}
]
},
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
"type": "Scope"
}
]
}
],
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADandPersonalMicrosoftAccount",
"tags": [],
"tokenEncryptionKeyId": null
}
I then tries to get an access token with MSAL from a .NET Desktop App
var strApplicationID = "<my appid>";
IPublicClientApplication PublicClientApp;
PublicClientApp = PublicClientApplicationBuilder.Create(strApplicationID)
.WithDefaultRedirectUri()
.Build();
string[] listScopes = new string[] {
"profile",
"email",
"openid",
$"api://{strApplicationID}/<somescope>"
};
var accounts = await PublicClientApp.GetAccountsAsync();
AuthenticationResult authResult;
try
{
authResult = await PublicClientApp.AcquireTokenInteractive(listScopes)
.ExecuteAsync();
MessageBox.Show(authResult.AccessToken);
Instead of popping the MSAL Authentication window, it starts a browser page. Once I login, I get the exception. "invalid_request: The provided value for the input parameter 'redirect_uri' is not valid. The expected value is a URI which matches a redirect URI registered for this client application."
In the URL, I clearly sees that it tries to use localhost in the redirect_uri, which doesn't make sense as I explicitly configured my App Reg for "Desktop and Mobile" Authentication.
What am I missing here?
To work around the problem, follow these steps to update your app registration:
Go to https://apps.dev.microsoft.com and login with the account you used in the quick-start download.
Locate the app by app ID and select it. You can get your app ID by opening the OAuth.resw file in Visual Studio.
When prompted to edit in the Azure Portal, choose "Not now".
Find the "Native Application" section, and choose "Add URI".
Enter "urn:ietf:wg:oauth:2.0:oob".
Choose "Save" at the bottom of the page.

Redirect to login with AAD in Azure App Service Authentication vs Authentication (Classic)

I'm trying to set up a system where an Azure DataFactory can call an Azure function through its managed identity. Good example here: Authorising Azure Function App Http endpoint from Data Factory
However, this was using the old(er) Authentication/Authorization tool for Azure functions, which has now been renamed Authentication (Classic). Setting the system up through this is fine, I can make the call and get a response, but upgrading to Authorization causes this to break. It seems like the key thing missing is the option of "Action to take when the request is not authenticated", which I cannot seem to set with the new Authorization tool but should be set to "Login with Azure AD"
In summary, how do I set this setting with the new Authorization tool so that a MSI can make a cool to the function and authenticate with AAD.
Image with classic
Image with new Authorization (no visible way to redirect to AAD)
In summary, how do I set this setting with the new Authorization tool so that a MSI can make a cool to the function and authenticate with AAD.
To make it work with the new Authentication, follow the steps below.
1.Edit the Authentication settings in the portal or set it when creating the app as below.
2.Edit the Identity provider, make sure the Issuer URL is https://sts.windows.net/<tenant-id>(without /v2.0) and Allowed token audiences include the App ID URI.
For the App ID URI, you could check it in your AD App of the function app -> Expose an API, if you use the old Authentication before, maybe it is your function app URL, it does matter, just make sure Allowed token audiences include it.
3.Then in the datafactory web activity, also make sure the resource is the App ID URI.
Then it will work fine.
Update:
You could refer to my configuration.
Function app:
AD App:
AD App manifest:
{
"id": "xxxxxx",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": null,
"addIns": [],
"allowPublicClient": null,
"appId": "xxxxx",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2021-06-08T01:51:06Z",
"disabledByMicrosoftStatus": null,
"groupMembershipClaims": null,
"identifierUris": [
"api://xxxxx"
],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": null,
"name": "joyfuna2",
"oauth2AllowIdTokenImplicitFlow": true,
"oauth2AllowImplicitFlow": false,
"oauth2Permissions": [
{
"adminConsentDescription": "Allow the application to access joyfuna2 on behalf of the signed-in user.",
"adminConsentDisplayName": "Access joyfuna2",
"id": "1704f162-421d-4733-855f-5d93c0c55689",
"isEnabled": true,
"lang": null,
"origin": "Application",
"type": "User",
"userConsentDescription": "Allow the application to access joyfuna2 on your behalf.",
"userConsentDisplayName": "Access joyfuna2",
"value": "user_impersonation"
}
],
"oauth2RequirePostResponse": false,
"optionalClaims": null,
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [
{
"customKeyIdentifier": null,
"endDate": "2031-06-08T01:51:05.573Z",
"keyId": "c6d4434f-7aaf-4c4c-9428-a38cbf8200bb",
"startDate": "2021-06-08T01:51:05.573Z",
"value": null,
"createdOn": "2021-06-08T01:51:07.3876164Z",
"hint": "UT_",
"displayName": "Generated by App Service"
}
],
"preAuthorizedApplications": [],
"publisherDomain": "xxxxxx.onmicrosoft.com",
"replyUrlsWithType": [
{
"url": "https://joyfuna2.azurewebsites.net/.auth/login/aad/callback",
"type": "Web"
}
],
"requiredResourceAccess": [
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
"type": "Scope"
}
]
}
],
"samlMetadataUrl": null,
"signInUrl": "https://joyfuna2.azurewebsites.net",
"signInAudience": "AzureADMyOrg",
"tags": [],
"tokenEncryptionKeyId": null
}
Datafactory web activity:

Login with OAuth2 And Azure Active Directory With Personal account microsoft

Hello guys i have exactly the same problem in this question:
Login with personal Microsoft accounts failes to Oauth2 v2
But i don't understand the answer, where i should configure this link in the manifest? https://login.microsoftonline.com/common/oauth2/v2.0/authorize
My manifest is:
{
"id": "0982f18d-116c-45c0-b1ee-59dd9fa3344b",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": null,
"appId": "002543f2-87b6-43e4-91a3-cfdef655dc7a",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2021-02-04T10:09:11Z",
"disabledByMicrosoftStatus": null,
"groupMembershipClaims": null,
"identifierUris": [],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": null,
"name": "AppBotTipBook",
"oauth2AllowIdTokenImplicitFlow": false,
"oauth2AllowImplicitFlow": false,
"oauth2Permissions": [],
"oauth2RequirePostResponse": false,
"optionalClaims": null,
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [
{
"customKeyIdentifier": null,
"endDate": "2299-12-30T23:00:00Z",
"keyId": "86c3141b-02ac-4d47-9ecf-0cabb8ba2fc4",
"startDate": "2021-02-04T10:10:43.464Z",
"value": null,
"createdOn": "2021-02-04T10:10:44.3986206Z",
"hint": "_3D",
"displayName": "botlogin"
}
],
"preAuthorizedApplications": [],
"publisherDomain": "unisalerno.onmicrosoft.com",
"replyUrlsWithType": [
{
"url": "https://token.botframework.com/.auth/web/redirect",
"type": "Web"
}
],
"requiredResourceAccess": [
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "570282fd-fa5c-430d-a7fd-fc8dc98a9dca",
"type": "Scope"
},
{
"id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
"type": "Scope"
},
{
"id": "b340eb25-3456-403f-be2f-af7a0d370277",
"type": "Scope"
},
{
"id": "e383f46e-2787-4529-855e-0e479a3ffac0",
"type": "Scope"
},
{
"id": "37f7f235-527c-4136-accd-4a02d197296e",
"type": "Scope"
},
{
"id": "14dad69e-099b-42c9-810b-d002981feec1",
"type": "Scope"
}
]
}
],
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADandPersonalMicrosoftAccount",
"tags": [],
"tokenEncryptionKeyId": null
}
For now the authentication works only for my university domain, but i want to allow the authentication through microsoft personal email, like xxxx#hotmail.com
In your code developed you would be using an endpoint to authorize and get the oauth token.
If you are using MSAL (Microsoft Authentication Library)
The commonly used parameters to configure the client app in your code would
Client ID
Redirect URI
Authority
Client Secret in some cases
So in this, you will have to configure authority url.
https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-client-application-configuration#authority
So for example in your code, if you are building client application object, you would something like below :
string authority = "https://login.microsoftonline.com/common";
string[] scopes = new string[] { "user.read" };
IPublicClientApplication app = PublicClientApplicationBuilder
.Create(clientId)
.WithAuthority(authority)
.Build();
Update :
Go to Bot Channels Registration page (Azure Portal)
Click Setting
OAuth Connection Settings -> Add Setting
In the new setting pag - enter the connection name, client app related informations in the following page
You will be using this connection name in your code.
Here's the catch :
Under tenantid, fill it up as a common rather than a specific tenant id.

Can't get email claim in access_token in Azure AD

We have configured an App Registration for the SPA in Azure, for Auth Code flow.
We have added email under optional claims as per below:
The manifest file is configured as below:
{
"id": "<redacted>",
"acceptMappedClaims": true,
"accessTokenAcceptedVersion": 1,
"addIns": [],
"allowPublicClient": null,
"appId": "<redacted>",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2020-12-03T10:30:07Z",
"disabledByMicrosoftStatus": null,
"groupMembershipClaims": "None",
"identifierUris": [],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": null,
"name": "<redacted>",
"oauth2AllowIdTokenImplicitFlow": false,
"oauth2AllowImplicitFlow": false,
"oauth2Permissions": [],
"oauth2RequirePostResponse": false,
"optionalClaims": {
"idToken": [],
"accessToken": [
{
"name": "email",
"source": null,
"essential": false,
"additionalProperties": []
}
],
"saml2Token": []
},
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [],
"preAuthorizedApplications": [],
"publisherDomain": "<redacted>",
"replyUrlsWithType": [
{
"url": "https://localhost:44338",
"type": "Spa"
}
],
"requiredResourceAccess": [
{
"resourceAppId": "<redacted>",
"resourceAccess": [
{
"id": "<redacted>",
"type": "Scope"
},
{
"id": "<redacted>",
"type": "Scope"
},
{
"id": "<redacted>",
"type": "Scope"
}
]
},
{
"resourceAppId": "<redacted>",
"resourceAccess": [
{
"id": "<redacted>",
"type": "Scope"
}
]
}
],
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADMyOrg",
"tags": [],
"tokenEncryptionKeyId": null
}
We have added the email to the permissions:
And finally on the client side I use MSAL browser to initiate authentication with the following scopes supplied:
However, I can't for the life of me figure out why the email claim is not appearing in the access_token
Please see v1.0 and v2.0 optional claims set.
When adding claims to the access token, the claims apply to access
tokens requested for the application (a web API), not claims requested
by the application.
It means that you email claim apply to the scene that you call your own web API, not call Microsoft Graph API.
You can see details from Protected web API: App registration.
You should configure the email optional claim in the Azure AD app which represents the web API, not the Azure AD app which represents the client end. Then when you request the access token for that API, the email claim will exist in the access token.
Set scope=api://{app id of the AAD app which represents the web api}/.default openid instead of scope=http://graph.microsoft.com/.default openid in the request.
So for calling Microsoft Graph API, you cannot use the built-in email optional claim directly. You need to query the email by calling Microsoft Graph GET https://graph.microsoft.com/v1.0/me/ or use another claim upn in access token.

Single Sign on with personal Microsoft account doesn't work in registered app in Azure

We registered an app in Azure with our corporate account.
We've set it as a web-app type, and set the signInAudience to AzureADandPersonalMicrosoftAccount
It works when we sign into our web-app with a corporate account, but when we use a personal microsoft account with hotmail address, we get the following message:
AADSTS50020: User account '*********#hotmail.com' from identity provider 'live.com' does not exist in tenant '*********' and cannot access the application '******'(***-api) in that tenant. The account needs to be added as an external user in the tenant first. Sign out and sign in again with a different Azure Active Directory user account.
We double checked all settings and they look valid. We've ran out of ideas
Here's a version of our manifest:
{
"id": "**********",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": null,
"appId": "*********",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2020-08-04T14:32:25Z",
"groupMembershipClaims": "None",
"identifierUris": [
"https://***.company.be"
],
"informationalUrls": {
"termsOfService": "https://www.company.be/legals/gebruiksvoorwaarden",
"support": null,
"privacy": "https://www.company.be/legals/privacy",
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": "https://secure.aadcdn.microsoftonline-p.com/...",
"logoutUrl": null,
"name": "***-api",
"oauth2AllowIdTokenImplicitFlow": true,
"oauth2AllowImplicitFlow": false,
"oauth2Permissions": [],
"oauth2RequirePostResponse": false,
"optionalClaims": {
"idToken": [
{
"name": "email",
"source": null,
"essential": false,
"additionalProperties": []
},
{
"name": "family_name",
"source": null,
"essential": false,
"additionalProperties": []
},
{
"name": "given_name",
"source": null,
"essential": false,
"additionalProperties": []
}
],
"accessToken": [],
"saml2Token": []
},
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [
{
"customKeyIdentifier": null,
"endDate": "2299-12-30T23:00:00Z",
"keyId": "**********",
"startDate": "2020-08-04T14:47:56.759Z",
"value": null,
"createdOn": "2020-08-04T14:47:58.647043Z",
"hint": "gIh",
"displayName": "*****-api clientSecret"
}
],
"preAuthorizedApplications": [],
"publisherDomain": "company.be",
"replyUrlsWithType": [
{
"url": "http://localhost:3000/link/microsoft/callback",
"type": "Web"
},
{
"url": "https://api.copmpany.be/link/microsoft/callback",
"type": "Web"
},
{
"url": "https://api.copmpany.be/auth/microsoft/callback",
"type": "Web"
},
{
"url": "https://api.staging.copmpany.be/link/microsoft/callback",
"type": "Web"
},
{
"url": "https://api.staging.copmpany.be/auth/microsoft/callback",
"type": "Web"
},
{
"url": "http://localhost:3000/auth/microsoft/callback",
"type": "Web"
}
],
"requiredResourceAccess": [
{
"resourceAppId": "***",
"resourceAccess": [
{
"id": "****",
"type": "Scope"
},
{
"id": "***",
"type": "Scope"
},
{
"id": "***",
"type": "Scope"
},
{
"id": "***",
"type": "Scope"
},
{
"id": "***",
"type": "Scope"
}
]
}
],
"samlMetadataUrl": null,
"signInUrl": "https://www.company.be",
"signInAudience": "AzureADandPersonalMicrosoftAccount",
"tags": [
"webApp",
"notApiConsumer"
],
"tokenEncryptionKeyId": null,
"verifiedPublisher": {
"displayName": null,
"verifiedPublisherId": null,
"addedDateTime": null
}
}
In addition to Sarthak's answer if your business scenario doesn't need to access your tenant's resource like call MS Graph API for your tenant, You could change your authority Uri to common endpoint which supports MSA without inviting into tenant. Please refer the documentation on for the authority endpoints. Depending upon your business scenario, choose your solution.
From your manifest file I can see that your app is already registered as multi-tenant, so no need to change any settings there.
The user should be invited before we sign or connect with our azure active directory as an external user, follow the below steps:
Visit here https://portal.azure.com/#blade/Microsoft_AAD_IAM/UsersManagementMenuBlade/MsGraphUsers
Invite as a guest user
Then the invited user will get an invitation, accept that first.
Retry to access the web app.
Definitely it would work.
Sign in option AzureADandPersonalMicrosoftAccount only works with v2.0. Hence, the authority URL should be this:
https://login.microsoftonline.com/common/v2.0
In addition to that, for multitenant applications, ValidateIssuer option should be disabled. You can do that in this way:
auth.AddOpenIdConnect(authScheme, displayName, options =>
{
options.TokenValidationParameters.ValidateIssuer = false;
)};
The app should be registered as multi-tenant for this to work.

Resources