2016-07-22 2 views
1

일부 클라이언트의 사용자 인증에 IdentityServerV3을 사용하고 있습니다. 특정 user이 특정`클라이언트에 로그인 할 수 있어야하는 방식으로 IdentityServer을 구성하는 데 문제가 있습니다. IdentityServer를 사용하여 특정 클라이언트에 대한 특정 사용자 인증

은 이제 아래의 시나리오를 보자 :

내가이 명 고객이 ->client1, client2을. 나는 3 명의 사용자가 ->user1, user2, user3입니다.

user1 & user2client1에만 액세스 할 수 있습니다. 반면 user3client2에만 액세스 할 수 있습니다.

client1user3으로 로그인하려고하면 ID 서버가 성공적으로 인증됩니다. 나는 싫어.

public static class Clients 
{ 
    public static IEnumerable<Client> Get() 
    { 
     return new[] 
     { 
      new Client 
      { 
       Enabled = true, 
       ClientName = "MVC Client", 
       ClientId = "mvc", 
       Flow = Flows.Hybrid, 

       RedirectUris = new List<string> 
       { 
        "https://localhost:44319/" 
       } 
      }, 
      new Client 
      { 
       Enabled = true, 
       ClientName = "MVC Client 2", 
       ClientId = "mvc2", 
       Flow = Flows.Hybrid, 

       RedirectUris = new List<string> 
       { 
        "https://localhost:44319/" 
       } 
      } 
     }; 
    } 
} 

사용자는 다음과 같습니다

public static class Users 
{ 
    public static List<InMemoryUser> Get() 
    { 
     return new List<InMemoryUser> 
     { 
      new InMemoryUser 
      { 
       Username = "bob", 
       Password = "secret", 
       Subject = "1", 

       Claims = new[] 
       { 
        new Claim(Constants.ClaimTypes.GivenName, "Bob"), 
        new Claim(Constants.ClaimTypes.FamilyName, "Smith") 
       } 
      }, 
      new InMemoryUser 
      { 
       Username = "rob", 
       Password = "secret", 
       Subject = "2", 

       Claims = new[] 
       { 
        new Claim(Constants.ClaimTypes.GivenName, "Rob"), 
        new Claim(Constants.ClaimTypes.FamilyName, "Thompson") 
       } 
      }, 
      new InMemoryUser 
      { 
       Username = "Jerry", 
       Password = "secret", 
       Subject = "3", 

       Claims = new[] 
       { 
        new Claim(Constants.ClaimTypes.GivenName, "Jerry"), 
        new Claim(Constants.ClaimTypes.FamilyName, "Smith") 
       } 
      } 
     }; 
    } 
} 

이제 OWIN 시작 클래스는 다음과 같습니다

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     app.Map("/identity", idsrvApp => 
      { 
       idsrvApp.UseIdentityServer(new IdentityServerOptions 
       { 
        SiteName = "Embedded IdentityServer", 
        SigningCertificate = LoadCertificate(), 

        Factory = InMemoryFactory.Create(
         users : Users.Get(), 
         clients: Clients.Get(), 
         scopes : StandardScopes.All) 
       }); 
      }); 
    } 

    X509Certificate2 LoadCertificate() 
    { 
     return new X509Certificate2(
      string.Format(@"{0}\bin\identityServer\idsrv3test.pfx", AppDomain.CurrentDomain.BaseDirectory), "idsrv3test"); 
    } 
} 

내가 IdentityServer이있는 사용자 bleongs을 알고 표시되지 않습니다하는 클라이언트. 내 시나리오가 IdentityServer으로 지원되지 않거나 무엇이든 누락되었습니다.

UPDATE

public class LocalRegistrationUserService : UserServiceBase 
    { 
     public class CustomUser 
     { 
      public string Subject { get; set; } 
      public string Username { get; set; } 
      public string Password { get; set; } 
      public List<Claim> Claims { get; set; } 
     } 

     public static List<CustomUser> Users = new List<CustomUser>(); 

     public string ClientId { get; set; } 

     public override Task AuthenticateLocalAsync(LocalAuthenticationContext context) 
     { 
      var user = Users.SingleOrDefault(x => x.Username == context.UserName && x.Password == context.Password); 
      if (user != null) 
      { 
       context.AuthenticateResult = new AuthenticateResult(user.Subject, user.Username); 
      } 

      return Task.FromResult(0); 
     } 
} 

While registering the user i am redirecting him to a controller in Identity Server Host.

public class LocalRegistrationController : Controller 
    { 
     [Route("core/localregistration")] 
     [HttpGet] 
     public ActionResult Index(string signin) 
     { 
      return View(); 
     } 

     [Route("core/localregistration")] 
     [HttpPost] 
     public ActionResult Index(string signin, LocalRegistrationModel model) 
     { 
      var ctx = Request.GetOwinContext(); 
      if (ModelState.IsValid) 
      { 
       var user = new LocalRegistrationUserService.CustomUser 
       { 
        Username = model.Username, 
        Password = model.Password, 
        Subject = Guid.NewGuid().ToString(), 
        Claims = new List<Claim>() 
       }; 
       LocalRegistrationUserService.Users.Add(user); 
       user.Claims.Add(new Claim(Constants.ClaimTypes.GivenName, model.First)); 
       user.Claims.Add(new Claim(Constants.ClaimTypes.FamilyName, model.Last)); 

       return Redirect("~/core/" + Constants.RoutePaths.Login + "?signin=" + signin); 
      } 

      return View(); 
     } 
    } 

startup.cs

app.Map("/core", coreApp => 
      { 
       var factory = new IdentityServerServiceFactory() 
        .UseInMemoryClients(Clients.Get()) 
        .UseInMemoryScopes(Scopes.Get()); 

       // different examples of custom user services 
       //var userService = new RegisterFirstExternalRegistrationUserService(); 
       //var userService = new ExternalRegistrationUserService(); 

       var userService = new LocalRegistrationUserService(); 

       // note: for the sample this registration is a singletone (not what you want in production probably) 
       factory.UserService = new Registration<IUserService>(resolver => userService); 
       factory.ViewService = new Registration<IViewService, CustomViewService>(); 
       var options = new IdentityServerOptions 
       { 
        SiteName = "Identity Server 3", 

        SigningCertificate = Certificate.Get(), 
        Factory = factory, 

        AuthenticationOptions = new AuthenticationOptions 
        { 
         IdentityProviders = ConfigureAdditionalIdentityProviders, 
         LoginPageLinks = new LoginPageLink[] { 
          new LoginPageLink{ 
           Text = "Register", 
           // Href = "~/externalregistration", 
           Href = "~/localregistration", 
           //Href = "localregistration" 
          }, 
          new LoginPageLink{ 
           Text = "Forgot Password?", 
           Href = "~/forgotpassword", 
           //Href = "localregistration" 
          } 
         } 
        }, 

        EventsOptions = new EventsOptions 
        { 
         RaiseSuccessEvents = true, 
         RaiseErrorEvents = true, 
         RaiseFailureEvents = true, 
         RaiseInformationEvents = true 
        } 
       }; 

       coreApp.UseIdentityServer(options); 
      }); 

나는 다른 클라이언트를 등록하는 동안 clientuser를 매핑 할 수있는 최선의 방법을 이해하고 사용자가 해당 클라이언트에 로그인 할 수 있는지 확인하지 필요 usernamepassword은 해당 사용자의 모든 클라이언트에 대해 동일합니다.

+0

당신이이 문제를 해결 했는가를? 솔루션을 공유 할 수 있습니까? – Keith

답변

3

사용자가 액세스 할 수있는 응용 프로그램/클라이언트의 값이 application_access 인 id_token을 사용할 사용자 정의 클레임을 제공하면 어떻게됩니까? 거기에는 많은 것이있을 수 있습니다. 사용자 지정 IUserService 구현에이 사용자 지정 클레임을 추가하고 다른 사용자 특정 클레임을 매핑하는 것과 같은 방법으로 매핑 할 수 있습니다.

그런 다음 클라이언트에서 해당 특정 클레임을 확인하고 로그인 한 사용자가 특정 클라이언트에 대한 특정 값의 클레임을 갖고 있는지 확인하십시오.

https://github.com/IdentityModel/Thinktecture.IdentityModel.45/blob/master/IdentityModel/Thinktecture.IdentityModel/Authorization/WebApi/ScopeAttribute.cs

(마크 : RequireScope는 액세스 토큰과 API입니다,하지만 당신은 일반적인 생각 얻을)

+0

당신의 제안에 감사하지만 그것을 이해하지 못했습니다.추가 링크 인'Register'를 통해 사용자를 등록하는 동안 사용자가'login' 양식으로 리디렉션 된 '클라이언트'로 사용자를 매핑해야하며 해당 사용자는 해당 특정 클라이언트에 대해서만 인증되어야합니다. – Venky

+0

내가 뭘하려고하는지 더 잘 알 수 있도록 내 질문을 업데이트했습니다. 희망이 도움이됩니다. 감사. – Venky

+0

그런 다음 쿼리 문자열 param'application'을 사용하는 동적 registerpage를 만들고 각 응용 프로그램에서 각 응용 프로그램의 link –