Я пытаюсь разобраться в "современных" методах аутентификации и иметь дело с OAuth и токеном доступа для вызова внешних служб в ASP.NET Core 5 MVC.
У меня есть регистрация приложения в Azure, которая настроена нормально — это разрешения API для этого приложения:
Моей целью является вызов MS Graph (несколько вызовов), а также MS Dynamics365 для сбора некоторой информации. Мне удалось настроить аутентификацию с помощью OAuth (или это OpenID Connect? Я никогда не уверен, как отличить эти два друг от друга) в моем приложении MVC, например (в Startup.cs
):
/* in appsettings.json:
"MicrosoftGraph": {
"Scopes": "user.read organization.read.all servicehealth.read.all servicemessage.read.all",
"BaseUrl": "https://graph.microsoft.com/v1.0"
},
*/
public void ConfigureServices(IServiceCollection services)
{
List<string> initialScopes = Configuration.GetValue<string>("MicrosoftGraph:Scopes")?.Split(' ').ToList();
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddInMemoryTokenCaches();
// further service setups
}
Все работает нормально — мне предлагается войти в систему, предоставить свои учетные данные, и в моем приложении MVC я могу проверить участников утверждений с их утверждениями после входа в систему — пока все выглядит нормально.
Следующий шаг — вызов нижестоящих API. Я изучил некоторые сообщения в блогах и учебные пособия и придумал это решение для получения токена доступа на основе имени scope
, которое мне нужно для данного вызова. Это мой код здесь (на странице Razor, используемой для отображения данных, полученных из MS Graph):
public async Task OnGetAsync()
{
List<string> scopes = new List<string>();
scopes.Add("Organization.Read.All");
// fetch the OAuth access token for calling the MS Graph API
var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(scopes);
HttpClient client = _factory.CreateClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
client.DefaultRequestHeaders.Add("Accept", "application/json");
string graphUrl = "https://graph.microsoft.com/v1.0/subscribedSkus";
string responseJson = await client.GetStringAsync(graphUrl);
// further processing and display of data fetched from MS Graph
}
Для областей MS Graph это работает просто отлично — я получаю свой токен доступа, я могу передать его моему HttpClient
, и вызов MS Graph завершается успешно, и я получаю нужную информацию.
Проблема начинается при попытке использовать тот же метод для получения маркера доступа для вызова MS Dynamics. Я предполагал, что просто указываю имя разрешения API, которое определено в регистрации Azure AD — user_impersonation
— вот так:
public async Task OnGetAsync()
{
List<string> scopes = new List<string>();
scopes.Add("user_impersonation");
var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(scopes);
// further code
}
Но теперь я не получаю ничего, кроме ошибок, таких как эта:
При обработке запроса произошло необработанное исключение.
MsalUiRequiredException: AADSTS65001: пользователь или администратор не дал согласия на использование приложения с идентификатором «257a582c-4461-40a4-95c3-2f257d2f8693» с именем «BFH_Dyn365_Monitoring». Отправьте интерактивный запрос авторизации для этого пользователя и ресурса.
что забавно, потому что согласие администратора было предоставлено - поэтому я не совсем уверен, в чем проблема.....
Затем я подумал, что, возможно, мне нужно добавить user_impersonation
в список начальных областей видимости (как определено в appsettings.json
и используется в методе Startup.ConfigureServices
), но добавление этого приводит к другой забавной ошибке:
При обработке запроса произошло необработанное исключение.
OpenIdConnectProtocolException: сообщение содержит ошибку: «invalid_client», error_description: «AADSTS650053: приложение «BFH_Dyn365_Monitoring» запросило область «user_impersonation», которая не существует в ресурсе «00000003-0000-0000-c000-000000000000». Свяжитесь с поставщиком приложения.
Странная вещь - как вы видели на самом первом снимке экрана - область ЕСТЬ присутствует при регистрации приложения - поэтому я не совсем уверен, почему это исключение выдается....
Может ли кто-нибудь пролить свет, возможно, из опыта вызова MS Dynamics с использованием токена OAuth? Это принципиально невозможно, или я где-то пропустил шаг или два?
Спасибо! Марк
И вуаля ! Вот и все ! При таком подходе я получаю действительный токен доступа для Dynamics при регистрации приложения Azure AD — большое спасибо! Хотел бы я проголосовать за это в 100 раз! :-)