【发布时间】:2021-07-21 22:58:30
【问题描述】:
由于结果比预期的要长,这里有一个 tl;dr:
我的 Angular 应用程序没有将它从 Azure AD 接收到的不记名令牌发送到 API,因此 API 返回 401 响应。 该设置基于blog post 解释如何实现它。 博文中提到的示例应用程序适用于我的 Azure AD 设置,并在 API 调用中正确提供令牌。
加长版:
我正在开发一个相对简单的基于 Angular 的前端和一个 Spring Boot 后端。前端和后端通过 REST API 进行通信。该应用程序部署在 Azure Spring Cloud 上。 对于用户身份验证,应用程序从 Azure AD 请求并接收持有者令牌。然后它应该将此令牌与每个 REST 请求一起传输到 API。
我按照blog post 进行了必要的更改。 Azure AD 确实提供了有效的 JWT 令牌。
我的问题是,令牌没有在 REST 调用中传递到后端,因此身份验证失败并返回 401 状态。
以下是我在前端所做的相关配置(根据链接的博文中的描述):
app.module.ts
@NgModule({
imports: [
...
HttpClientModule,
OAuthModule.forRoot({
resourceServer: {
allowedUrls: ['http://localhost:8020/api', 'http://localhost:4200/api'], //environment.allowedUrls,
sendAccessToken: true
}
})
...
],
declarations: [AppComponent],
providers: [{ provide: APP_BASE_HREF, useValue: environment.baseHref }],
bootstrap: [AppComponent]
})
auth.config.ts
import { AuthConfig } from 'angular-oauth2-oidc';
import {environment} from "../environments/environment";
export const authConfig: AuthConfig = {
issuer: 'https://login.microsoftonline.com/*****************61ea/v2.0',
redirectUri: window.location.origin + environment.redirectURIPath,
clientId: '*****************cf76',
responseType: 'code',
strictDiscoveryDocumentValidation: false,
scope: 'openid api://*****************cf76/Rest.Api',
}
客户和租户 ID “模糊”了。但他们是正确的。 Screenshot of the app overview on Azure (Tenant and Client ID)
app.component.ts
export class AppComponent {
constructor(private oauthService: OAuthService, private apiService: ApiService, private adapterService: AdapterService) {
this.oauthService.configure(authConfig);
this.oauthService.loadDiscoveryDocumentAndLogin();
this.oauthService.setupAutomaticSilentRefresh();
...
我已经克隆并设置了博客文章中提供的示例,并使用相同的 Azure 应用程序(租户和客户端 ID 等)对其进行了配置。 在那里它工作正常,我可以看到它在向 API 的请求中发送我的不记名令牌
Screenshot of request header from request sent from the sample application 我注意到示例应用程序向 api 发送了两个请求,第一个请求提供不记名令牌,第二个请求是简单的 GET 请求。 Two requests in the sample application
同时,我的应用程序仅发送一个请求,并且不包括不记名令牌: Request header from own application without bearer token 虽然上面的屏幕截图返回 200,但这是因为本地运行的后端不检查令牌。但正如您在屏幕截图中看到的那样,令牌没有被传输。 这是在已部署应用程序上运行的请求的另一个屏幕截图。由于设置了更多信息,但令牌仍未发送。 Request header from own application (deployed version) without bearer token
关于问题可能是什么的任何想法?
【问题讨论】:
-
有 2 个请求的事实让我认为您正在执行跨源请求,而第一个请求是一个选项。如果是这种情况,那么您的服务器端应该返回标头
Access-Control-Allow-Credentials:true否则浏览器将不包含不记名令牌。 -
没错。第一个请求是一个选项。但是,此请求仅在示例应用程序中发送。所以我想我需要确保我的应用程序也发送这个请求。谢谢你的提示。不过有一件事。 OPTION 响应标头不包括
Access-Control-Allow-Credentials:true。但是,它确实包含Access-Control-Allow-Headers: authorization这与使 UI 提供 JWT 令牌有关吗? -
当 url 位于与页面不同的域时,浏览器会自动发送 OPTION 请求。为使应用程序能够发送令牌,服务器应使用两个标头
Access-Control-Allow-Credentials: true和Access-Control-Allow-Headers: authorization响应此请求。但是由于您的应用程序只发送一个请求,我想您并没有处于跨源情况,并且您的问题来自其他地方。身份验证流程是否正常工作?您是否被重定向到 Azure AD 身份验证页面,然后返回到您的应用程序? -
就是这样。所以这就解释了差异。前端和后端都在同一个域上。否则身份验证流程工作正常。自动转发到登录页面,然后令牌本身也被传输到前端。唯一失败的部分是将令牌与 api 请求一起发送到后端。
-
登录后,token应该保存在key id_token下的session storage中。你能在会话存储中看到它吗?如果不是这种情况,请确保在 AAD 中您的重定向 uri 注册为单页应用程序而不是 Web 应用程序
标签: angular rest azure-active-directory openid-connect