Как запросить информацию пользователя у IdentityServer4 - PullRequest
0 голосов
/ 31 декабря 2018

У меня есть основной поток входа в систему с использованием типа предоставления ResourceOwnerPassword.Пользователь может войти в систему, подтвердить свой пароль и получить токен, который он может использовать для доступа к API.Сейчас я пытаюсь передать претензию клиенту, чтобы я мог определить, с каким пользователем я имею дело, но я получаю сообщение об ошибке, которое, по моему мнению, является проблемой с областью действия клиента (хотяЯ не вижу, что).

Код ниже сокращен, чтобы избежать страниц и страниц кода, но я считаю, что он содержит все, что имеет отношение.Это настройка сервера идентификации:

services
    .AddIdentityServer()       
    .AddInMemoryClients(IdentityServerHelper.GetClients())
    .AddInMemoryApiResources(IdentityServerHelper.GetApiResources())
    .AddTestUsers(IdentityServerHelper.GetUsers())
    .AddInMemoryIdentityResources(
          IdentityServerHelper.GetIdentityResources());

Вспомогательные методы:

internal static IEnumerable<Client> GetClients()
{
    var clients = new List<Client>
    {
        new Client
        {
            ClientId = "MyClientApp",                    
            AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,                    
            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },
            AllowedScopes =
            {
                "myApi",
                "Role",
                IdentityServerConstants.StandardScopes.OpenId
                /*
                IdentityServerConstants.StandardScopes.Profile
                */
            }
        }
    };
}

internal static IEnumerable<IdentityResource> GetIdentityResources()
{
    return new List<IdentityResource> {
        new IdentityResource {
            Name = "Role",
            UserClaims = new List<string> { JwtClaimTypes.Role },

        }
    };
}

internal static List<TestUser> GetUsers()
{
    var users = new List<TestUser>
    {
            new TestUser
            {
                SubjectId = Guid.NewGuid(),
                Username = "user",
                Password = "pass",
                Claims = new List<Claim>()
                {
                    new Claim(JwtClaimTypes.Role, "Role1")
                }
            },

Идея состоит в том, чтобы вернуть Role1 клиенту.Вот код клиента:

_discoveryResponse = await _httpClient.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest
{
    Address = "https://localhost:5021",               
    Policy =
    {                    
        ValidateIssuerName = false,
    }                
});

var response = await _httpClient.RequestPasswordTokenAsync(new PasswordTokenRequest
{
    Address = _discoveryResponse.TokenEndpoint,
    ClientId = "MyClientApp",
    ClientSecret = "secret",
    Scope = "openid Role myApi",
    UserName = username,
    Password = password
});

if (response.IsError)
{
    return false;  // When specifying openid, get invalid scope here
}

_accessToken = response.AccessToken;                                    

. . . 

var userInfo = await _httpClient.GetUserInfoAsync(new UserInfoRequest()
{
    Address = _discoveryResponse.UserInfoEndpoint,
    Token = _accessToken
});

// userInfo is returning "Forbidden" here.

РЕДАКТИРОВАТЬ:

При указании openid в области я получаю следующую ошибку в журналах Identity Server:

fail: IdentityServer4.Validation.ScopeValidator [0] Запрошенная область не разрешена: openid

1 Ответ

0 голосов
/ 31 декабря 2018

Вам нужно добавить как минимум openid область при запросе токена.Изменение кода, как показано ниже, вероятно, решает проблему.

var clients = new List<Client>
{
    new Client
    {
        ClientId = "MyClientApp",                    
        AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,                    
        ClientSecrets =
        {
            new Secret("secret".Sha256())
        },
        AllowedScopes =
        {
            "myApi",
            "Role",
            IdentityServerConstants.StandardScopes.OpenId
        }
    }
};

var response = await _httpClient.RequestPasswordTokenAsync(new PasswordTokenRequest
{
    Address = _discoveryResponse.TokenEndpoint,
    ClientId = "MyClientApp",
    ClientSecret = "secret",
    Scope = "openid Role myApi",
    UserName = username,
    Password = password
});

Вы можете увидеть часть исходного кода с https://github.com/IdentityServer/IdentityServer4/blob/master/src/Validation/Default/UserInfoRequestValidator.cs#L47

...