2016-07-22 22 views
1

私はIdentityServerV3を使用して、ほとんどのクライアントでユーザーを認証しています。 userが特定の `クライアントにログインできる必要があるように、IdentityServerを設定する際に問題が発生しています。IdentityServerを使用して特定のクライアントに特定のユーザーを認証する

はのは、以下のシナリオを見てみましょう:

私は2つのクライアントがある - >client1client2を。 私には3人のユーザーがいます - >user1user2user3です。

user1 & user2のみclient1へのアクセス権を持っています。 user3client2だけにアクセスできます。

client1にログインしようとすると、user3という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

id_tokenに入るカスタムクレームを指定すると、ユーザーがアクセスできるアプリケーション/クライアントの値がapplication_accessとなります。その中にはたくさんの人がいます。このカスタムクレームをIUserService実装に追加して、他のユーザー固有の主張と同じ方法でマッピングすることができます。

クライアントで、特定のクレームを確認し、ログインしたユーザーがその特定のクライアントの特定の値を持つクレームを持っているかどうかを確認します。

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

(マーク:RequireScopeは、アクセストークンとAPIのためですが、一般的なアイデアを得る)

+0

あなたの提案をありがとうが、私はそれをかなり理解していませんでした。追加のリンク 'Register'を介してユーザーを登録している間に、ユーザーが' login'フォームにリダイレクトされたその 'client'にユーザーをマップする必要があり、そのユーザーはその特定のクライアントに対してのみ認証されるべきです。 – Venky

+0

私は何をしようとしているのかをよりよく理解できるように質問を更新しました。それが役に立てば幸い。ありがとう。 – Venky

+0

次に、クエリ文字列のパラメータ 'application'を取得し、それぞれのアプリケーションからそのアプリケーションにリンクする動的registerpageを作成します –

関連する問題