2017-11-01 6 views
0

현재 Forms 인증 (또는 FormsAuthenticationTicket 쿠키를 설정하는 LDAP)을 사용하는 웹 양식 응용 프로그램이 있습니다. 이 프로젝트에 SSO를 추가해야하며 현재 OpenID/Azure AD를 사용하여 인증하고 있습니다. 다음 Startup.cs가 구성되었습니다. (결코 타격을 받고있는 것 같다 없지만. - 내가 인증을 필요로하는 페이지를 탐색 할 때 인증 프로세스가 킥오프 원인이되어야 다른 뭔가를)기존 Web Forms 응용 프로그램에 SSO OpenId/Azure AD 인증 추가

 public void Configuration(IAppBuilder app) 
    { 
     string appId = "<id here>"; 
     string aadInstance = "https://login.microsoftonline.com/{0}"; 
     string tenant = "<tenant here>"; 
     string postLogoutRedirectUri = "https://localhost:21770/"; 
     string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant); 

app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); 
      app.UseCookieAuthentication(new CookieAuthenticationOptions()); 

      app.UseOpenIdConnectAuthentication(
      new OpenIdConnectAuthenticationOptions 
      { 
       ClientId = appId, 
       Authority = authority, 
       PostLogoutRedirectUri = postLogoutRedirectUri, 
       Notifications = new OpenIdConnectAuthenticationNotifications 
       { 
        SecurityTokenReceived = context => 
        { 
         System.Diagnostics.Debug.WriteLine("SecurityTokenReceived"); 
         return Task.FromResult(0); 
        }, 

        SecurityTokenValidated = async n => 
        { 
         var claims_to_exclude = new[] 
         { 
          "aud", "iss", "nbf", "exp", "nonce", "iat", "at_hash" 
         }; 

         var claims_to_keep = 
          n.AuthenticationTicket.Identity.Claims 
          .Where(x => false == claims_to_exclude.Contains(x.Type)).ToList(); 
         claims_to_keep.Add(new Claim("id_token", n.ProtocolMessage.IdToken)); 

         if (n.ProtocolMessage.AccessToken != null) 
         { 
          claims_to_keep.Add(new Claim("access_token", n.ProtocolMessage.AccessToken)); 

          //var userInfoClient = new UserInfoClient(new Uri("https://localhost:44333/core/connect/userinfo"), n.ProtocolMessage.AccessToken); 
          //var userInfoResponse = await userInfoClient.GetAsync(); 
          //var userInfoClaims = userInfoResponse.Claims 
          // .Where(x => x.Item1 != "sub") // filter sub since we're already getting it from id_token 
          // .Select(x => new Claim(x.Item1, x.Item2)); 
          //claims_to_keep.AddRange(userInfoClaims); 
         } 

         var ci = new ClaimsIdentity(
          n.AuthenticationTicket.Identity.AuthenticationType, 
          "name", "role"); 
         ci.AddClaims(claims_to_keep); 

         n.AuthenticationTicket = new AuthenticationTicket(
          ci, n.AuthenticationTicket.Properties 
         ); 
        }, 
        MessageReceived = context => 
        { 
         System.Diagnostics.Debug.WriteLine("MessageReceived"); 
         return Task.FromResult(0); 
        }, 
        AuthorizationCodeReceived = context => 
        { 
         System.Diagnostics.Debug.WriteLine("AuthorizationCodeReceived"); 
         return Task.FromResult(0); 
        }, 
        AuthenticationFailed = context => 
        { 
         System.Diagnostics.Debug.WriteLine("AuthenticationFailed"); 
         context.HandleResponse(); 
         context.Response.Write( context.Exception.Message); 
         return Task.FromResult(0); 
        } 
        , 
        RedirectToIdentityProvider = (context) => 
        { 
         System.Diagnostics.Debug.WriteLine("RedirectToIdentityProvider"); 
         //string currentUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.Path; 
         //context.ProtocolMessage.RedirectUri = currentUrl; 

         return Task.FromResult(0); 
        } 
       } 
      }); 
      app.UseStageMarker(PipelineStage.Authenticate); 

     } 

내 마스터 페이지로드 이벤트에서이 놓여있다

내가이 청구 정보로 로그인하고 내 이메일을 볼 수 있습니다,하지만 난 다음에 무엇을 확실하지 않다 - 나는 SecurityTokenValidated 및 AuthorizationCodeReceived 기능을 타격하고 있기 때문에
if (!Request.IsAuthenticated) 
       { 
        HttpContext.Current.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/Login.aspx" }, OpenIdConnectAuthenticationDefaults.AuthenticationType); 
       } 

