2017-12-27 78 views
0

제 웹 사이트의 경우 OWIN OpenId를 사용하여 타사 인증 공급자와 통합하여 방문자가 로그인/로그인/로그 아웃 할 수 있도록하고 있습니다. "Second"Double OWIN 인증이 함께 작동하지 않습니다.

또한 이러한 변경 사항을 프로덕션 환경에 적용하기 전에 모든 코드 변경 사항을 테스트 한 응용 프로그램에 대한 테스트 환경이 있습니다. 필자는 OWIN OpenId와 "First"를 사용하여 테스트 환경을 다른 타사 인증 공급자와의 공용 액세스로부터 보호합니다. 인증 된 방문자 만 테스트 환경 웹 사이트를 방문 할 수 있습니다.

이제 문제는이 두 가지가 모두 독립적으로 작동하지만 문제가 있다는 것입니다. 내가 성취하고자하는 것은 First로 인증하여 테스트 환경에 액세스 한 다음 다시 방문한 방문자로 등록 된 방문자를 위해 고안된 콘텐츠를 Second로 인증하도록 인증하는 것입니다.

여기에 내가 뭘 내용은 다음과 같습니다

두 authnetication 공급자는 쿠키 인증으로 작동하지만 나는 간격을 유지하기 위해 그들에게 다른 AuthenticationType했다. 먼저 활성화

if (IsEnabled("First")) 
    app.SetDefaultSignInAsAuthenticationType("First"); 
else 
    app.SetDefaultSignInAsAuthenticationType("Second"); 

// Configure First. 
if (IsEnabled("First")) { 
    app.UseCookieAuthentication(First.CookieAuthenticationOptions); // AuthenticationType is set to "First" in these options. 
    app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions 
    { 
     ClientId = First.AADClientId, 
     Authority = First.Authority, 
     Notifications = new OpenIdConnectAuthenticationNotifications 
     { 
      AuthenticationFailed = context => { ... }, 
      RedirectToIdentityProvider = context => { ... } 
     }, 
     AuthenticationType = "First" 
    }); 
    app.Map($"{First.Path}/login", config => 
    { 
     config.Run(context => 
     { 
      context.Authentication.Challenge(new AuthenticationProperties 
       { RedirectUri = First.ReturnUrl, IsPersistent = true }, 
       "First" 
      ); 

      context.Response.StatusCode = 401; 
      return context.Response.WriteAsync(string.Empty); 
     }); 
    }); 
} 

// Configure Second. 
app.UseCookieAuthentication(Second.CookieAuthenticationOptions); // AuthenticationType is set to "Second" in these options. 
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions 
{ 
    UseTokenLifetime = false, 
    Notifications = new OpenIdConnectAuthenticationNotifications 
    { 
     AuthenticationFailed = x => ..., 
     RedirectToIdentityProvider = x => 
     { 
      var mgr = x.Options.ConfigurationManager as PolicyConfigurationManager; 
      if (x.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest) 
      { 
       var config = await mgr.GetConfigurationByPolicyAsync(CancellationToken.None, 
       x.OwinContext.Authentication.AuthenticationResponseRevoke.Properties.Dictionary["PolicyId"]); 
       x.ProtocolMessage.IssuerAddress = config.EndSessionEndpoint; 
      } 
      else 
      { 
       var config = await mgr.GetConfigurationByPolicyAsync(CancellationToken.None, 
       x.OwinContext.Authentication.AuthenticationResponseChallenge.Properties.Dictionary["PolicyId"]); 
       x.ProtocolMessage.IssuerAddress = config.AuthorizationEndpoint; 
      } 

      var redirectUri = Second.ReturnPath; 
      x.ProtocolMessage.RedirectUri = redirectUri; 
      x.ProtocolMessage.PostLogoutRedirectUri = redirectUri; 
     }, 
     SecurityTokenValidated = x => ... 
    }, 
    Scope = "openid", 
    ResponseType = "id_token", 
    ReturnUri = Second.ReturnUri, 
    ClientId = Second.ClientId, 
    ConfigurationManager = GetConfigurationManager() 
    AuthenticationType = configuration.AuthenticationType 
}); 
app.Map(Second.LoginPath, config => 
{ 
    // Trigger unauthorized so that active authentication will redirect to active directory. 
    config.Run(context => 
    { 
     // Set policy in context to mitigate null ref exception in Startup.Auth OnRedirectToIdentityProvider 
     context.Authentication.Challenge(
      new AuthenticationProperties(new Dictionary<string, string> 
      { 
       {"PolicyId", Second.LoginPolicyId} 
      }) 
      { 
       IsPersistent = true, 
       RedirectUri = returnUrl 
      }, "Second"); 

     context.Response.StatusCode = 401; 

     // Middleware will redirect us instead of using this output. 
     return context.Response.WriteAsync(string.Empty); 
    }); 
}); 
app.Map(Second.ReturnPath, config => 
{ 
    config.Use((context, next) => 
    { 
     // In case of login, we will never get here because we will get redirected by middleware. 
     context.Response.Redirect("/"); 

     return Task.FromResult(0); 
    }); 
}); 

