首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >带有Azure AD访问令牌的Azure函数

带有Azure AD访问令牌的Azure函数
EN

Stack Overflow用户
提问于 2021-03-29 20:15:49
回答 2查看 972关注 0票数 2

我正在构建一组定制的Azure函数(Java),以便由iOS和安卓本地客户端使用本质上和Oauth2身份验证策略访问。

我能够从https://login.microsoftonline.com/XXXXX-XXXXXXXXX/oauth2/v2.0/token成功地获得一个承载访问令牌,但是当我将这个令牌呈现给Azure函数并尝试用代码验证它时,我会收到以下错误。在验证承载令牌时,我正在执行与这里提供的示例类似的操作:https://dev.to/425show/secure-apis-with-azure-functions-java-azure-ad-and-ms-graph-49p1

AADSTS50013:断言签名验证失败。[原因-提供的签名值与预期的签名值不匹配。客户端使用的密钥的拇指指纹:‘

Microsoft的文档很难用于应该是这样的标准用例。任何帮助都将不胜感激。

EN

回答 2

Stack Overflow用户

发布于 2021-04-02 08:19:09

我以前也回答过几个类似的问题。根本原因是断言中使用的访问令牌是用于Microsoft 资源还是web 资源。您可以通过解析令牌来查看aud声明来确定令牌的发行者。

如果使用此访问令牌调用Microsoft,则只需将scope设置为:https://graph.microsoft.com/.default

如果使用访问令牌调用web (这是在Azure门户中公开的api ),则需要将scope设置为:api://{your api application client id}/{scope name}

请注意:您只能在范围内放置一种类型的api资源。

票数 1
EN

Stack Overflow用户

发布于 2021-10-11 09:05:44

我花了相当长的时间试图解决一个类似的问题,虽然一些答案指向了解决方案,但我所看到的没有一个能提供对根本原因的深入了解。所以我想我可以提供一些我自己的发现。

下面是一个提取访问令牌的示例Spring控制器:

代码语言:javascript
运行
复制
package com.matthewcasperson.onenote.controllers;

import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class Test {
  @Autowired
  OAuth2AuthorizedClientRepository clientRepository;

  @GetMapping("/test")
  public String test(HttpServletRequest request) {
    final OAuth2AuthenticationToken oauth2Token = (OAuth2AuthenticationToken) SecurityContextHolder
        .getContext()
        .getAuthentication();

    final OAuth2AuthorizedClient client = clientRepository
        .loadAuthorizedClient(oauth2Token.getAuthorizedClientRegistrationId(), oauth2Token, request);

    final String accessToken = client.getAccessToken().getTokenValue();

    System.out.println(accessToken);

    return "test";
  }
}

这个Spring应用程序是配置为web应用程序,具有以下application.yml文件:

代码语言:javascript
运行
复制
azure:
  activedirectory:
    tenant-id: ${TENANT_ID}
    client-id: ${CLIENT_ID}
    client-secret: ${CLIENT_SECRET}

控制器打印的令牌解码如下:

代码语言:javascript
运行
复制
{
  "typ": "JWT",
  "nonce": "nx2pG8jshz2m6AY8eBafUJDXVgJNjjg526wpwsVRVoU",
  "alg": "RS256",
  "x5t": "l3sQ-50cCH4xBVZLHTGwnSR7680",
  "kid": "l3sQ-50cCH4xBVZLHTGwnSR7680"
}.{
  "aud": "https://graph.microsoft.com",
  "iss": "https://sts.windows.net/2ed832a8-cd8c-4f7d-89b3-935447e260c8/",
  "iat": 1633941558,
  "nbf": 1633941558,
  "exp": 1633945458,
  "acct": 0,
  "acr": "1",
  "aio": "AUQAu/8TAAAAPyU5VrhiE9R+skcJpwWKTVMqg/DfvQs1i0CQFYQgUAAHS5uZI72LdEjZxRn7VjMNfaq8gL1CbRcoD1PYVjWPfQ==",
  "amr": [
    "pwd",
    "mfa"
  ],
  "app_displayname": "OneNote",
  "appid": "abfb7030-ff37-48cd-8bd7-1bf5ec0777db",
  "appidacr": "1",
  "family_name": "Casperson",
  "given_name": "Matthew",
  "idtyp": "user",
  "ipaddr": "45.67.96.131",
  "name": "Matthew Casperson",
  "oid": "4c037c2f-4b2f-46c1-a25f-d214e2396d47",
  "platf": "3",
  "puid": "1003200188788F6F",
  "rh": "0.AUEAqDLYLozNfU-Js5NUR-JgyDBw-6s3_81Ii9cb9ewHd9tBACU.",
  "scp": "openid profile User.Read email",
  "signin_state": [
    "kmsi"
  ],
  "sub": "56Tq2KFJPnykNSAwOCFPSjq1s9kqybnOmJ99Nfnn53M",
  "tenant_region_scope": "OC",
  "tid": "2ed832a8-cd8c-4f7d-89b3-935447e260c8",
  "unique_name": "matthewcasperson@matthewcasperson.onmicrosoft.com",
  "upn": "matthewcasperson@matthewcasperson.onmicrosoft.com",
  "uti": "WWzRGjCqAEWNwcH4le9TAQ",
  "ver": "1.0",
  "wids": [
    "62e90394-69f5-4237-9190-012177145e10",
    "b79fbf4d-3ef9-4689-8143-76b194e85509"
  ],
  "xms_st": {
    "sub": "gnpeDIbUpAnTYqfXYe3lNOwC2_MV5UvEIm3zvZK6LVc"
  },
  "xms_tcdt": 1632346078
}.[Signature]

注意aud of https://graph.microsoft.com (我还看到了一个aud of 00000003-0000-0000-c000-000000000000,它是Microsoft的客户端id )。

尽管它是一个JWT,因此我们可以检查它,但是这个特定的令牌应该是被视为不透明

您不应该查看访问令牌,因为访问令牌是针对资源的(在您的情况下是图),而不是客户端(您的应用程序)。在这种情况下,您可以只使用id令牌中的声明。

如果您尝试将此JWT用于生成OBO令牌,您将收到与OP类似的错误:

代码语言:javascript
运行
复制
{
    "error": "invalid_grant",
    "error_description": "AADSTS50013: Assertion failed signature validation. [Reason - The provided signature value did not match the expected signature value., Thumbprint of key used by client: '977B10FB9D1C087E3105564B1D31B09D247BEBCD', Found key 'Start=02/07/2021 17:00:39, End=02/06/2026 17:00:39'].\r\nTrace ID: 384637e2-0853-4a10-b42a-a7cb53aa8500\r\nCorrelation ID: 1e9a639e-45e4-48e4-99b6-028ce43fe815\r\nTimestamp: 2021-10-11 08:54:13Z",
    "error_codes": [
        50013
    ],
    "timestamp": "2021-10-11 08:54:13Z",
    "trace_id": "384637e2-0853-4a10-b42a-a7cb53aa8500",
    "correlation_id": "1e9a639e-45e4-48e4-99b6-028ce43fe815",
    "error_uri": "https://login.microsoftonline.com/error?code=50013"
}

我认为这里发生的事情是,这个JWT除了获得一个/userinfo令牌之外,并没有做任何其他事情,而这个令牌又包含了应用程序访问其代码所需的角色。尽管访问令牌是一个JWT,但它被看作是一个不透明的令牌,不能在其他流(如OBO )中使用。

您可以创建一个需要在Azure AD应用程序上定义的作用域的自授权客户端。这个作用域通常只是一些没有特殊意义的虚拟值(我称我的作用域为default,但任何作用域名称都可以):

代码语言:javascript
运行
复制
azure:
  activedirectory:
    tenant-id: ${TENANT_ID}
    client-id: ${CLIENT_ID}
    client-secret: ${CLIENT_SECRET}
    authorization-clients:
      api:
        scopes:
          - api://${CLIENT_ID}/default

这个客户端可以这样使用:

代码语言:javascript
运行
复制
  @GetMapping("/test2")
  public String test2(@RegisteredOAuth2AuthorizedClient("api") OAuth2AuthorizedClient api) {

    final String accessToken = api.getAccessToken().getTokenValue();

    System.out.println(accessToken);

    return "test";
  }

为此授权客户端创建的访问令牌解码如下所示:

代码语言:javascript
运行
复制
{
  "typ": "JWT",
  "alg": "RS256",
  "x5t": "l3sQ-50cCH4xBVZLHTGwnSR7680",
  "kid": "l3sQ-50cCH4xBVZLHTGwnSR7680"
}.{
  "aud": "api://abfb7030-ff37-48cd-8bd7-1bf5ec0777db",
  "iss": "https://sts.windows.net/2ed832a8-cd8c-4f7d-89b3-935447e260c8/",
  "iat": 1633942486,
  "nbf": 1633942486,
  "exp": 1633946386,
  "acr": "1",
  "aio": "AVQAq/8TAAAAjlqywvUGKhdO5xKGTXyMxif6+n+PW+HQfqQUE2rz5vXQHmeqAWCJuWbxQEZJrn5FQwxPibQ/FZ8ZjsvlMWbscs8bG7AiCNwHepHg9HqCYTo=",
  "amr": [
    "pwd",
    "mfa"
  ],
  "appid": "abfb7030-ff37-48cd-8bd7-1bf5ec0777db",
  "appidacr": "1",
  "family_name": "Casperson",
  "given_name": "Matthew",
  "ipaddr": "45.67.96.131",
  "name": "Matthew Casperson",
  "oid": "4c037c2f-4b2f-46c1-a25f-d214e2396d47",
  "rh": "0.AUEAqDLYLozNfU-Js5NUR-JgyDBw-6s3_81Ii9cb9ewHd9tBACU.",
  "scp": "default",
  "sub": "gnpeDIbUpAnTYqfXYe3lNOwC2_MV5UvEIm3zvZK6LVc",
  "tid": "2ed832a8-cd8c-4f7d-89b3-935447e260c8",
  "unique_name": "matthewcasperson@matthewcasperson.onmicrosoft.com",
  "upn": "matthewcasperson@matthewcasperson.onmicrosoft.com",
  "uti": "AqpGPbtGNkayP_368gJ1AQ",
  "ver": "1.0"
}.[Signature]

注意,aud字段是Azure应用程序,而不是Microsoft。我相信这个标记意味着透明,这意味着我们可以将它用于其他流,如OBO。实际上,在使用它创建OBO令牌时,此令牌可以正常工作。

web应用程序使用OBO流没有多大意义,因为作为授权代码流的一部分,web应用程序只需使用任何所需的用户权限就可以直接请求批准访问令牌。所以上面的exmaple有点麻烦,但是突出了您自动获得的不透明令牌与通过自授权客户端获得的透明令牌之间的区别。

透明的JWT是您发送到OAuth资源服务器的内容,资源服务器生成自己的OBO令牌是有意义的。

为了进一步阅读,这个职位有一个用Azure生成令牌的详细演练。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66861040

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档