Я стараюсь понять, как работают IdentityServer3, AzureAD и частная база данных. Самая большая проблема заключается в том, как обрабатываются URI Redirect.IdentityServer3 + AzureAD и RedirectUri Confusion
Мой сценарий У меня есть отдельный IdentityServer3. Задача состоит в том, чтобы аутентифицировать пользователей либо с AzureAD, либо с частной БД. В файле Startup.cs на сервере ID3, у меня есть следующий OpenID Connect код:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.Map("/identity", s3App =>
{
s3App.UseIdentityServer(new IdentityServerOptions
{
SiteName = "3S",
SigningCertificate = Certificate.Load(),
Factory = new IdentityServerServiceFactory()
.UseInMemoryUsers(InMemoryUsers.Get())
.UseInMemoryClients(InMemoryClients.Get())
.UseInMemoryScopes(InMemoryScopes.Get()),
AuthenticationOptions = new AuthenticationOptions
{
EnablePostSignOutAutoRedirect = true,
EnableSignOutPrompt = false,
IdentityProviders = ConfigureAdditionalIdentityProviders
}
});
});
}
public static void ConfigureAdditionalIdentityProviders(IAppBuilder app, string signInAsType)
{
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
AuthenticationType = "AzureAd",
Caption = "Login",
ClientId = "4613ed32-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // GUID of registered application on Azure
Authority = "https://login.microsoftonline.com/our-tenant-id/",
PostLogoutRedirectUri = "https://localhost:44348/identity",
RedirectUri = "https://localhost:44348/identity",
Scope = "openid email profile",
ResponseType = "id_token",
AuthenticationMode = AuthenticationMode.Passive,
SignInAsAuthenticationType = signInAsType,
TokenValidationParameters = new TokenValidationParameters
{
AuthenticationType = Constants.ExternalAuthenticationType,
ValidateIssuer = false
}
});
}
Я не понимаю, почему сервер ID3 будет необходимо иметь либо RedirectUri или PostLogoutRedirectUri ... не следует, что быть «пройденным» из приложения, запрашивающего аутентификацию? В конце концов, мы хотим вернуться к приложению, а не к ID3-серверу. Конечно, я не думаю, что это то, что вызывает мою проблему, но было бы неплохо понять, почему они здесь.
Я скажу, что я получил «близко» к этой работе.
Когда мое приложение, требующее аутентификации, запрашивает аутентификацию против AzureAD, я перенаправляюсь на экран входа в учетную запись Microsoft, чтобы ввести свое имя пользователя/пароль для моей учетной записи. Я отправляю свои учетные данные, а затем перенаправляюсь обратно на сервер ID3 или мое приложение, в зависимости от того, какой RedirectUri использовался в вышеуказанном коде.
Ради аргумента, допустим, я использую свое приложение для RedirectUri. Я буду отправлен обратно в приложение, но не на страницу, изначально вызвавшую вызов аутентификации, и если я нажму на страницу, требующую проверки подлинности, я отправлю обратно на сервер AzureAD, чтобы снова войти в систему, только на этот раз AzureAD признает, что я уже вошел в систему.
К сожалению, при перенаправлении с AzureAD уведомление/SecurityTokenValidated уведомление не подтверждается/устанавливается.
Вот код найден в прикладном Startup.cs:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
Authority = "https://localhost:44348/identity",
ClientId = "3af8e3ba-5a04-4acc-8c51-1d30f8587ced", // Local ClientID registered as part of the IdentityServer3 InMemoryClients
Scope = "openid profile roles",
RedirectUri = "http://localhost:52702/",
PostLogoutRedirectUri = "http://localhost:52702/",
ResponseType = "id_token",
SignInAsAuthenticationType = "Cookies",
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = n =>
{
var id = n.AuthenticationTicket.Identity;
var givenName = id.FindFirst(Constants.ClaimTypes.GivenName);
var familyName = id.FindFirst(Constants.ClaimTypes.FamilyName);
var sub = id.FindFirst(Constants.ClaimTypes.Subject);
var roles = id.FindAll(Constants.ClaimTypes.Role);
var nid = new ClaimsIdentity(
id.AuthenticationType,
Constants.ClaimTypes.GivenName,
Constants.ClaimTypes.Role
);
nid.AddClaim(givenName);
nid.AddClaim(familyName);
nid.AddClaim(sub);
nid.AddClaims(roles);
nid.AddClaim(new Claim("application_specific", "Some data goes here. Not sure what, though."));
nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
n.AuthenticationTicket = new AuthenticationTicket(nid, n.AuthenticationTicket.Properties);
return Task.FromResult(0);
},
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType != OpenIdConnectRequestType.LogoutRequest)
return Task.FromResult(0);
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenHint != null)
{
n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
}
return Task.FromResult(0);
},
AuthenticationFailed = (context) =>
{
context.HandleResponse();
context.Response.Redirect("/Error/message=" + context.Exception.Message);
//Debug.WriteLine("*** AuthenticationFailed");
return Task.FromResult(0);
},
}
});
AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject;
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
}
}
Вы заметите, что OpenIdConnectAuthenticationOptions также содержат RedirectUri и PostLogoutRedirectUri, которые указывают на применение, но те, похоже, не имеет значения ,
Конечно, все работает отлично, когда я вхожу в систему с помощью «куки» - я вижу все мои претензии к пользователю. И, потратив некоторое время на телефон с Microsoft, они предложили решение за пределами ID3, которое работало, но не так, как нам нужно. У нас будет несколько приложений, прошедших аутентификацию против нашего ID3, поэтому нам нужно будет содержать и контролировать поток внутри.
Мне очень нужна помощь, пытаясь выяснить эту проблему в последней миле. Я знаю, что я рядом, я так долго смотрел на это так, что я, вероятно, смотрю прямо на мою ошибку и не вижу ее.
10/22/2016 Редактировать
Дальнейшее тестирование и позволяет Serilog выявили проблему с RedirectUri
и PostLogoutRedirectUri
привело к моему добавление /identity
к концу URI, который соответствует значению, установленному в app.Map. Это решило проблему моего возвращения на «пустую» страницу IdentityServer3, теперь я вернулся на экран входа IdentityServer3. Azure AD все еще думает, что я вошел в систему, я просто не получаю токены, установленные должным образом в моем приложении.
Я использовал вашу иллюстрацию и код для изменения/проверки кода, который я использую. К сожалению, такая же проблема происходит ... Как только я аутентифицируюсь против Azure AD, я перенаправлен на IdentityServer3, а не в мое приложение по своему желанию. Я также подтвердил, что клиент в IdentityServer3 имеет правильные RedirectUris и PostLogoutRedirectUris. Я просто не вернусь к своей заявке. – rcastagna
Поскольку тест выше работает для меня хорошо, я предлагаю вам отслеживать HTTP-запрос/перенаправление/ответ через ** Fiddler **, чтобы увидеть, есть ли сообщение об ошибке, когда запрос был перенаправлен на Identity Server3. –