如何在后端 API 中验证 AzureAD accessToken

Posted

技术标签:

【中文标题】如何在后端 API 中验证 AzureAD accessToken【英文标题】:How to validate AzureAD accessToken in the backend API 【发布时间】:2021-06-17 14:11:30 【问题描述】:

我只是想知道如何在我的情况下验证后端 API 中的天蓝色广告访问令牌,即 Django rest 框架。

假设我有一个单页应用程序或一个本机应用程序和一个完全独立的后端 API(django rest 框架)。在我的情况下,如果我的单页应用程序/原生应用程序想要从后端 API 访问某些数据,并且为了访问 API,用户应该登录后端 API。

所以我的方法是利用 MSAL 库从 SPA/本机应用程序获取访问令牌,然后在获取令牌后,将该令牌传递给后端 API,对其进行验证,从图形 API 获取用户信息。如果数据库中存在用户,则登录用户并传递所需的信息。如果用户信息不存在,则创建用户,登录并从 API 传递信息。

所以我的问题是,当我将访问令牌传递给我的后端 API 时,我如何验证用户/SPA/本机应用程序传递给后端 API 的令牌是否是有效令牌?

是否只是我们需要使用用户/SPA/native 传递的 accessToken 对图形 API 端点进行 API 调用,如果它能够使用 accessToken 获取用户数据,那么令牌是有效的,或者如果它失败了,那么accessToken 无效。

这是验证令牌的一般方法还是有更好的方法?请帮忙

【问题讨论】:

这可能会有所帮助:docs.microsoft.com/en-us/azure/databricks/dev-tools/api/latest/… 它所做的是解码令牌并针对我的天蓝色 AD 配置验证 audiss 键值。请参阅this,了解有关可以验证的声明的更多详细信息。 【参考方案1】:

先生,您好,我想在这里分享一些我的想法,我知道这不是解决方案,但评论太长了。

我创建了一个SPA,之前使用msal.js让用户登录并生成访问令牌来调用graph api,这里你必须知道,当你生成访问令牌时,你需要设置目标api的范围,对于例如,您想调用“graph.microsoft.com/v1.0/me”,您需要一个范围为“User.Read,User.ReadWrite”的令牌,并且您还需要将委派的 api 权限添加到 azure 应用程序。

所以作为你自己后端程序的自定义api。我创建了一个springboot api,如果我调用'localhost:8080/hello',它将返回'hello world',如果我想让我的api受天蓝色广告保护,我需要添加一个过滤器来验证所有请求是否具有有效的访问令牌.所以我需要找到一个jwt库来解码请求头中的令牌并检查它是否有令牌,令牌是否已过期以及令牌是否具有正确的范围。那么在这里,哪个范围是正确的范围?由你exposed in azure ad的api决定。您可以设置名为“AA_Custom_Impression”的范围,然后可以将此委托 api 权限添加到客户端 azure 广告应用程序,然后该应用程序生成一个范围为“AA_Custom_Impression”的访问令牌。在调用请求中附加 Bearer 令牌后,将被后端代码过滤。

我不知道python,所以我只能推荐你this sample,你可以试试,它是provided by microsoft。

【讨论】:

你好 Tiny-wa。感谢您的回复。我想我的问题并没有解释一切。我不希望我的后端 API(Django Rest Framework)受 azure AD 保护,因为它会有自己的自定义授权。基本上我想做的是一种你可以说的注册过程。当用户通过 SPA/native 应用程序登录时,msal.js 将生成一个访问令牌,并且该访问令牌将传递给后端 API,以检查该用户是否有权访问某个端点。因此,当用户第一次这样做时,数据库中不会出现用户记录。 所以我想做的是。如果用户记录不存在,则使用本机/SPA 已通过后端 API 的访问令牌进行图形 API 调用,例如:'graph.microsoft.com/v1.0/me'。使用该后端 API 将获取用户信息,它将创建用户记录,登录创建的用户,并使用后端 API 生成的 JWT 令牌返回用户。因此,现在 native/SPA 将接收该 JWT 令牌,并将使用后端 API 提供的该 JWT 令牌调用后端 API。例如'localhost:8080/' 所以现在后端 API 将知道 JWT 令牌(由后端 API 生成)是有效的,它将返回适当的数据。在我们的示例中,它将返回 hello。所以我的问题是因为我们正在将 Graph API 访问令牌传递给后端 API。验证它的最佳方法是什么? 是的,先生,感谢您的回复,我想我能找到您。所以首先,我想我需要告诉你,jwt 令牌(我们上面说访问令牌)可以解码为 json 对象,json 对象包含很多 cliams,你可以refer to this doc 了解细节并确定如何你判断令牌是否有效。最后,我认为您的问题可以转换为找到decode library 来解密令牌。【参考方案2】:

我已经解决了类似的问题。我没有找到如何直接验证访问令牌,但您可以在后端使用您在 MSAL 客户端获得的令牌调用图形 API。

Node.js 示例:

class Microsoft 

  get baseUrl() 
    return 'https://graph.microsoft.com/v1.0'
  

  async getUserProfile(accessToken) 
    const response = await got(`$this.baseUrl/me`, 
      headers: 
        'x-li-format': 'json',
        Authorization: `Bearer $accessToken`,
      ,
      json: true,
    )
    return response.body
  
  
  // `acessToken` - passed from client
  async authorize(accessToken) 
    try 
      const userProfile = await this.getUserProfile(accessToken)
      const email = userProfile.userPrincipalName

      // Note: not every MS account has email, so additional validation may be required
      const user = await db.users.findOne( email )

      if (user) 
        // login logic
       else 
        // create user logic
      
     catch (error) 
      // If request to graph API fails we know that token wrong or not enough permissions. `error` object may be additionally parsed to get relevant error message. See https://docs.microsoft.com/en-us/graph/errors 
      throw new Error('401 (Unauthorized)')
    
  

【讨论】:

以上是关于如何在后端 API 中验证 AzureAD accessToken的主要内容,如果未能解决你的问题,请参考以下文章

如何使 AzureAD 和自定义 JWT 令牌在 Web API 中并行工作?

如何在 python 中验证来自 AzureAD 的 JWT?

如何将 AzureAD 和 AzureADBearer 添加到 asp.net core 2.2 web api

如何在 api 网关架构中获取 JWT 令牌

如何验证 Azure AD 访问的 appid

laravel 5.4 中的 API 验证