8

コンテキスト: OWIN セルフ ホストで ASP.NET MVC を使用しています。以下は、構成/セットアップの残りの部分です。

アイデンティティ サーバーの Client で (AllowedScopes セットに注目してください) :

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

スコープは次のとおりです。

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

Identity Serverで、サーバーがどのように構成されているかを次に示します。(クライアントスコープは上記のものであることに注意してください):

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

最後に、クライアント Web アプリケーション側では、認証の設定方法は次のとおりです。

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

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

ご覧のとおり、クレームは次の行で渡されます。

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

IdentityServer3 にログインしようとすると、クライアント Web アプリケーションに正常にログインできます。ただし、ユーザー クレームを取得しても、ID クレームは表示されません。given_namefamily_name、およびemailクレームはありません。以下のスクリーンショット:

ご覧のとおり、given_name、family_name、および email クレームは含まれていません。

私が見逃したかもしれないものはありますか?前もって感謝します!

4

3 に答える 3

6

私の解決策は、クレームを返すためにスコープ構成にクレームのリストを追加することでした。ここのwikiのドキュメントはそれを説明しました。

インメモリクライアントの場合、私がしたことは次のようなことだけでした:

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)
                }
            }
         };
    }
}
于 2015-12-01T06:27:42.553 に答える
5

最後に、この問題の解決策を見つけました。

まず、クレームの作成をオーバーライドされた GetProfileDataAsync (UserService クラス内) に移動しました。これが私の実装です:

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

タスクを返す前に、GetProfileDataAsync() 内の "context.IssueClaims" にクレームを渡すようにしてください。

そして、私の AuthenticateLocalAsync() がどのように見えるかに興味がある人のために:

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

問題が発生した理由についての説明を含む IdentityServer3 GitHub プロジェクト ページで同様の問題を提起しました。リンクは次のとおりです: https://github.com/IdentityServer/IdentityServer3/issues/1938

于 2015-09-25T18:29:15.050 に答える