OAuth. Сервер ресурсов использует неправильный URI аутентификации (ошибка носителя =invalid_token)

При соединении oauth между службами я пытаюсь отправить запрос токена на внешнюю конечную точку токена Oauth и использовать токен в качестве носителя для решения Microsoft (Dynamics CRM v.9.1 On-Premises). Используемая платформа не должна быть столь актуальной, поскольку мы говорим об OAuth, который представляет собой документированный протокол RFC. Код, который я использовал до сих пор для получения токена и выполнения запроса к серверу ресурсов с помощью носителя, вставлен ниже.

Когда я делаю запрос на сервер ресурсов, я получаю следующую ошибку.

      Bearer error=invalid_token, error_description=Error during token validation!, 
authorization_uri=https://mytokenserver/login, 
resource_id=https://myresourceserver/

Проблема в ответе заключается в том, что он показывает «authorization_uri», то есть https://mytokenserver/login , что неверно. Мой URI авторизации: https://mytokenserver/oauth2/authorize.

Мне не удалось найти какие-либо настройки на платформе Microsoft CRM, поэтому я предполагаю, что я генерирую неправильное утверждение JWT в приведенном ниже коде.

Есть ли опыт в этом? (небольшая деталь: сервер токенов oauth написан на Java)

          static private string clientId     = "rb7ddjkjWd8djkjlk";
    static private string pfxFile      = "C:\\keystore.p12";
    static private string pass         = "blabla";
    static private string authorityUri = "https://mytokenserver/oauth2/token";

    static private Uri environmentUri  = new Uri("https://myresourceserver/api/data/v9.1");

    static async Task<string> RequestTokenAndSendRequestToResourceServerAsync()
    {
        if (tokenCache != "")
            return tokenCache;

        var client = new HttpClient();

        var clientToken = GetJwtToken(pfxFile, pass, clientId, authorityUri, 180);

        Console.WriteLine("JWT Token is: " + clientToken);

        Parameters parameters = new Parameters
        {
            new KeyValuePair<string, string>("audience", clientId),
            new KeyValuePair<string, string>("requested_token_type", "urn:ietf:params:oauth:token-type:access_token")
        };
        ClientCredentialsTokenRequest clientCredentialsRequest = new ClientCredentialsTokenRequest
        {
            Parameters = parameters,
            GrantType = OidcConstants.GrantTypes.ClientCredentials,
            Address = authorityUri,
            ClientAssertion =
            {
                Type = OidcConstants.ClientAssertionTypes.JwtBearer,
                Value = clientToken
            }
        };
        clientCredentialsRequest.ClientCredentialStyle = ClientCredentialStyle.PostBody;
        var response = await client.RequestClientCredentialsTokenAsync(clientCredentialsRequest);

        if (response.IsError)
        { 
            Console.WriteLine(response.HttpStatusCode);
            Console.WriteLine(response.ErrorDescription);
            Console.WriteLine(response.ErrorType.ToString());
            throw response.Exception;
        }
        Console.WriteLine("Access Token is: " + response.AccessToken);

        // Set up the HTTP client
        var httpclient = new HttpClient
        {
            BaseAddress = new Uri("https://myresourceserver"),
            Timeout = new TimeSpan(0, 2, 0)  // Standard two minute timeout.
        };

        HttpRequestHeaders headers = httpclient.DefaultRequestHeaders;
        headers.Authorization = new AuthenticationHeaderValue("Bearer", response.AccessToken);
        headers.Add("OData-MaxVersion", "4.0");
        headers.Add("OData-Version", "4.0");
        headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        // Web API call
        var result = httpclient.GetAsync("WhoAmI").Result;

        var jsonResponse = await result.Content.ReadAsStringAsync();

        Console.WriteLine(result.ReasonPhrase);
        Console.WriteLine(jsonResponse);
        result.EnsureSuccessStatusCode();

        return response.AccessToken;
    }
    

    public static string GetJwtToken(string pfxFilePath, string password, string issuer, string audience, int expiryInMinutes)
    {
        Console.WriteLine("Creating JWT Token");
        string jwtToken = string.Empty;
        JwtSecurityToken jwtSecurityToken;

        X509Certificate2 signingCert = new X509Certificate2(pfxFilePath, password);
        X509SecurityKey privateKey = new X509SecurityKey(signingCert);

        var descriptor = new SecurityTokenDescriptor
        {
            // Audience = auth2/token endpoint, Issuer = clientId                
            Issuer = issuer,
            Audience = audience,
            IssuedAt = DateTime.UtcNow,
            Expires  = DateTime.UtcNow.AddMinutes(expiryInMinutes),
            Subject  = new ClaimsIdentity(new List<Claim>
            {
                new Claim(JwtClaimTypes.Subject, issuer),
                new Claim(Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
            }),
            SigningCredentials = new SigningCredentials(privateKey, SecurityAlgorithms.RsaSha256)
        };

        var handler = new JwtSecurityTokenHandler();
        handler.SetDefaultTimesOnTokenCreation = false;
        jwtSecurityToken = handler.CreateJwtSecurityToken(descriptor);
        jwtSecurityToken.Header.Remove("kid");

        jwtToken = handler.WriteToken(jwtSecurityToken);
        return jwtToken;
    }

1 ответ

Я предполагаю, что сервер ресурсов, который вы вызываете, не разрешает токены доступа к учетным данным клиента. Вероятно, это требует, чтобы пользователь был субъектом токена, а не вашего сервиса. Это может объяснить сообщение об ошибке. Сервер ожидает, что конечная точка для запроса кода авторизации — это точка, присутствующая в токене. У вас есть конечная точка токена (которая используется в потоке учетных данных клиента).

Другие вопросы по тегам