Dear support, I'm configurating SSO with Microsoft Entra using OpenId provider
The configuration seems good but I'm facing an error when the code call the method: /api/TokenAuth/ExternalAuthenticate
The error is: "Both name and http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress claims are missing! You can use claims mapping to map one of the retrieved claims to name or http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress claim."
And the frontend show the same error on popup:

Below my appsettings:
"Authentication": {
"AllowSocialLoginSettingsPerTenant": true,
....
"OpenId": {
"IsEnabled": "true",
"ClientId": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
"Authority": "https://login.microsoftonline.com/organizations/v2.0",
"LoginUrl": "https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize",
"ValidateIssuer": "false",
"ResponseType": "id_token",
"ClaimsMapping": [
{
"claim": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
"key": "id"
},
{
"claim": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
"key": "name"
},
{
"claim": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname",
"key": "given_name"
},
{
"claim": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname",
"key": "family_name"
},
{
"claim": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"key": "email"
}
]
},
...
},
As you can see, the "emailaddress" claim is declared
Any suggestion?
Thanks in advance
Br, Fabrizio
10 Answer(s)
-
0
Hi @dominici
May I know your project version so that I can repeat this situation? In the latest version, when you try to log in and register with OpenIdConnect social login with the setting you specified, it does not give this error.
Can you debug the
jsonClaimMappingsvariable in theCreateExternalLoginInfomethod in theTenantBasedOpenIdConnectExternalLoginInfoProviderclass? Are the claims mappings correct as you set them here?Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
Hi @oguzhanagir, my project is Asp Net Core + Angular version 13.2.0
I've not tried with last version but I'm going to do it.
In the meanwhile:
This is the
jsonClaimMappingsin theGetOpenIdConnectExternalLoginProviderSettingsAs you can see, is valued and the email one is present
Then, is not possible to trace the
jsonClaimMappingsin theCreateExternalLoginInfobecause the exception is raised before. In detail, the exception is raised in theGetExternalUserInfomethod of classTokenAuthControllerThanks you
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
Hi @dominici
Can you look at the Claims value in the return values of the
GetExternalLoginInfomethod in theTenantBasedExternalLoginInfoProviderBaseclass? Are the email claims coming correctly here? Maybe the email claim is not coming here because the values come from the cache?Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
Hi @oguzhanagir, I've just tried with the last version of Asp Net Zero Core + Angular 14.1.0
Test environment: I've downloaded the project, created th db with the default tenant and then inserted one single user. No changes to the code
1 - Fist test using my claims definition
"ClaimsMapping": [ { "claim": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "key": "id" }, { "claim": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", "key": "name" }, { "claim": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname", "key": "given_name" }, { "claim": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname", "key": "family_name" }, { "claim": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", "key": "email" } ]The result is the same of my real project -> Exception -> "Both name and http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress claims are missing! You can use claims mapping to map one of the retrieved claims to name or http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress claim."
2 - Second test using the claims definition provided by the template
"ClaimsMapping": [ { "claim": "unique_name", "key": "preferred_username" } ]Inexplicably this works and I can read all the necessary claims. I'm really surprised ....
But, always inexplicably, the login fails because it can't find the only user I created on the database. Also, the system tries to register it but fails because the email already exists. I'm really confused...
3 - Third test using my real project (AbpZero 13.2.0) and the new claims mapping
"ClaimsMapping": [ { "claim": "unique_name", "key": "preferred_username" } ]Also in this case, the SSO works, the claims are ok but the login not. User is found but the login fail. Then the attempt to register the user fail because the email is already used.
Do you have any suggestion?
Thanks in advance
Br, Fabrizio
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
Maybe the email claim is not coming here because the values come from the cache?
I'm doing all tests using private browsing and checking the cache, so I can exclude that
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
Hi @dominici
Have you defined the email claim in the Token configuration section on the Entra ID side? If you have not made a definition, you need to add it as shown in the screenshot below. Otherwise, it will give the error you specified because it does not match the information from the OpenId validation result.
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
Hello @oguzhanagir,
Have you defined the email claim in the Token configuration section on the Entra ID side?
Yes, I have defined the email claim
Coming back to AbpZero, I did another significant test.
Test environment: New project AbpZero Core + Angulare v14.1.0. No changes to the code
Test case
IMPORTANT: I've deleted the user created using the AbpZero UI, so my test user is not registered
Using this claims configuration
"ClaimsMapping": [ { "claim": "unique_name", "key": "preferred_username" } ]The SSO with my user works but (in this case it's the right behaviour) the user is not found on database. Then the user is succesfully registrered and all the SSO process works as expected. Yeah! What an effort!
It seems that without this data

the SSO process fail.
Conclusion
I don't know if this behaviour is by design but, IMHO:
- SSO should works also on users created without the SSO process. Think about a legacy database, existing users, etc... Is not sufficient using only TenantId and Email?
- Claims mapping documentation. I don't know if the documentation is up to date, it seems misaligned respect to the Microsoft Entra Id specification. I know it's hard to do
- there is a bug on this line of code:
authConfig.skipIssuerCheck = loginProvider.additionalParams['ValidateIssuer'] === 'false';The value coming from API is "False" even if in the appsettings it is written as "false". So, the issuer check is never skipped
Questions
1 - If the SSO require a record on table AbpUserLogins for every single user/tenant, how to fix it for the existing users? I have to override your provider and skip the AbpUserLogins check on SSO? 2 - Same as above, how to enable new registered users to SSO? I think I have to implement something. Do you see other solutions?
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
Hello @oguzhanagir, any news?
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
1
Hi @dominici
Sorry for the late reply. Thanks for your feedback. We can add this as a feature, we created an issue for this, you can follow the developments here. I will be suggesting a temporary solution for this situation.
Here, you can update the
RegisterExternalUserAsyncmethod inTokenAuthControlleras shown in the example below, so that a user who is not previously registered with external login in your system can log in with external login. In this way, your registered user will be able to log in to the system with external login. However, you may need to add setting on the system side here. This setting should check whether the user is not registered with external login but can log in with external login. Or, when the user logs in with a previously registered user with external login, a one-time confirmation code can be sent as a notification to the normally logged-in system. This is a temporary solution for you.private async Task<User> RegisterExternalUserAsync(ExternalAuthUserInfo externalLoginInfo) { string username; using (var providerManager = _externalLoginInfoManagerFactory.GetExternalLoginInfoManager(externalLoginInfo.Provider)) { username = providerManager.Object.GetUserNameFromExternalAuthUserInfo(externalLoginInfo); } var registeredUser = await _userManager.FindByEmailAsync(externalLoginInfo.EmailAddress); var user = registeredUser ?? await _userRegistrationManager.RegisterAsync( externalLoginInfo.Name, externalLoginInfo.Surname, externalLoginInfo.EmailAddress, username, await _userManager.CreateRandomPassword(), true, null ); user.Logins = new List<UserLogin> { new UserLogin { LoginProvider = externalLoginInfo.Provider, ProviderKey = externalLoginInfo.ProviderKey, TenantId = user.TenantId } }; await CurrentUnitOfWork.SaveChangesAsync(); return user; }
We have created a separate issue for this situation. You can follow the developments in this issue.
there is a bug on this line of code: authConfig.skipIssuerCheck = loginProvider.additionalParams['ValidateIssuer'] === 'false'; The value coming from API is "False" even if in the appsettings it is written as "false". So, the issuer check is never skipped
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
Hi @oguzhanagir, I confirm the work-around works as expected.
I'll follow the issues resolution related to this topic.
Thanks for support, have a good day
Fabrizio
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image)


