Фон
Итак, у нас есть служба приложений, которая аутентифицируется из Azure AD в другом клиенте с использованием OpenIdConnect.
Вход в систему работает на экземпляре IIS разработчика, а также на нашем сервисе тестового приложения. Мы увидели проблему в тесте, и она исчезла и не возвращалась в течение всей фазы тестирования проекта.
Теперь мы развернуты в производство и снова видим проблему.
Выпуск
То, что мы видим, это то, что в течение некоторого времени все будет работать нормально, а затем через несколько часов проблема снова возникнет.
У нас есть обходное решение для восстановления службы, то есть включение и отключение проверки подлинности службы приложения на панели управления Azure. Также работает обратное - отключить, а затем включить восстановить сервис.
Код
public void ConfigureAuth(IAppBuilder app)
{
//Azure AD Configuration
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
//sets client ID, authority, and RedirectUri as obtained from web config
ClientId = clientId,
ClientSecret = appKey,
Authority = authority,
RedirectUri = redirectUrl,
CallbackPath = new PathString("/"), //use this line for production and test
//page that users are redirected to on logout
PostLogoutRedirectUri = redirectUrl,
//scope - the claims that the app will make
Scope = OpenIdConnectScope.OpenIdProfile,
ResponseType = OpenIdConnectResponseType.CodeIdToken,
//setup multi-tennant support here, or set ValidateIssuer = true to config for single tennancy
TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
//SaveSigninToken = true
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = OnAuthenticationFailed,
AuthorizationCodeReceived = OnAuthorizationCodeReceived,
}
}
);
}
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
{
var code = context.Code;
ClientCredential cred = new ClientCredential(clientId, appKey);
string userObjectId = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
//this token cache is stateful, we're going to populate it here, but we'll store it elsewhere in-case the user ends up accessing a different instance
AuthenticationContext authContext = new AuthenticationContext(authority, new NaiveSessionCache(userObjectId));
// If you create the redirectUri this way, it will contain a trailing slash.
// Make sure you've registered the same exact Uri in the Azure Portal (including the slash).
Uri uri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path));
AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(code, uri, cred, "https://graph.windows.net");
//populate the persistent token cache
testdb2Entities5 db = new testdb2Entities5();
PersistentTokenCache tc = await db.PersistentTokenCaches.FindAsync(userObjectId);
//if null, populate a new item
if (tc == null)
{
tc = new PersistentTokenCache();
tc.object_id = userObjectId;
tc.token = code;
db.PersistentTokenCaches.Add(tc);
await db.SaveChangesAsync();
}
else
{
tc.token = code;
await db.SaveChangesAsync();
}
}
//authentication failed notifications
private Task OnAuthenticationFailed(AuthenticationFailedNotification<Microsoft.IdentityModel.Protocols
.OpenIdConnect.OpenIdConnectMessage,
OpenIdConnectAuthenticationOptions> context)
{
context.HandleResponse();
context.Response.Redirect("/?errormessage=" + context.Exception.Message);
return Task.FromResult(0);
}
Вопрос
Итак, основываясь на том, что делает включение и отключение аутентификации службы приложений, оно явно исправляет ситуацию временно. Так что я думаю, что это проблема, связанная с cookie - поскольку это было бы единственной вещью, передающей состояние между сеансами. Что на земле может быть проблема здесь? И какие шаги мне нужно предпринять, чтобы диагностировать и решить проблему?