0

Я стараюсь понять, как работают 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 все еще думает, что я вошел в систему, я просто не получаю токены, установленные должным образом в моем приложении.

ответ

2

Поскольку поток Аутентифицировать немного сложный, я пытаюсь проиллюстрировать с помощью рисунка ниже: enter image description here

Сначала Перенаправление URL необходимо зарегистрироваться провайдеру идентификации, так что сервер будет соответствовать RedirectURL в запросе для обеспечения того, чтобы ответ перенаправлялся, как ожидалось, вместо перенаправления на сайт Phishing (соображения безопасности).

Как показано на рисунке, для использования Azure AD в качестве поставщика внешней идентификации для IdentityServer3 нам необходимо зарегистрировать приложения на Azure AD. Однако, поскольку приложение используется для связи с Identity Server, регистр URL-адреса перенаправления на портале Azure должен перенаправляться на IdentityServer3 вместо URL-адреса приложения.

Например, URL-адрес моего сервера идентификации 3: https://localhost:44333, затем я использую следующий код для добавления дополнительных поставщиков удостоверений. И этот URL является перенаправление URL на Лазурном портал:

public static void ConfigureAdditionalIdentityProviders(IAppBuilder app, string signInAsType) 
{ 
     app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions 
     { 
      AuthenticationType = "aad", 
      Caption = "Azure AD", 
      SignInAsAuthenticationType = signInAsType, 

      Authority = "https://login.microsoftonline.com/04e14a2c-0e9b-42f8-8b22-3c4a2f1d8800", 
      ClientId = "eca61fd9-f491-4f03-a622-90837bbc1711", 
      RedirectUri = "https://localhost:44333/core/aadcb", 
     }); 
} 

И URL моего приложения является http://localhost:1409/, который зарегистрироваться на IdentyServer3 и ниже кода является использование веб-приложение Owin OpenId Connect, чтобы добавить IdentyServer3 как поставщик идентификационных данных:

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions 
{ 
     AuthenticationType = "oidc", 
     SignInAsAuthenticationType = "cookies", 
     Authority = "https://localhost:44333", 
     ClientId = "mvc", 
     RedirectUri = "http://localhost:1409/", 
     ResponseType = "id_token", 
     Scope = "openid profile email" 
}); 
+0

Я использовал вашу иллюстрацию и код для изменения/проверки кода, который я использую. К сожалению, такая же проблема происходит ... Как только я аутентифицируюсь против Azure AD, я перенаправлен на IdentityServer3, а не в мое приложение по своему желанию. Я также подтвердил, что клиент в IdentityServer3 имеет правильные RedirectUris и PostLogoutRedirectUris. Я просто не вернусь к своей заявке. – rcastagna

+0

Поскольку тест выше работает для меня хорошо, я предлагаю вам отслеживать HTTP-запрос/перенаправление/ответ через ** Fiddler **, чтобы увидеть, есть ли сообщение об ошибке, когда запрос был перенаправлен на Identity Server3. –