내 푸른 설정은 모든 정확합니다. 나는 끝없는 인증 요청 루프를 가지고 있습니다. 나는 내가 폼 인증으로받은 클레임 정보를 번역하지 않았기 때문에 이것을 가정하고 있습니까? AuthorizationCodeReceived에서 응답에 더미 인증 티켓을 추가하려고 시도했지만 아무 것도 변경하지 못했습니다. 여전히 반복 인증 요청을 받고 있습니다.

FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, "<UserName>", DateTime.Now, DateTime.Now.AddMinutes(60), true,""); 
String encryptedTicket = FormsAuthentication.Encrypt(authTicket); 
context.Response.Cookies.Append(FormsAuthentication.FormsCookieName, encryptedTicket); 
+0

"인증 요청이 끊어지지 않는 루프"문제가 있습니까? 메모리에서, 나는 명백한 로그온 코드를 사용할 필요가 없다고 확신한다 - 그것은 startup.cs에 올바른 것을 추가함으로써 모두 처리되었다. 아마도 가장 좋은 해결책은 OpenID를 사용하여 새로운 프로젝트를 만들고 자동 생성되는 코드를 살펴 보는 것입니다. –

+0

문제는 두 가지입니다. - 결코 끝나지 않는 루프와 내가 알고있는 사용자에게 광고에 로그인 한 친구, 내 앱 등에서 어떤 역할을 받았는지 (사실은 직설적 인 이메일이된다고 가정 함) 주소 비교). 나는 새로운 프로젝트를 볼 것이다. –

답변

0

이것은 명확한 대답은 아니지만 코멘트 너무 큽니다.

"Organizational Accounts"(즉, O365 전자 메일 로그인)를 사용하고 있는데 두 가지 큰 문제 (두 가지 모두 해결됨)가있었습니다. 앞뒤로 두 페이지 사이 (무한 리디렉션 루프로 갈 것입니다 거기에 로그인 할 때

간헐적으로

첫 번째 문제는,이 문제는 항상 발생하지 않았다 - 절반 밖에 시간 테스트 및 로깅에 후 및 밖으로).

길게 입력하면 "query string too long"이라고 표시됩니다. 쿠키와 물건에 대한 설명은 오래되었지만 문제를 해결하는 데 어려움이있었습니다. 결국 그것은 HTTP 대신 https를 강제로 해결했습니다.

매번 그런 것처럼 보이는 것이 문제라고 생각하지 않습니다. 아마도이

New Asp.Net MVC5 project produces an infinite loop to login page

한 대답을 읽고 말한다 :

보호 된 웹 API 등 ~/계정으로 인증 페이지에서 ( 인증이 필요한 웹 API)를 호출하지 마십시오/로그인 (그 자체로는이 작업을 수행하지 않습니다.) 당신이한다면 서버 측에 무한 리다이렉트 루프 인 을 입력 할 것입니다.

두 번째 문제

그래서 다음 일이었다 : 우리의 기존 인증 시스템은 우리의 데이터베이스에 고전 로그인/비밀번호 테이블에 앉아 있던 (> 암호화되지 않은 암호 필드 : |). 그래서 로그인 이메일을 가져와이 표에 정의 된 역할과 일치시켜야했습니다.

  1. 이동이 초기 로그인
  2. 을 따라 한 번에 데이터베이스에서 사용자의 역할을 데리러 :

    Capturing login event so I can cache other user information

    이 대답은 내가 할 수있는 것을 의미 : 내 질문에 대답 사람 덕분에 그것을했다 기존 기본 C# 보안 개체에이 역할 저장

  3. 모든 방법 : 사용자 지정 코드없이 내 컨트롤러 메서드에서 네이티브 인증 주석을 사용하십시오.

나는 당신이 무엇을하고 있다고 생각하지만 질문은 실제로 그렇습니다. 어떻게 지내십니까 현재 역할을 저장하고 있습니까? 데이터베이스 테이블에서? Active Directory에 있습니까? Azure 액티브 디렉토리에?

+0

