OAuth。资源服务器使用错误的身份验证 URI(承载错误=invalid_token)

问题描述 投票:0回答:1

在服务到服务的 oauth 通信中,我尝试将令牌请求发送到外部 Oauth 令牌端点,并将令牌用作 Microsoft 解决方案(Dynamics CRM v.9.1 On-Premises)的承载。 所使用的平台不应该如此相关,因为我们正在谈论 OAuth,它是 RFC 记录的协议 到目前为止,我用来获取令牌并使用 Bearer 向资源服务器发出请求的代码是下面粘贴的代码。

当我向资源服务器发出请求时,出现以下错误。

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 token server是用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;
    }
java c# oauth-2.0 dynamics-crm microsoft-oauth
1个回答
0
投票

我的猜测是您调用的资源服务器不允许客户端凭据访问令牌。它可能需要用户成为令牌的主题,而不是您的服务。这可以解释错误消息。服务器期望授权代码请求的端点是令牌中存在的端点。您拥有令牌端点(在客户端凭证流程中使用)。

© www.soinside.com 2019 - 2024. All rights reserved.