I have the following code to configure the process of authentication in my ASP.NET MVC web application, including the setting a claim to the user's "name" when validating the user's identity token received by the application.
(Note that I am following this sample code)
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
CookieSecure = CookieSecureOption.Always
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
// Generate the metadata address using the tenant and policy information
MetadataAddress = String.Format(AadInstance, Tenant, DefaultPolicy),
// These are standard OpenID Connect parameters, with values pulled from web.config
ClientId = ClientId,
Authority = Authority,
PostLogoutRedirectUri = RedirectUri,
RedirectUri = RedirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications()
{
RedirectToIdentityProvider = OnRedirectToIdentityProvider,
AuthenticationFailed = OnAuthenticationFailed,
AuthorizationCodeReceived = OnAuthorizationCodeReceived,
},
// Specify the claims to validate
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name"
},
// Specify the scope by appending all of the scopes requested into one string (separated by a blank space)
Scope = $"{OpenIdConnectScopes.OpenId} {ReadTasksScope} {WriteTasksScope}"
});
}
The "name" claim type maps to the user's DisplayName
, which is returned when I use the code User.Identity.Name
.
How can I get User.Identity.Name
to map to the user's Username, like in the below screenshot of an Azure Active Directory B2C user?
Here is the 2nd half of the answer above, which includes the code changes that were made:
Add the line of code commented with "Added line here" so that the user's ObjectId
is claimed:
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
{
// Extract the code from the response notification
var code = notification.Code;
string signedInUserID = notification.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
TokenCache userTokenCache = new MSALSessionCache(signedInUserID, notification.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase).GetMsalCacheInstance();
ConfidentialClientApplication cca = new ConfidentialClientApplication(ClientId, Authority, RedirectUri, new ClientCredential(ClientSecret), userTokenCache, null);
///////////////////////////////////
// Added line here
///////////////////////////////////
// Add a custom claim to the user's ObjectId ('oid' in the token); Access it with this code: ((System.Security.Claims.ClaimsIdentity)User.Identity).FindFirst("ObjectId").Value
notification.AuthenticationTicket.Identity.AddClaim(new System.Security.Claims.Claim("ObjectId", signedInUserID));
try
{
AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(code, Scopes);
}
catch (Exception ex)
{
MyLogger.LogTrace("Failed to retrieve AuthenticationResult Token for user " + signedInUserID, MyLogger.LogLevel.Critical);
return;
}
}
Then later in the web application, when you need to get and use the user's ObjectId
, do this:
try
{
string signedInUserObjectId = ((System.Security.Claims.ClaimsIdentity)User.Identity).FindFirst("ObjectId").Value;
}
catch (Exception e)
{
... This should never happen, but better safe than sorry ...
}
And lastly, using the Azure AD graph client, you can get the user object using ObjectId
, which contains the user name. The specific query you will need is GET https://graph.windows.net/myorganization/users/{user_id}?api-version
. You may need to get the UserPrincipalName
or a SignInName
, depending on your type of user. For more information, see the "Get a user" section here.