У меня есть веб-приложение, написанное на Angular 6, использующее пакет adal-angular4 для выполнения аутентификации через AAD. Я пытаюсь получить интерфейс пользователя для связи с бэкэнд-сервисом с помощью этого токена. Тем не менее, я продолжаю получать 401 Несанкционированный ответ при попытке вызвать API сервера, даже когда вся проверка должна быть отключена. Проверка токена с помощью jwt.io выдает ошибку «недопустимая подпись» внизу страницы, но в противном случае токен доступен для чтения.
Что касается конфигурации AAD, то и внешнее приложение, и базовая служба регистрируются как отдельные приложения AAD, поэтому любые ссылки на clientId
или clientAppId
относятся к идентификатору приложения клиента, а apiServiceId
- к идентификатору серверной службы. , Я также раскрыл область действия при регистрации внутреннего приложения, добавил разрешение API для регистрации внешнего приложения для этой области и авторизовал приложение внешнего интерфейса в базовом приложении. Я также включил неявное предоставление для идентификаторов токенов и токенов доступа для обеих служб. Вот соответствующий код:
app.module.ts:
// imports
@NgModule({
declarations: [ ... ],
imports: [ ... ],
providers: [
AdalService,
AdalGuard,
{ provide: HTTP_INTERCEPTORS, useClass: AdalInterceptor, multi: true }
],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.ts:
import { Component } from '@angular/core';
import { AdalService } from 'adal-angular4';
import { environment } from '../environments/environment';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'Tour of Heroes';
constructor(private adalService: AdalService) {
adalService.init(environment.adalConfig);
}
}
toolbar.component.ts (где находится кнопка входа в систему):
import { Component, OnInit } from '@angular/core';
import { AdalService } from 'adal-angular4';
@Component({
selector: 'app-toolbar',
templateUrl: './toolbar.component.html',
styleUrls: ['./toolbar.component.css']
})
export class ToolbarComponent implements OnInit {
constructor(private adalService: AdalService) { }
ngOnInit() {
this.adalService.handleWindowCallback();
console.log(this.adalService.userInfo);
}
login() {
this.adalService.login();
}
logout() {
this.adalService.logOut();
}
get authenticated(): boolean {
return this.adalService.userInfo.authenticated;
}
get username(): string {
return this.adalService.userInfo.userName;
}
}
environment.ts:
export const environment = {
production: true,
adalConfig: {
tenant: 'MyTenant.onmicrosoft.com',
clientId: '<clientId>',
endpoints: {
"https://localhost:8443/api": "<apiServiceId>"
}
}
};
Из Startup.cs:
// TODO: Put strings in config
const string tenantId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
const string clientAppId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
appBuilder.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = "MyTenant.onmicrosoft.com",
TokenValidationParameters = new TokenValidationParameters
{
// Authentication still fails when all bools below are set to false.
NameClaimType = ClaimTypes.Name,
AuthenticationType = "AADJwt",
ValidateLifetime = true,
RequireExpirationTime = true,
ValidateAudience = true,
ValidAudiences = new[]
{
clientAppId,
},
ValidateIssuer = true,
ValidIssuers = new[]
{
$"https://sts.windows.net/{tenantId}/",
$"https://login.microsoftonline.net/{tenantId}/",
},
}
});
Controller.cs:
[Authorize]
public class MyController : ApiController
{
// APIs
}
Вот как выглядит токен согласно jwt.io:
.
Заголовок:
{
"typ": "JWT",
"alg": "RS256",
"x5t": "nbCwW11w3XkB-xUaXwKRSLjMHGQ",
"kid": "nbCwW11w3XkB-xUaXwKRSLjMHGQ"
}
Полезная нагрузка:
{
"aud": "<clientId>",
"iss": "https://sts.windows.net/<tenantId>/",
"iat": 1547682045,
"nbf": 1547682045,
"exp": 1547685945,
"aio": "AVQAq/8KAAAAONOm6T/DrjjHFUTe/uPcsFcv2Iye85/EtY+cFYyq+X69OcQlHyqqPcYF0cjRWHyIRnnkcr7PkSTHp5bRb40AGUhVS5yuG53RCO0lNAQCBfE=",
"amr": [
"pwd",
"rsa"
],
"email": "asdf@asdf.com",
"family_name": "asdf",
"given_name": "asdf",
"idp": "https://sts.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/",
"ipaddr": "x.x.x.x",
"name": "asdf asdf",
"nonce": "1a80bf29-e720-4abc-91c3-bc37c066286a",
"oid": "f4f2107f-a760-4db4-b5d6-9a9fb6d2cb6b",
"sub": "ll04ffs2YHBR0esHBJp9vevJEbgITRC9ushAQdZbB7U",
"tid": "d93850bc-6bc9-4a51-9975-13e297ee0710",
"unique_name": "asdf@asdf.com",
"uti": "A7mEPuQ6REKQIFShTCoDAA",
"ver": "1.0"
}
Почему моя аутентификация не будет выполнена? Все в токене, который я хочу проверить, кажется, соответствует тому, что я ожидаю, поэтому я понятия не имею, почему я продолжаю получать 401. Тот факт, что jwt.io не может проверить подпись, заставляет меня думать, что что-то не так; что бы это могло быть?
Редактировать : Добавлена информация о настройке AAD и предоставлен обновленный файл environment.ts, включающий массив endpoints
. Из того, что я читаю, AdalInterceptor
будет автоматически получать и вводить токены доступа на основе endpoints
. Полученный токен функционально идентичен показанному выше. Я пропускаю какую-то другую конфигурацию?