사용자/역할은 현재 응용 프로그램 데이터베이스의 aspnet_Users/aspnet_UsersInRoles/aspnet_Roles 테이블에 저장됩니다. 그런 다음 응용 프로그램은 System.Web.Security.Membership.GetUser() 및 System.Web.Security.Roles.IsUserInRole ("")을 사용하여 다양한 페이지에서 작업을 수행합니다. 만약 내가 그것을 도울 수있는, 그래서 인증 된 사용자와 내 애플 리케이션을 알게 사용자를 기쁘게하려고 노력 중 하나를 만지고 싶지 않아 :) –

+0

그래서 내가 제대로 당신이 양식 보안을 사용하여 기존의 ASP.Net 애플 리케이션을 가지고 이해 (그 테이블이 무엇인지) 조직의 보안 (O365 로그인)을 사용하도록 변경하려고하지만 이미 사용자 데이터베이스에있는 기존의 모든 역할 정의를 다시 사용하려고합니다. 또한 기존 코드를 변경하지 않으려 고합니다. –

+0

이것은 나에게 모두 새로운 것이므로 나는 그렇다고 생각한다. 장기적으로 나는 다른 아이덴터티 공급자에 대한 지원을 추가해야 할 것으로 예상됩니다. 푸른 디렉토리 인증은 시스템에 추가하려는 첫 번째 옵션 일뿐입니다. 그리고 Forms 보안은 결코 내 앱에서 완전히 사라지지 않을 것입니다. Azure 또는 다른 소스에 대한 로그인이없는 시스템 사용자가 항상있을 것입니다. 그래서 나는 모두가 함께 좋은 게임을 할 수있는 가장 쉬운 방법을 찾고 있습니다. . –

0

그래서 다른 사람을 도울 수 있기를 바랍니다. 이것이 제가 끝내었던 것입니다. web.config에서 인증 모드는 'Forms'로 설정됩니다. 이것은 것을 의미한다

if (!Request.IsAuthenticated && AttemptSSO) 
{ 
    ReturnURL = Request.QueryString["ReturnUrl"]; 
    HttpContext.Current.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/Login.aspx" }, OpenIdConnectAuthenticationDefaults.AuthenticationType); 
} 
else if (Request.IsAuthenticated && AttemptSSO) 
{ 
    if (!string.IsNullOrEmpty(ReturnURL)) 
    { 
      var url = ReturnURL; 
      ReturnURL = ""; 
      Response.Redirect(ResolveUrl(url)); 
    } 
    else 
    { 
      Response.Redirect(ResolveUrl("~/Default.aspx")); 
    } 
} 

: 나는

나는 인증 요청을 트리거 내 사이트 마스터 페이지에 어떤 도전을 추가하고 대신 내 로그인 페이지로 다음을 추가하지 않은 다음 Startup.cs에게

public class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 

     var appId = ConfigurationCache.GetConfigurationString(TOS_Configuration.KEY_SSO_APPID); 
     var authority = ConfigurationCache.GetConfigurationString(TOS_Configuration.KEY_SSO_AUTHORITY); 

     app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); 
     app.UseCookieAuthentication(new CookieAuthenticationOptions()); 

     app.UseOpenIdConnectAuthentication(
     new OpenIdConnectAuthenticationOptions 
     { 
      ClientId = appId, 
      Authority = authority, 
      Notifications = new OpenIdConnectAuthenticationNotifications 
      { 
       AuthorizationCodeReceived = context => 
       { 

        string username = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Name).Value; 

        FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, username, DateTime.Now, DateTime.Now.AddMinutes(60), true, ""); 
        String encryptedTicket = FormsAuthentication.Encrypt(authTicket); 
        context.Response.Cookies.Append(FormsAuthentication.FormsCookieName, encryptedTicket); 

        return Task.FromResult(0); 
       }, 
       AuthenticationFailed = context => 
       { 
        context.HandleResponse(); 
        context.Response.Write(context.Exception.Message); 
        return Task.FromResult(0); 
       } 
      } 
     }); 

     // This makes any middleware defined above this line run before the Authorization rule is applied in web.config 
     app.UseStageMarker(PipelineStage.Authenticate); 

    } 

} 

추가 사용자가 유효한 폼 인증 토큰없이 인증 된 페이지에 도착하면 로그인 페이지로 리다이렉트됩니다. 로그인 페이지는 SSO가 설정되고 적절하게 처리되는지 결정합니다. 누군가가 그것을 향상시키는 방법에 관해 어떤 생각을 가지고 있다면 - 나는 그것들을 듣고 싶지만, 현재는 효과가 있습니다.