Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to access "ID token"/"claims" in Web Controllers? #147

Closed
spalmcc opened this issue Mar 28, 2023 · 5 comments
Closed

How to access "ID token"/"claims" in Web Controllers? #147

spalmcc opened this issue Mar 28, 2023 · 5 comments

Comments

@spalmcc
Copy link

spalmcc commented Mar 28, 2023

Hello All

We are working on integrating "Azure AD B2C" authentication in MVC 3 based existing application. This is an old application where we are passing logged on "user name" and password for different purposes.
I have integrated "Azure AD B2C" at the moment. To continue with my work, I need to have access to logged in user name in controlers.

What is the limitation?
By default "userName" from Azure AD B2C is not getting populated in the claims due to the limitation mentioned here Azure-Samples/active-directory-b2c-dotnetcore-webapp#64.

How we are overcoming mentioned limitation?
We have added a custome attribute with name "userName" and this value would get populated during account migration.
At the moment, we have populated that attribute using powershell script to continue our work.

How claims is being accessed?
I am able to parse the claims and get access to that custome attribute in claims. Refer the following code

private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
        {
            try
            {
                /*
				 The `MSALPerUserMemoryTokenCache` is created and hooked in the `UserTokenCache` used by `IConfidentialClientApplication`.
				 At this point, if you inspect `ClaimsPrinciple.Current` you will notice that the Identity is still unauthenticated and it has no claims,
				 but `MSALPerUserMemoryTokenCache` needs the claims to work properly. Because of this sync problem, we are using the constructor that
				 receives `ClaimsPrincipal` as argument and we are getting the claims from the object `AuthorizationCodeReceivedNotification context`.
				 This object contains the property `AuthenticationTicket.Identity`, which is a `ClaimsIdentity`, created from the token received from
				 Azure AD and has a full set of claims.
				 */
                ClaimsPrincipal objClaims = new ClaimsPrincipal(notification.AuthenticationTicket.Identity);
                int count = objClaims.Claims.Count();
                IConfidentialClientApplication confidentialClient = MsalAppBuilder.BuildConfidentialClientApplication(objClaims);
                // IConfidentialClientApplication confidentialClient = MsalAppBuilder.BuildConfidentialClientApplication(new ClaimsPrincipal(notification.AuthenticationTicket.Identity));

                // Upon successful sign in, get & cache a token using MSAL
                AuthenticationResult result = await confidentialClient.AcquireTokenByAuthorizationCode(Globals.Scopes, notification.Code).ExecuteAsync();
                
                DisplayUserInfo(result);
                
            }
            catch (Exception ex)
            {
                throw new HttpResponseException(new HttpResponseMessage
                {
                    StatusCode = HttpStatusCode.BadRequest,
                    ReasonPhrase = $"Unable to get authorization code {ex.Message}."
                });
            }
        }

        private void DisplayUserInfo(AuthenticationResult authResult)
        {
            if (authResult != null)
            {
                var token = new JwtSecurityToken(jwtEncodedString: authResult.IdToken);
                // string expiry = token.Claims.First(c => c.Type == "expiry").Value;
                string userName = token.Claims.First(c => c.Type == "extension_userName").Value;
            }
        }

How I can access "Id token"/"claims" in the web controllers?
Is there any way to access id toke or claims in the controllers?

Any pointers would be helpful.

best regards
S

@spalmcc
Copy link
Author

spalmcc commented Apr 17, 2023

Finally someone responded to me over another forum:-

var claims = (HttpContext.User as ClaimsPrincipal).Claims;
var enume = claims.GetEnumerator();
while (enume.MoveNext())
{
var data = enume.Current;
// var claimType = data.Type;
switch (data.Type)
{
case "name":
loggedInUserName = data.Value.ToString();
break;
case "extension_CustomRole":
roles = data.Value.ToString().Split(',');
break;

            }
        }

This is how, it can be done.
Thanks to Alfredo Revilla (MSFT)

@spalmcc spalmcc closed this as completed Apr 17, 2023
@spalmcc
Copy link
Author

spalmcc commented Apr 17, 2023

Sad to experince MS team do not care...

@jmprieur
Copy link
Contributor

jmprieur commented Apr 17, 2023

@spalmcc sorry for the delay and if you had the impression we don't care. We do care (but lost people recently ...)
From the controller, you can user HttpContext.User.GetDisplayName() if you use Microsoft.Identity.Web which adds extension methods to ClaimsPrincipal (which we recommend you do as you are on ASP.NET Core).

See https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/blob/master/1-WebApp-OIDC/1-5-B2C/README.md

@spalmcc
Copy link
Author

spalmcc commented Apr 17, 2023

Hello jmprieur, people who are working to implement B2C Auth are dependent on the documention and support from MS teams. When we are stuck and we dont hear from MS team, we dont know what do you. Someone replied to me from another forum. I posted here so that others can get help.

But I am happy now to see respone coming from MS people.

We are facing another issue #149
Could someone look into that and share some pointers? (FYI-Someone is responding on this now so please ignore this request.. )

You would know what we are getting null in account.

best regards,
S

@bgavrilMS
Copy link
Contributor

To sum up - to access the id token claims, you can look into the ClaimsPrincipal object https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsprincipal?view=net-7.0

This is available as (HttpContext.User as ClaimsPrincipal). If it is not present, it means the user is not authenticated and needs to be challenged.

@bgavrilMS bgavrilMS closed this as not planned Won't fix, can't repro, duplicate, stale Oct 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants