Azure Signed In User Email

I am trying to get the Users' signed-in email address using Azure AD for user authentication, but whatever I try, I cannot get their email address. Any help would be appreciated.

1 Like

What have you tried?

I have tried using the Current application user email, but the error I get is that the Email in the user does not exist. I have also tried adding "Email" as a scope.

Simon

Same problem here. When accessing attribute Email of the the ApplicationUser object via ${Security.User.Email}, what the Radzen editor sees somehow:
image

dotnet: C:\git\myproject\server\Pages\Login.razor(27,48): 
error CS1061: 'ApplicationUser' does not contain a definition for 'Email' and no accessible extension method 'Email' accepting a first argument of type 'ApplicationUser' could be found (are you missing a using directive or an assembly reference?)

I saw that it is not part of the class, so I guess I have to add it. But I am not sure if this is the way, because the email is not a custom attribute, it is already in the ID token I guess.
Extend application user | Blazor (Blazor) (radzen.com)

Radzen incorrectly shows that the ApplicationUser has an Email property (it does have it when Default security is used). Email isn't available as a property in Azure AD security. You can probably extend the ApplicationUser and read the email from the claims. You will have to customize the SecurityService to do so and use the code generation ignore list.

1 Like

I added the custom application user file:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Runtime.Serialization;

namespace Myproject.Models
{
    public partial class ApplicationUser
    {
        public string Email { get; set; }
    }
}

and the build error has gone, but the field was still empty, even the claim in the code returned the email (I checked it in the debugger, the plural in "Emails" is correct, according to the Azure AD attributes). I added this to SecurityService.cs in line 52:

  var email = Principal?.FindFirstValue(ClaimTypes.Email) ?? Principal?.FindFirstValue("Emails");
  if (user == null && name != null)
            {
                user = new ApplicationUser { Name = name , Email = email};
                //user.Email = email; // also tried this
            }

So, I executed the schema EF migration command from the documentation and got this error:
No DbContext named 'ApplicationIdentityDbContext' was found.

PS C:\git\myproject> dotnet tool install --global dotnet-ef
You can invoke the tool using the following command: dotnet-ef
Tool 'dotnet-ef' (version '6.0.3') was successfully installed.
PS C:\git\myproject> cd server
PS C:\git\myproject\server> dotnet ef migrations add Email -c ApplicationIdentityDbContext
Build started...
Build succeeded.
No DbContext named 'ApplicationIdentityDbContext' was found.

Radzen does not generate ApplicationIdentityDbContext when using Azure AD. I suggest you debug the code and check what claims are returned. This could also be an Azure AD configuration problem and the email may not be returned at all as a claim.

1 Like

It works: I stopped the server, until now I just "reloaded" the binary in Visual Code. I added the modified SecurityService.cs to the "code generation ignore list" in the Application Settings and run the application from within Radzen again. (I don't think the dotnet call above had any influence to make it work, because as you said there is no ApplicationIdentityDbContext in my case). But your hint helped me to not dig deeper there. Thanks!

I need to extract AzureAD Attribute "User Principal Name". I have debugged ClaimTypes and found out that it is named as "Upn"... but how can I debug the second part for possible values?

...?? Principal?.FindFirstValue("???");

Could you give me a hint, please?

I first activated email related claims in Azure. (Can't see any "upn" here, but this is a user flow, are you using a custom policy?)

And then I debugged the claims coming in to determine, the string I shall look for:

No upn in here too, but I would be interested how you got it into the claim.

1 Like

It is available for me under AppRegistrations --> TokenConfiguration --> OptionalClaims.
I cannot say why this attribute is available in our environment because I have limited right on Azure Portal. Thanks for your answer!

1 Like

Ok, found out, that your view shows possible claims of an Azure AD resource. In my example I use an Azure AD B2C resource and there I have the claim configuration inside the User flow.
Back to your question (until I get a Upn into my B2C AD) I can only guess: I found there is a ClaimType "Upn" and the name afterwards I would guess "upn" or something you will see in your debugger when you look at the "Principal" content during the authentication:
var upn = Principal?.FindFirstValue(ClaimTypes.Upn) ?? Principal?.FindFirstValue("upn");

Thank you, I will check that in the next days and leave a reply.

Ok, finally got it:
At first, I checked which claim from my user profile I want to access in radzen:

After that, I accessed the desired claim value by using this line of code:

Next thing I want to access is my profile picture to show it in radzen profile menu. If I got it I let you know.

2 Likes

By logging in with Azure you dont have access to user profile picture by default. You need to add some permissions on the application in Azure to be able to get the user pixture. The user also need to confirm that you acces their profile picture when logging in.

1 Like

Follow-up-question: Has anyone ever tried to access AzureAD-Approles on Radzen Blazor? I´ve followed a lot of threads to this topic but I am no closer to solution...

Have you checked this section from the Azure AD documentation?

Hello Korchev,

yes I did. I need to access the user´s approles (claims?) in the server part of my app:
image

But I fail to access them similar to my screenshot above:
image

There are a lot of claims available but no role claims.

It is AzureAD that returns the claims so we are not sure why it doesn't do that in your case. Could be some configuration issue but we are not sure what.

Indeed, there was a configuration issue on my side.
It is working now as expected.