2016-07-22 48 views
1

我正在使用IdentityServerV3为少数客户端验证用户。我在配置IdentityServer时遇到问题,以致特定的user必须能够登录到特定的客户端。使用IdentityServer为特定客户端验证特定用户

让我们下面的情形:

我有2个客户 - >client1client2。我有3个用户 - >user1user2user3

user1 & user2只能访问client1。而user3只能访问client2

当我尝试登录到client1user3身份服务器正在验证成功。我不想要的。

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); 
      }); 

我需要了解的最好方式到user映射到client同时注册,并确保用户只能登录一个客户端,而不是任何其他客户端即使usernamepassword对于该用户的所有客户端都是相同的。

+0

你解决这个问题?你能分享你的解决方案吗? – Keith

回答

3

如果您提供自定义声明以进入id_token,名为application_access,并且该值具有用户有权访问的应用程序/客户端的值;哪一个可能有很多。您可以在您的IUserService实施中添加此自定义声明,并以映射其他用户特定声明的相同方式映射此声明。

然后,在您的客户端中,对该特定索赔进行检查,并检查登录用户是否对该特定客户端具有特定值的索赔。

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

(标志:RequireScope是访问令牌和API,但你的总体思路)

+0

感谢您的建议,但我并不完全了解它。在通过附加链接“注册”注册用户时,我需要将用户映射到用户重定向到登录表单的那个“客户端”,并且该用户只能通过该特定客户端的身份验证。 – Venky

+0

我更新了我的问题,让您更好地了解我正在尝试做什么。希望能帮助到你。谢谢。 – Venky

+0

然后只需创建一个动态注册页面,该页面需要查询字符串参数“应用程序”,并从每个应用程序链接到每个应用程序 –