2015-09-18 18 views
7

Bối cảnh: Tôi đang sử dụng ASP.NET MVC với máy chủ riêng. Dưới đây là phần còn lại của cấu hình/thiết lập.IdentityServer3: Một số Xác nhận quyền sở hữu không được trả về từ máy chủ định danh

Trong Khách hàng s của tôi trong máy chủ danh tính (chú ý AllowedScopes bộ):

public static class InMemoryClientSource 
{ 
    public static List<Client> GetClientList() 
    { 
     return new List<Client>() 
     { 
      new Client() 
      { 
       ClientName = "Admin website", 
       ClientId = "admin", 
       Enabled = true, 
       Flow = Flows.Hybrid, 
       ClientSecrets = new List<Secret>() 
       { 
        new Secret("admin".Sha256()) 
       }, 
       RedirectUris = new List<string>() 
       { 
        "https://admin.localhost.com/" 
       }, 
       PostLogoutRedirectUris = new List<string>() 
       { 
        "https://admin.localhost.com/" 
       }, 
       AllowedScopes = new List<string> { 
        Constants.StandardScopes.OpenId, 
        Constants.StandardScopes.Profile, 
        Constants.StandardScopes.Email, 
        Constants.StandardScopes.Roles 
       } 
      } 
     }; 
    } 
} 

Sau đây là các Scopes:

public static class InMemoryScopeSource 
{ 
    public static List<Scope> GetScopeList() 
    { 
     var scopes = new List<Scope>(); 

     scopes.Add(StandardScopes.OpenId); 
     scopes.Add(StandardScopes.Profile); 
     scopes.Add(StandardScopes.Email); 
     scopes.Add(StandardScopes.Roles); 

     return scopes.ToList(); 
    } 
} 

Trong nhận dạng máy chủ, đây là cách cấu hình máy chủ. (Chú ý ClientsScopes được những người cung cấp ở trên):

var userService = new UsersService(.... repository passed here ....); 

     var factory = new IdentityServerServiceFactory() 
      .UseInMemoryClients(InMemoryClientSource.GetClientList()) 
      .UseInMemoryScopes(InMemoryScopeSource.GetScopeList()); 

     factory.UserService = new Registration<IUserService>(resolver => userService); 

     var options = new IdentityServerOptions() 
     { 
      Factory = factory, 
      SigningCertificate = Certificates.Load(), // certificates blah blah 
      SiteName = "Identity" 
     }; 

     app.UseIdentityServer(options); 

Cuối cùng, ở phía bên ứng dụng web của khách hàng, đây là cách auth được thiết lập:

app.UseCookieAuthentication(new CookieAuthenticationOptions() 
     { 
      AuthenticationType = "Cookies" 
     }); 

     app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions() 
     { 
      Authority = "https://id.localhost.com", 
      ClientId = "admin", 
      RedirectUri = "https://admin.localhost.com/", 
      PostLogoutRedirectUri = "https://admin.localhost.com/", 
      ResponseType = "code id_token token", 
      Scope = "openid profile email roles", 
      ClientSecret = "admin", 
      SignInAsAuthenticationType = "Cookies" 
     }); 

Tôi có triển khai lớp tùy chỉnh cho IUserService:

public class UsersService : UserServiceBase 
{ 
    public UsersService(.... repository passed here ....) 
    { 
     //.... ctor stuff 
    } 

    public override Task AuthenticateLocalAsync(LocalAuthenticationContext context) 
    { 
     // var user = .... retrieved from database ..... 
     // ... auth logic ... 

     if (isAuthenticated) 
     { 
      var claims = new List<Claim>(); 
      claims.Add(new Claim(Constants.ClaimTypes.GivenName, user.FirstName)); 
      claims.Add(new Claim(Constants.ClaimTypes.FamilyName, user.LastName)); 
      claims.Add(new Claim(Constants.ClaimTypes.Email, user.EmailAddress)); 
      context.AuthenticateResult = new AuthenticateResult(user.Id.ToString(), user.EmailAddress, claims); 
     } 

     return Task.FromResult(0); 
    } 
} 

Như bạn thấy, các xác nhận quyền sở hữu được chuyển vào dòng này:

context.AuthenticateResult = new AuthenticateResult(user.Id.ToString(), user.EmailAddress, claims); 

Khi tôi thử đăng nhập vào IdentityServer3, tôi có thể đăng nhập thành công vào ứng dụng web của ứng dụng khách. HOWEVER, khi tôi nhận được xác nhận quyền sở hữu của người dùng, tôi không thấy bất kỳ xác nhận quyền sở hữu danh tính nào. Không given_name, family_nameemail khiếu nại. Ảnh chụp màn hình bên dưới:

As you can see, there are no given_name, family_name and email claims included.

Bất cứ điều gì tôi có thể đã bỏ lỡ? Cảm ơn trước!

+0

cấu hình của bạn trông tốt. Tôi biết, nhưng bạn có chắc chắn rằng người dùng được xác thực có những tuyên bố đó không? –

+0

