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