Получите 401 Несанкционированный вызов WebApi из другого WebAp от имени api (не пользователя)
У нас есть несколько веб-API ASPNET Core в Azure, которые мы вызываем от имени пользователя. Этот пользователь обычно входит на веб-сайт ASPNET, также в Azure.
Мы вводим аудиторскую службу. Похоже, что он должен вызываться от имени вызывающей службы, а не от имени аутентифицированного пользователя.
- Служба аудита имеет связанную регистрацию приложения в Azure AD.
- Служба аудита имеет область действия под названием "access_as_application", хотя, просмотрев документацию по области ".default", я не был уверен, что мне нужна область
- Вызывающее приложение (веб-сайт ASPNET Core) было добавлено в раздел «Авторизованные клиентские приложения» для ранее упомянутой области.
В вызывающем приложении я получаю токен доступа для приложения, а не для пользователя, используя
GetAccessTokenForAppAsync
.
var accessToken = await this.tokenAcquisition.GetAccessTokenForAppAsync(this.auditApiScope);
System.Diagnostics.Debug.WriteLine($"access token-{accessToken}");
this.httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
this.httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
В настоящее время я запускаю вызывающее приложение и службу аудита на своей локальной машине разработки.
Когда я звоню в аудиторскую службу, я получаю сообщение 401 Unauthorized
var response = await this.httpClient.PostAsync($"{this.auditApiBaseAddress}v1/entries", requestContent);
ОБНОВИТЬ
Я добавил идентификатор приложения Azure Ad вызывающего приложения как известное приложение-клиент в службе аудита через манифест приложения. Это не помешало 401
"knownClientApplications": [
"7ac7f49d-e9fa-4e1b-95b2-03e0e1981f58"
],
ОБНОВЛЕНИЕ 2
Я вижу, что экземпляр службы, работающей в Visual Studio, сообщает о трассировке стека. Это относится к проблеме IDW10201.
System.UnauthorizedAccessException: IDW10201: Neither scope or roles claim was found in the bearer token.
at Microsoft.Identity.Web.MicrosoftIdentityWebApiAuthenticationBuilderExtensions.<>c__DisplayClass3_1.<<AddMicrosoftIdentityWebApiImplementation>b__1>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.Identity.Web.MicrosoftIdentityWebApiAuthenticationBuilder.<>c__DisplayClass14_0.<<CallsWebApiImplementation>b__1>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.AuthenticateAsync()
at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Есть мысли почему?
2 ответа
В настоящее время вы должны выполнять межсерверное взаимодействие, то есть без участия пользователя. Таким образом, ваше серверное приложение должно создать, а затем предоставить роль приложения в качестве разрешения приложения для клиентского приложения .
Во-первых, вам необходимо предоставить доступ к API- интерфейсу серверного приложения, защищенного Azure, который можно настроить в соответствии со следующим процессом:
Портал Azure> Регистрация приложений> Предоставить API> Добавить область> Добавить клиентское приложение
Затем вам нужно создать
appRole
серверного приложения, а затем предоставьте эту роль как разрешение приложения клиентскому приложению.
Затем перейдите в клиентское приложение > Разрешения API> Добавить разрешение> Мои API > ваше приложение API.
Наконец, вам нужно получить токен доступа, используя поток учетных данных клиента, в котором ни один пользователь не вошел в систему:
Разобрать токен :
Хотя я отметил вклад Карла Чжао как ответ, мне показалось, что за скриншотами немного сложно следить, так что это моя попытка сделать это немного яснее.
В этом сценарии, когда мы хотим, чтобы проверка подлинности между зарегистрированным приложением (клиентом) Azure Ad и другим зарегистрированным приложением Azure Ad (службой аудита) не была решением. Вместо того, чтобы открывать область видимости, нам нужно было раскрыть appRole.
Шаги, необходимые для предоставления и последующего запроса доступа к роли приложения, были
- Регистрация приложений -> Служба аудита -> Управление -> Роли приложений -> Создание роли приложения
- При создании роли приложения убедитесь, что типом Разрешенного члена является «Приложения».
- Теперь перейдите в Регистрация приложений -> YourClientApplication -> Разрешения Api -> Добавить разрешение
- Я ожидал, что служба аудита появится в разделе «Мои API» на панели «Запросить разрешения API». Я этого не сделал, единственный способ запросить разрешение на ранее созданное AppRole - это ввести AppId службы аудита в поле поиска в разделе «API-интерфейсы, которые использует моя организация».
- Как только мне удалось выбрать службу аудита, я выбрал «Разрешения для приложений», а не «Делегированные разрешения», а затем выбрал конкретную роль.
После того, как клиентскому приложению был предоставлен доступ, нам нужно было написать код, чтобы получить токен доступа. Использование библиотеки Mictosoft.Identity.Web
var accessToken = await this.tokenAcquisition.GetAccessTokenForAppAsync(this.auditApiScope);
System.Diagnostics.Debug.WriteLine($"access token-{accessToken}");
this.httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
this.httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Обратите внимание на вызов GetAccessTokenForApp Async, а не GetAccessTokenForUserAsync.
GetAccessTokenForAppAsync
по-прежнему требуется область действия, однако, как уже было сказано, настраиваемая область не требуется. Область видимости - ".default", поэтому строка, переданная этому вызову в нашем случае, была https://ourdomain/audit-service/.default", которая является нашим URI идентификатора приложения плюс".default"