Hey @ScottBrady, tôi cho rằng họ đã có bởi vì tôi đã thêm những yêu cầu đó vào context.AuthenticateResult (như bạn thấy trên mã mẫu ở trên để triển khai thực hiện UsersService tùy chỉnh). – jerbersoft

Trả lời

5

Cuối cùng tìm thấy giải pháp cho vấn đề này.

Trước tiên, tôi đã di chuyển việc tạo xác nhận quyền sở hữu đối với GetProfileDataAsync đã ghi đè (trong lớp UserService của tôi). Dưới đây là thực hiện của tôi về nó:

public override Task GetProfileDataAsync(ProfileDataRequestContext context) 
     { 
      var identity = new ClaimsIdentity(); 

      UserInfo user = null; 
      if (!string.IsNullOrEmpty(context.Subject.Identity.Name)) 
       user = _facade.Get(context.Subject.Identity.Name); 
      else 
      { 
       // get the sub claim 
       var claim = context.Subject.FindFirst(item => item.Type == "sub"); 
       if (claim != null) 
       { 
        Guid userId = new Guid(claim.Value); 
        user = _facade.Get(userId); 
       } 
      } 

      if (user != null) 
      { 
       identity.AddClaims(new[] 
       { 
        new Claim(Constants.ClaimTypes.PreferredUserName, user.Username), 
        new Claim(Constants.ClaimTypes.Email, user.EmailAddress) 
        // .. other claims 
       }); 
      } 

context.IssuedClaims = identity.Claims; //<- MAKE SURE you add the claims here 
      return Task.FromResult(identity.Claims); 
     } 

Hãy chắc chắn rằng chúng ta vượt qua những tuyên bố với "context.IssueClaims" bên trong GetProfileDataAsync() trước khi trở về nhiệm vụ.

Và đối với những người quan tâm về cách AuthenticateLocalAsync của tôi() trông giống như:

var user = _facade.Get(context.UserName); 
      if (user == null) 
       return Task.FromResult(0); 

      var isPasswordCorrect = BCrypt.Net.BCrypt.Verify(context.Password, user.Password); 
      if (isPasswordCorrect) 
      { 
       context.AuthenticateResult = new AuthenticateResult(user.Id.ToString(), user.Username); 
      } 

      return Task.FromResult(0); 

tôi nêu ra một vấn đề tương tự trong trang dự án IdentityServer3 GitHub có chứa các lời giải thích về việc tại sao tôi gặp phải vấn đề của tôi. Đây là liên kết: https://github.com/IdentityServer/IdentityServer3/issues/1938

+0

Điều này có nghĩa là phần mã này trong phương thức "GetProfileDataAsync": var claim = context.Subject.FindFirst (item => item.Type == "sub"); if (claim! = Null) { Hướng dẫn sử dụngId = new Guid (claim.Value); user = _facade.Get (userId); } – Jenan

+0

Phương thức "" GetProfileDataAsync "được gọi hai lần và sau cuộc gọi đầu tiên là context.Subject.Identity.Name null, tại sao là null - bạn có biết không? – Jenan

+0

@Janan, để trả lời câu hỏi đầu tiên của bạn, nhận được" phụ "(Tôi không biết tại sao nó lại được gọi là hai lần. Có lẽ bạn có thể muốn đi đến các cuộc thảo luận gorub IdentityServer3, ai đó có thể giúp đỡ. :) – jerbersoft

-1

Tôi không sử dụng máy chủ định danh, tuy nhiên tôi đang sử dụng Quỹ nhận diện Windows, mà tôi tin là những gì IdentityServer sử dụng. Để truy cập vào những tuyên bố tôi sử dụng:

((ClaimsIdentity)User.Identity).Claims

+0

Hi @ rll, tôi đã thử nhưng những tuyên bố vẫn là những gì bạn có thể thấy trong ảnh chụp màn hình trong câu hỏi. Dù sao cũng cảm ơn bạn. :) – jerbersoft

4

Giải pháp của tôi là thêm danh sách xác nhận quyền sở hữu vào cấu hình phạm vi của tôi để trả lại các xác nhận quyền sở hữu đó. Tài liệu của wiki here mô tả nó.

Đối với một ứng dụng trong bộ nhớ tất cả tôi đã làm được một cái gì đó như thế này:

public class Scopes 
{ 
    public static IEnumerable<Scope> Get() 
    { 
     return new Scope[] 
     { 
      StandardScopes.OpenId, 
      StandardScopes.Profile, 
      StandardScopes.Email, 
      StandardScopes.Roles, 
      StandardScopes.OfflineAccess, 
      new Scope 
      { 
       Name = "yourScopeNameHere", 
       DisplayName = "A Nice Display Name", 
       Type = ScopeType.Identity, 
       Emphasize = false, 
       Claims = new List<ScopeClaim> 
       { 
        new ScopeClaim("yourClaimNameHere", true), 
        new ScopeClaim("anotherClaimNameHere", true) 
       } 
      } 
     }; 
    } 
} 
Các vấn đề liên quan