Reputation: 289
I am trying to retrieve the access token so I can store it, and pass it to an ExchangeService later on. Startup.Auth looks like this:
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = authority,
UseTokenLifetime = false,
/*
* Skipping the Home Realm Discovery Page in Azure AD
* http://www.cloudidentity.com/blog/2014/11/17/skipping-the-home-realm-discovery-page-in-azure-ad/
*/
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = OpenIdConnectNotification.RedirectToIdentityProvider,
MessageReceived = OpenIdConnectNotification.MessageReceived,
SecurityTokenReceived = OpenIdConnectNotification.SecurityTokenReceived,
SecurityTokenValidated = OpenIdConnectNotification.SecurityTokenValidated,
AuthorizationCodeReceived = OpenIdConnectNotification.AuthorizationCodeReceived,
AuthenticationFailed = OpenIdConnectNotification.AuthenticationFailed
},
});
then in SecurityTokenValidated I did this:
public static async Task<Task> SecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
{
string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
var authContext = new AuthenticationContext(aadInstance + "/oauth2/token", false);
var authResult =await authContext.AcquireTokenByAuthorizationCodeAsync(context.ProtocolMessage.Code,
new Uri(aadInstance), new ClientAssertion(clientId, "5a95f1c6be7bf3c61f6392ec84ddd044acef61d9"));
var accessToken = authResult.Result.AccessToken;
context.AuthenticationTicket.Identity.AddClaim(new Claim("access_token", accessToken));
return Task.FromResult(0);
}
I don't get any errors but the application hangs on this line:
var accessToken = authResult.Result.AccessToken;
The ClientAssertion was constructed using a thumbprint of a SSL certificate that I have installed in IIS, not sure if the certificate is the wrong type...
UPDATE: I updated the SecurityTokenValidated to reflect Saca's comment but I get an "AADSTS50027: Invalid JWT token. Token format not valid" error this way. I also tried this code:
string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
var authContext = new AuthenticationContext(aadInstance, false);
var cert = new X509Certificate2("...", "...");
var cacert = new ClientAssertionCertificate(clientId, cert);
var authResult = await authContext.AcquireTokenByAuthorizationCodeAsync(context.ProtocolMessage.Code, new Uri(aadInstance), cacert);
var accessToken = authResult.AccessToken;
context.AuthenticationTicket.Identity.AddClaim(new Claim("access_token", accessToken));
return Task.FromResult(0);
but this way I get "AADSTS70002: Error validating credentials. AADSTS50012: Client assertion contains an invalid signature."
Upvotes: 2
Views: 7977
Reputation: 289
I managed to get the access token tike this:
public static async Task<Task> SecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
{
string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
string clientSecret = ConfigurationManager.AppSettings["ida:ClientSecret"];
string source = ConfigurationManager.AppSettings["ExchangeOnlineId"];
var authContext = new AuthenticationContext(aadInstance, false);
var credentials = new ClientCredential(clientId, clientSecret);
var appRedirectUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + "/";
var authResult = await authContext.AcquireTokenByAuthorizationCodeAsync(context.ProtocolMessage.Code, new Uri(appRedirectUrl), credentials, source);
var accessToken = authResult.AccessToken;
var applicationUserIdentity = new ClaimsIdentity(context.OwinContext.Authentication.User.Identity);
applicationUserIdentity.AddClaim(new Claim("AccessToken", accessToken));
context.OwinContext.Authentication.User.AddIdentity(applicationUserIdentity);
return Task.FromResult(0);
}
Initially I wanted to use a ClientAssertion so I don't have to expose the client Secret but it's too much work managing the certificate...
Upvotes: 2
Reputation: 10672
The application hangs because your blocking on the result of an async taskby accessing the .Result of authResult.
You should change that to:
public static async Task SecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
{
string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
var authContext = new AuthenticationContext(aadInstance + "/oauth2/token", false);
var authResult = await authContext.AcquireTokenByAuthorizationCodeAsync(context.ProtocolMessage.Code,
new Uri(aadInstance), new ClientAssertion(clientId, "5a95f1c6be7bf3c61f6392ec84ddd044acef61d9"));
var accessToken = authResult.AccessToken;
context.AuthenticationTicket.Identity.AddClaim(new Claim("access_token", accessToken));
}
Upvotes: 3