I'm trying to migrate from Umbraco 8.x to 9.0.1. All works fine, except the external backoffice authentication (Azure B2C). In this case I want to login using Azure AD B2C (which currencly has local accounts, and Azure AD. In the future there will be more options).
I try to simplify this implementation by using the build in external login providers (https://our.umbraco.com/documentation/reference/security/external-login-providers/).
My current setup let me authenticate against Azure AD B2C. The login works fine. The one thing is that after a succesful login, Umbraco says the email claim is missing:
I tried to hook into OnAutoLinking and OnExternalLogin, but this seems not to be called yet (https://our.umbraco.com/documentation/reference/security/auto-linking/#transfering-claims-from-external-identities).
When I take a look at the claims that are returned, I do have an 'emails' claim. I do not have the 'email' claim. I would like to use the value from 'emails' for linking the accounts.
This specific issue is resolved by adding the claim after the external authentication occurs.
Remark: this is not in production yet. You might need some null checks for example. Also I'm not sure if this will work for every identity providering configured in your B2C tenant.
private static Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext ctx)
{
// This is where we appear after a successfull login, since we use AADB2C Open ID Connect, we already get a lot with the initial authorization code
ctx.Options.Events.OnAuthorizationCodeReceived = async context =>
{
context.ProtocolMessage.RedirectUri = context.ProtocolMessage.RedirectUri.Replace("http:", "https:");
await Task.FromResult(0);
};
// Get the current claims
var claims = ctx.Principal?.Claims;
// Find the original JWT token
string jwtTokenFromIdentityProvider =
claims.Where(m => m.Type.Equals("idp_access_token", StringComparison.OrdinalIgnoreCase))
.Select(m => m.Value).FirstOrDefault();
// Resolve the token to a readable format
var handler = new JwtSecurityTokenHandler();
var jsonToken = handler.ReadToken(jwtTokenFromIdentityProvider);
var tokenFromIdentityProvider = (JwtSecurityToken)jsonToken;
// Get the principal name (so: the login email)
var principalName = tokenFromIdentityProvider.Claims.First(claim => claim.Type == "upn").Value;
// Define the new claim
var claimsToAdd = new List<Claim>
{
new Claim("email", principalName)
};
// Add the claim by adding a new ClaimsIdentity
var appIdentity = new ClaimsIdentity(claimsToAdd);
ctx.Principal.AddIdentity(appIdentity);
var user = ctx.Principal;
var identity = user.Identity as ClaimsIdentity;
var claim = (from c in user.Claims
where c.Type == "idp_access_token"
select c).Single();
identity.RemoveClaim(claim);
return Task.CompletedTask;
}
I had a similar issue, email wasn't set in properties on the user in Active directory / Microsoft Entra ID. So I enabled upn claim in the token configuration. upn claim will contain the email id that was used to login in to Microsoft. Then on OnTokenValidated event I check if the email claim isn't present then simply add upn claim value to email claim like this:
options.Events = new OpenIdConnectEvents
{
OnTokenValidated = context =>
{
var principal = context.Principal;
if (principal is null) throw new InvalidOperationException("No claims found.");
// check if email claim doesn't exist and if so, add it from upn claim type
if (!principal.HasClaim(x => x.Type == ClaimTypes.Email))
{
var loggedInEmail = principal.FindFirst(ClaimTypes.Upn)?.Value;
// append loggedInEmail value as a email claim to context principal
if (!string.IsNullOrEmpty(loggedInEmail))
{
var emailClaim = new Claim(ClaimTypes.Email, loggedInEmail);
principal.AddIdentity(new ClaimsIdentity(new[] { emailClaim }));
}
}
return Task.CompletedTask;
}
};
ExternalLogin Azure B2C email claim in Umbraco 9
Hi there,
I'm trying to migrate from Umbraco 8.x to 9.0.1. All works fine, except the external backoffice authentication (Azure B2C). In this case I want to login using Azure AD B2C (which currencly has local accounts, and Azure AD. In the future there will be more options).
The old implementation of the external login was quite different (based on https://24days.in/umbraco-cms/2019/aad-and-headless/umbraco8-aadb2c/)
I try to simplify this implementation by using the build in external login providers (https://our.umbraco.com/documentation/reference/security/external-login-providers/).
My current setup let me authenticate against Azure AD B2C. The login works fine. The one thing is that after a succesful login, Umbraco says the email claim is missing:
The implementation I used came from https://our.umbraco.com/documentation/reference/security/auto-linking/
I tried to hook into OnAutoLinking and OnExternalLogin, but this seems not to be called yet (https://our.umbraco.com/documentation/reference/security/auto-linking/#transfering-claims-from-external-identities).
When I take a look at the claims that are returned, I do have an 'emails' claim. I do not have the 'email' claim. I would like to use the value from 'emails' for linking the accounts.
How can I get this account linking to work?
This specific issue is resolved by adding the claim after the external authentication occurs.
Remark: this is not in production yet. You might need some null checks for example. Also I'm not sure if this will work for every identity providering configured in your B2C tenant.
I had a similar issue, email wasn't set in properties on the user in Active directory / Microsoft Entra ID. So I enabled
upn
claim in the token configuration.upn
claim will contain the email id that was used to login in to Microsoft. Then onOnTokenValidated
event I check if the email claim isn't present then simply add upn claim value to email claim like this:Don't forget to add
upn
claim first:is working on a reply...
This forum is in read-only mode while we transition to the new forum.
You can continue this topic on the new forum by tapping the "Continue discussion" link below.