I am working on ASP.Net MVC 4.7.2 (classics). Using Azure AD Authenticaiton (Microsoft Identity platform) for authentication and for Web Api authorization.
When using code flow to get the api resource I wan to store the token and get it silently when needed. I got the code from MSAL team from Git. But code doesn't work. Whenever I acquire the code silently the I get the error. When I debugged the issue I found that IAccounet is return null see the following line that returns null.
IAccount account =
_MsalAppBuilder.GetAccountAsync(ClaimsPrincipal.Current.GetAccountId()).Result;
Since account is null therefore the next line of code throws error. Therefore nt aoo us unable to work
AuthenticationResult result = app.AcquireTokenSilent(scopes, account).ExecuteAsync().Result;
As I debugged the issue, I could not find any reason why it is happening and even after extensive search. However what I found that in the Startup class, the method AcquireAccessToken never hit, thus the token does not save.
Can something help understand it please.
MSAL class:
public static class MsalAppBuilder
{
public static string GetAccountId(this ClaimsPrincipal claimsPrincipal)
{
string oid = claimsPrincipal.GetObjectId();
string tid = claimsPrincipal.GetTenantId();
return $"{oid}.{tid}";
}
private static IConfidentialClientApplication clientapp;
public static IConfidentialClientApplication BuildConfidentialClientApplication()
{
if (clientapp == null)
{
clientapp = ConfidentialClientApplicationBuilder.Create(Globals.clientId)
.WithClientSecret(Globals.clientSecret)
.WithRedirectUri(Globals.redirectUri)
.WithAuthority(new Uri(Globals.authority))
.Build();
// In-memory distributed token cache
clientapp.AddDistributedTokenCache(services =>
{
services.AddDistributedMemoryCache();
services.Configure<MsalDistributedTokenCacheAdapterOptions>(o =>
{
o.Encrypt = true;
});
});
}
return clientapp;
}
//this was commented already
/*
// Could also use other forms of cache, like Redis
// See https://aka.ms/ms-id-web/token-cache-serialization
clientapp.AddDistributedTokenCache(services =>
{
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost";
options.InstanceName = "SampleInstance";
});
});
*/
public static async Task RemoveAccount()
{
BuildConfidentialClientApplication();
var userAccount = await clientapp.GetAccountAsync(ClaimsPrincipal.Current.GetAccountId());
if (userAccount != null)
{
await clientapp.RemoveAsync(userAccount);
}
}
startup class:
public void Configuration(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
//app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
// CookieManager = new SystemWebCookieManager()
AuthenticationType = "Cookies",
CookieManager = new Microsoft.Owin.Host.SystemWeb.SystemWebChunkingCookieManager()
});
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
// Sets the ClientId, authority, RedirectUri as obtained from web.config
ClientId = clientId,
Authority = authority,
RedirectUri = redirectUri,
// PostLogoutRedirectUri is the page that users will be redirected to after sign-out. In this case, it is using the home page
PostLogoutRedirectUri = redirectUri,
Scope = OpenIdConnectScope.OpenIdProfile,
// ResponseType is set to request the code id_token - which contains basic information about the signed-in user
//ResponseType = OpenIdConnectResponseType.CodeIdToken,
ResponseType = OpenIdConnectResponseType.CodeIdToken,
// OpenIdConnectAuthenticationNotifications configures OWIN to send notification of failed authentications to OnAuthenticationFailed method
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = OnAuthorizationCodeReceived,
AuthenticationFailed = OnAuthenticationFailed
}
}
);
}
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
{
var scopes = Globals.scopeTravelAuthApi;
IConfidentialClientApplication clientApp = MsalAppBuilder.BuildConfidentialClientApplication();
AuthenticationResult result = await clientApp.AcquireTokenByAuthorizationCode(new[] { scopes}, context.Code).ExecuteAsync().ConfigureAwait(true);
context.HandleCodeRedemption(result.AccessToken, result.IdToken);
}
/// <summary>
/// Handle failed authentication requests by redirecting the user to the home page with an error in the query string
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
{
context.HandleResponse();
context.Response.Redirect("/?errormessage=" + context.Exception.Message);
return Task.FromResult(0);
}
}
By the way, I have checked all the settings related to Azure AD they ar correct. In the same app I am accessing Graph API which is working fine only issue is getting the access token silently.