,이 날 이후의 요청에

var identity = HttpContext.Current.GetOwinContext.Authentication.AuthenticateAsync("Second").Result?.Identity; 

을하고 ClaimsIdentity을 할 수 있습니다. 그러나 First가 활성화되면 어떤 이유로 위의 결과가 null입니다.

나는 First와 Second를 모두 활성화하고 DefaultSignInAsAuthenticationType을 "Second"로 설정하면 처음에는 더 이상 작동하지 않는 것으로 나타났습니다. First와 Second를 모두 활성화하고 First 인증 쿠키를 사용하여 사이트를 탐색하면 모든 것이 올바르게 작동합니다.

반환 방법은 인증 쿠키를 설정하는 어딘가에서 AuthenticationType에 대한 참조가 필요하다고 생각하지만 그 위치를 알지 못합니다.

무엇이 누락 되었습니까?

답변

1

비결은 두 번째 구성 할 때과 같이, TokenValidationParameters에 AuthenticationType을 추가하는 것입니다

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions 
{ 
    UseTokenLifetime = false, 
    Notifications = new OpenIdConnectAuthenticationNotifications 
    { 
     AuthenticationFailed = x => ..., 
     RedirectToIdentityProvider = x => 
     { 
      var mgr = x.Options.ConfigurationManager as PolicyConfigurationManager; 
      if (x.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest) 
      { 
       var config = await mgr.GetConfigurationByPolicyAsync(CancellationToken.None, 
       x.OwinContext.Authentication.AuthenticationResponseRevoke.Properties.Dictionary["PolicyId"]); 
       x.ProtocolMessage.IssuerAddress = config.EndSessionEndpoint; 
      } 
      else 
      { 
       var config = await mgr.GetConfigurationByPolicyAsync(CancellationToken.None, 
       x.OwinContext.Authentication.AuthenticationResponseChallenge.Properties.Dictionary["PolicyId"]); 
       x.ProtocolMessage.IssuerAddress = config.AuthorizationEndpoint; 
      } 

      var redirectUri = Second.ReturnPath; 
      x.ProtocolMessage.RedirectUri = redirectUri; 
      x.ProtocolMessage.PostLogoutRedirectUri = redirectUri; 
     }, 
     SecurityTokenValidated = x => ... 
    }, 
    Scope = "openid", 
    ResponseType = "id_token", 
    ReturnUri = Second.ReturnUri, 
    ClientId = Second.ClientId, 
    ConfigurationManager = GetConfigurationManager(), 
    AuthenticationType = configuration.AuthenticationType, 
    // ADD THIS TO MAKE IT WORK: 
    TokenValidationParameters = new TokenValidationParameters 
     { 
      AuthenticationType = configuration.AuthenticationType 
     } 
});