-->

Azure Active Directory - MVC application best prac

2019-05-09 02:33发布

问题:

I've set up a simple MVC Application using Azure Active Directory(AAD).

I need to query the AAD Graph API in order to manage application roles and groups from my application.

In the Startup class, I received the AccessToken like that:

public void ConfigureAuth(IAppBuilder app)
{
    AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;

    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

    app.UseCookieAuthentication(new CookieAuthenticationOptions());

    app.UseOpenIdConnectAuthentication(
        new OpenIdConnectAuthenticationOptions
        {
            ClientId = Constants.ClientId,
            Authority = Constants.Authority,
            PostLogoutRedirectUri = Constants.PostLogoutRedirectUri,
            Notifications = new OpenIdConnectAuthenticationNotifications()
            {
                // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
                AuthorizationCodeReceived = (context) =>
                {
                    var code = context.Code;
                    var credential = new ClientCredential(Constants.ClientId, Constants.ClientSecret);
                    var signedInUserId =
                        context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
                    var authContext = new AuthenticationContext(Constants.Authority,
                        new TokenDbCache(signedInUserId));
                    var result = authContext.AcquireTokenByAuthorizationCode(
                        code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential,
                        Constants.GraphUrl);

                    var accessToken = result.AccessToken;                        
                    return Task.FromResult(0);
                }
            }
        });
}

To instantiate the ActiveDirectoryClient class, I need to pass the AccessToken :

var servicePointUri = new Uri("https://graph.windows.net");
var serviceRoot = new Uri(servicePointUri, tenantID);
var activeDirectoryClient = new ActiveDirectoryClient(serviceRoot,
        async () => await GetTokenForApplication());

I am wondering if storing the AccessToken as a claim is a good solution (line to add in the Startup class)?

context.AuthenticationTicket.Identity.AddClaim(new 
    Claim("OpenId_AccessToken", result.AccessToken));

EDIT Token is already stored..

Get it !!! Thank you George. So my Token has been stored in the database using the TokenDbCache class.

To get it again (in one of my controller) according to the sample:

public async Task<string> GetTokenForApplication()
{
    string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
    string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
    string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;

    // get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc)
    ClientCredential clientcred = new ClientCredential(clientId, appKey);
    // initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's database
    AuthenticationContext authenticationContext = new AuthenticationContext(aadInstance + tenantID, new TokenDbCache<ApplicationDbContext>(signedInUserID));
    AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenSilentAsync(graphResourceID, clientcred, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
    return authenticationResult.AccessToken;
}

What I don't know from the AuthenticationContext: If the token has already been requested, it is going to retrieve it from the TokenDbCache.

回答1:

When you are retrieving tokens through Adal it is caching it in NaiveCache object.

Code to retrieve token withing StartUp class:

  AuthenticationResult kdAPiresult = authContext.AcquireTokenByAuthorizationCode(code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, "Your API Resource ID");
                            string kdAccessToken = kdAPiresult.AccessToken;

In Azure Active Directory samples (https://github.com/AzureADSamples) this object utilized to retrieve token within app controllers. Youcan implement your own caching to retrieve it in a same manner.

In your controller code you can do following:

IOwinContext owinContext = HttpContext.GetOwinContext();
                string userObjectID = owinContext.Authentication.User.Claims.First(c => c.Type == Configuration.ClaimsObjectidentifier).Value;
                NaiveSessionCache cache = new NaiveSessionCache(userObjectID);
                AuthenticationContext authContext = new AuthenticationContext(Configuration.Authority, cache);
                TokenCacheItem kdAPITokenCache = authContext.TokenCache.ReadItems().Where(c => c.Resource == "You API Resource ID").FirstOrDefault();

You can store token in claims as well if your are obtaining tokens not though AuthenticationContext (3d party apis)