davidjrh / dnn.azureadprovider

The DNN Azure Active Directory Provider is an Authentication provider for DNN Platform (formerly DotNetNuke) that uses Azure Active Directory OAuth2 authentication to authenticate users.
MIT License
35 stars 21 forks source link

Claim 'upn' was not found on the token. #40

Closed maduranga001 closed 10 months ago

maduranga001 commented 3 years ago

I can not load the ADD login interface through the login page. I am receiving the following error and I found it on the AdminLog page.

Why I am receiving this error? Please, help.

Claim 'upn' was not found on the token. Available claims are: , aud, iss, iat, nbf, exp, acr, aio, amr, appid, appidacr, email, family_name, given_name, idp, ipaddr, name, oid, rh, scp, sub, tid, unique_name, uti, ver

What and where I have missed? Appreciate your support.

Thank you!

maduranga001 commented 3 years ago

I just changed 'upn' token for now to 'unique_name'. token.

But still, one thing to clarify. It loads the profile data from the Azure AD account. But not all profile data. I can not find appropriate tokens that I use to map with DNN profile fields.

Ex: DNN Fileds - PhoneNumber, Photo, country, region, city etc. What are the Azure AD tokens to use in the 'Mapping -> User Mapping' in the module settings?

Appreciate your support. Thank you.

JRPonte commented 3 years ago

I'me having a similar issue, I'me getting this error:

Claim 'given_name' was not found on the token. Available claims are: , aud, iss, iat, nbf, exp, acr, aio, amr, appid, appidacr, ipaddr, name, oid, onprem_sid, rh, scp, sub, tid, unique_name, upn, uti, ver

The claim is there for some users, but not for others. If the claim is not present the value should be empty, and not present an error.

miguelvaz78 commented 2 years ago

Hi, I am having the same issue when users do not have their names (given_name or family_name) set in the active directory. For this reason, the login process fails. I am thinking on having some rule that can fill these values based on the name (splitting by spaces to get the first and last names). Anyone has a better idea?

Unfortunately, I cannot ask the active directory managers to fill out the names correctly so I have to come up with something else.

davidjrh commented 2 years ago

I've seen this behavior and on other apps they just put "Unknown" as the name. I believe that's better than throwing an exception. Sounds like another advanced setting.

miguelvaz78 commented 2 years ago

Hi all,

Just a quick note. What I have done to surpass my issue not having some AD fields set was to be a little more permissive and have a method for falling back when first or last name are not defined:

Hope this contribution helps someone:

internal AzureUserData GetCurrentUserInternal(JwtSecurityToken pToken = null)
        {
            if (pToken == null && (!IsCurrentUserAuthorized() || JwtIdToken == null))
            {
                return null;
            }
            var claims = JwtIdToken.Claims.ToArray();
            //EnsureClaimExists(claims, FirstNameClaimName);
            //EnsureClaimExists(claims, LastNameClaimName);
            EnsureClaimExists(claims, DisplayNameClaimName);
            EnsureClaimExists(claims, EmailClaimName);
            EnsureClaimExists(claims, UserIdClaim);
            EnsureClaimExists(claims, "oid");       // we need this claim to make calls to AAD Graph

            var user = new AzureUserData()
            {
                AzureFirstName = claims.FirstOrDefault(x => x.Type == FirstNameClaimName)?.Value,
                AzureLastName = claims.FirstOrDefault(x => x.Type == LastNameClaimName)?.Value,
                AzureDisplayName = claims.FirstOrDefault(x => x.Type == DisplayNameClaimName)?.Value,
                Email = claims.FirstOrDefault(x => x.Type == EmailClaimName)?.Value,
                Id = claims.FirstOrDefault(x => x.Type == UserIdClaim).Value
            };
            //If no first name, try and get it from the display name.
            if (string.IsNullOrEmpty(user.AzureFirstName))
            {
                user.AzureFirstName = user.AzureDisplayName.Split(' ')
                    .First();
            }
            //If no last name, try and get it from the display name.
            if (string.IsNullOrEmpty(user.AzureLastName))
            {
                user.AzureLastName = user.AzureDisplayName.Split(' ')
                    .Skip(1)
                    .Aggregate("", (current, next) => current + " " + next);
            }
            user.AzureDisplayName = $"{user.AzureFirstName} {user.AzureLastName}";
            return user;
        }
davidjrh commented 2 years ago

This is interesting, in most of scenarios I've seen this error, is because what's not filled is the DisplayName. Thing to note when developing this enhancement.

Thanks for for your contribution!

davidjrh commented 1 year ago

maduranga001 about the initial error related to the "upn" not being found in the token, the reason could be that the user being logged is a B2B user (this is a guest user in the current tenant).

Hope this helps.

davidjrh commented 10 months ago

This has been now fixed