1

I have been working with AADB2C Authentication and struggling over redirecting the user to home page with id_token as fragment in redirect url. below is how i initiate authentication challenge in Account controller

public class AccountController : Controller
{
    public AzureAdB2COptions AzureAdB2COptions { get; set; }

    public AccountController(IOptions<AzureAdB2COptions> b2cOptions)
    {
        AzureAdB2COptions = b2cOptions.Value;
    }
    // GET: /<controller>/
    [HttpGet]
    public IActionResult SignUpSignIn()
    {
        var redirectUrl = "http://localhost:7878/dasdfsd/home";
        return Challenge(
            new AuthenticationProperties { RedirectUri = redirectUrl },
            OpenIdConnectDefaults.AuthenticationScheme);

    }
}

and below is where i redirect user to redirect url(http://localhost:7878/dgddfg/home) with id token fragmented along with url

            public async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext context)
        {

            // Use MSAL to swap the code for an access token
            // Extract the code from the response notification
            var code = context.ProtocolMessage.Code;

            string signedInUserID = context.Principal.FindFirst(ClaimTypes.NameIdentifier).Value;
            TokenCache userTokenCache = new MSALSessionCache(signedInUserID, context.HttpContext).GetMsalCacheInstance();
            ConfidentialClientApplication cca = new ConfidentialClientApplication(AzureAdB2COptions.ClientId, AzureAdB2COptions.Authority, AzureAdB2COptions.RedirectUri, new ClientCredential(AzureAdB2COptions.ClientSecret), userTokenCache, null);
            try
            {
                AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(code, AzureAdB2COptions.ApiScopes.Split(' '));
                context.HandleCodeRedemption(result.AccessToken, result.IdToken);
                context.HandleResponse();
                context.Response.Redirect("dfgfd/home#grant_type=" + context.ProtocolMessage.GrantType + "&id_token=" + result.IdToken);
            }
            catch (Exception)
            {
                //TODO: Handle
                throw;
            }
        }

when user redirects to home page using javascript i get the id_token from url and calling Account controller action("GetAccessTokenAsync") to get access token using identity user

 [HttpGet]
    public async Task<string> GetAccessTokenAsync()
    {
       string signedInUserID = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
        TokenCache userTokenCache = new MSALSessionCache(signedInUserID , HttpContext).GetMsalCacheInstance();
        ConfidentialClientApplication cca = new ConfidentialClientApplication(AzureAdB2COptions.ClientId, AzureAdB2COptions.Authority, AzureAdB2COptions.RedirectUri, new ClientCredential(AzureAdB2COptions.ClientSecret), userTokenCache, null);
        try
        {
            var userAccounts = await cca.GetAccountsAsync();
            if (userAccounts == null && userAccounts.Count()==0)
            {
                throw new Exception("The User is NULL.  Please clear your cookies and try again.  Specifically delete cookies for 'login.microsoftonline.com'.  See this GitHub issue for more details: https://github.com/Azure-Samples/active-directory-b2c-dotnet-webapp-and-webapi/issues/9");
            }
            AuthenticationResult result = await cca.AcquireTokenSilentAsync(AzureAdB2COptions.ApiScopes.Split(' '),userAccounts.FirstOrDefault());
            return result.AccessToken;

        }
        catch (Exception ex)
        {
            //TODO: Handle
            return "";
        }
    }

the problem here is the HttpContext.User in action method is null. but if i remove the part where i have written the redirect url with id_token appended and context.HandleResponse();in OnAuthorizationCodeReceived , user will be redirected without the id token yet when getAccessToken action executed HttpContext.User will not be null, user will have every detail including claims.

How can i redirect user with id token in url and also to have user without being null to get access token in controller method? Is it something to do with cookie?

SINFER
  • 147
  • 6
  • 18

1 Answers1

2

I don't know why you need ID token in javascript , ID token contains user profile information (like the user's name, email, and so forth) , these claims are statements about the user but should not include sensitive information.

If you want to get the user claims you can query claims from HttpContext.User object and pass related claims to client side . Or directly get the user's profile information from Azure AD using Microsoft Graph API .

You can use cookie to store the id token in OnAuthorizationCodeReceivedevent, something like :

 context.Response.Cookies.Append("IDToken", context.ProtocolMessage.IdToken, new CookieOptions()
            {
                Path = "/",
                HttpOnly = false,
                Secure = true
            });

And access the value on server side by :

 var idToken= Request.Cookies["IDToken"];

But you should concern the security problem . When used with the HttpOnly cookie flag(=true), are not accessible through JavaScript, and are immune to XSS. You can also set the Secure cookie flag to guarantee the cookie is only sent over HTTPS. However cookies are vulnerable to cross-site request forgery (CSRF) attacks . You can refer to this thread which provides detail discussion about that .

In short , you can store the ID token in cookie . But i would suggest to get the user claims from HttpContext.User object .

Nan Yu
  • 26,101
  • 9
  • 68
  • 148