Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at

  • Bjorn 4 posts 94 karma points
    Oct 26, 2021 @ 07:25

    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

    I try to simplify this implementation by using the build in 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:

    Umbraco B2C email claim missing

    The implementation I used came from

    I tried to hook into OnAutoLinking and OnExternalLogin, but this seems not to be called yet (

    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?

  • Bjorn 4 posts 94 karma points
    16 days ago

    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);
            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();
            return Task.CompletedTask;
Please Sign in or register to post replies

Write your reply to: