【问题标题】:Angular - Bearer token not sent in request header on API callsAngular - API调用的请求标头中未发送不记名令牌
【发布时间】: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: trueAccess-Control-Allow-Headers: authorization 响应此请求。但是由于您的应用程序只发送一个请求,我想您并没有处于跨源情况,并且您的问题来自其他地方。身份验证流程是否正常工作?您是否被重定向到 Azure AD 身份验证页面,然后返回到您的应用程序?
  • 就是这样。所以这就解释了差异。前端和后端都在同一个域上。否则身份验证流程工作正常。自动转发到登录页面,然后令牌本身也被传输到前端。唯一失败的部分是将令牌与 api 请求一起发送到后端。
  • 登录后,token应该保存在key id_token下的session storage中。你能在会话存储中看到它吗?如果不是这种情况,请确保在 AAD 中您的重定向 uri 注册为单页应用程序而不是 Web 应用程序

标签: angular rest azure-active-directory openid-connect


【解决方案1】:

在这里。 事实证明,问题是由于“X-Frame-Options”响应标头设置为“DENY”而引起的。 如果设置为“DENY”,则此标头会阻止打开不可见的帧。 该实现在身份验证过程中使用 iFrame 进行静默重定向,而这个关键部分被阻止了。

为了解决这个问题,我在后端配置中将其更改为“SAME ORIGIN”

        @Override
        protected void configure(HttpSecurity http) throws Exception {
        ...
        // global security configuration
        http.headers().frameOptions().sameOrigin().
        ...

希望这对将来可能偶然发现此问题的任何人有所帮助, 干杯和感谢那些帮助过的人, 狮子座

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-10
    • 2019-04-11
    • 2013-09-03
    • 1970-01-01
    • 2014-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多