2016-07-22 47 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

然後只需創建一個動態註冊頁面,該頁面需要查詢字符串參數「應用程序」,並從每個應用程序鏈接到每個應用程序 –