【问题标题】:Azure AD OAuth client credentials grant flow with Web API AuthorizeAttribute RolesAzure AD OAuth 客户端凭据授予流与 Web API AuthorizeAttribute 角色
【发布时间】:2019-12-15 06:38:43
【问题描述】:

给定

  • 我们有一个 .NET Web API 服务。
  • 它使用AuthorizeAttributeRoles 保护对控制器和操作的访问。例如:
[Authorize(Roles = "Reader,Requester,Editor,Approver,Administrator")]
  • 此应用程序在 Azure Active Directory 中有一个应用程序注册
  • 它使用 OAuth 进行用户模拟,并且用户正在正确进行身份验证。有很多教程可以帮助您了解这一点。

意图

  • 我们希望有一个无人参与的计划进程(脚本)在 Web API 上调用 REST 调用。
  • 无人参与进程的标识在 Azure Active Directory 中不可用。

    在我的特定场景中,这是因为我们没有将大量本地 AD 服务帐户同步到 AAD,并且此脚本将从本地服务主体身份运行。

  • 我们希望使用AuthorizeAttribute 来控制我们的脚本对 Web API 中的控制器/操作的访问。

我怎样才能做到这一点?

【问题讨论】:

    标签: asp.net-web-api oauth-2.0 azure-active-directory asp.net-core-webapi


    【解决方案1】:

    方法

    其中一个限制是无人参与进程的用户身份将不存在于 Azure Active Directory 中;所以我们将在这个场景中使用OAuth 2.0 client credentials grant flow

    第 1 步:收集信息

    首先,确定以下信息:

    1. 客户 ID
    2. 租户 ID
    3. 授权网址
    4. 资源网址
    5. 客户端密码

    如果您已经让 OAuth 为用户和角色工作,那么您可能已经拥有其中的大部分。如果没有,这里是它们的位置以及在哪里可以找到它们。

    1a:查找客户端 ID

    客户端 ID 是一个 GUID,是应用程序在 Azure Active Directory 中的 ID。 不是对象 ID(不同)。

    Azure 门户Azure Active Directory > 应用注册 > [您的应用] > 概述刀片 > 应用程序(客户端)ID 字段。

    PowerShell,来自登录的上下文:

    $(Get-AzADApplication -DisplayName "[your app name]").ApplicationId.Guid
    

    1b:查找租户 ID

    Azure 租户 ID 是一个 GUID。

    Azure 门户Azure Active Directory > 应用注册 > [您的应用] > 概述刀片 > 目录(租户)ID 字段。

    PowerShell,来自登录的上下文:

    $(Get-AzContext).Tenant.Id
    

    Azure CLI,来自登录的上下文:

    az account show --query 'tenantId' -o tsv
    

    1c:查找权威网址

    Authority Url 是 OAuth 授权服务器的 URL。它看起来像这样:https://login.microsoftonline.com/[your-tenant-id]/oauth2/v2.0/token

    Azure 门户Azure Active Directory > 应用注册 > [您的应用] > 端点 按钮 > OAuth 2.0 令牌端点 (v2) 字段。

    1d:查找资源 URL

    Resource Url 是 Web API 服务的 URL。大概是这样的:https://[yourdomain].onmicrosoft.com/[guid]

    Azure 门户Azure Active Directory > 应用注册 > [您的应用] > 公开 API 刀片> 应用程序 ID URI 字段。

    它也位于identifierUris 字段的应用程序清单中。 Azure 门户Azure Active Directory > 应用注册 > [您的应用] > 清单

    清单属性示例:

    "identifierUris": [
        "https://[yourdomain].onmicrosoft.com/[guid]"
    ]
    

    PowerShell,来自登录的上下文:

    $(Get-AzADApplication -ApplicationId [ClientId]).IdentifierUris
    

    Azure CLI,来自登录的上下文:

    az ad app show --id [ClientId] --query 'identifierUris' -o tsv
    

    1e:创建客户端密码

    客户端密码可以是客户端密码(密钥/密码)或证书。以下是创建客户端密码的方法。

    Azure 门户

    1. 转到 Azure Active Directory > 应用注册 > [您的应用] > 证书和机密 刀片 > 客户端机密 em> 部分。
    2. 新建客户端密码按钮并完成此过程。
    3. 复制键值;这是客户的秘密。不要丢失它。

    PowerShell:使用New-AzADAppCredential cmdlet。

    步骤 2:配置 Azure Active Directory 应用程序

    由于您使用AuthorizeAttribute 角色来控制访问,因此您必须将应用程序添加到这些角色中的至少一个。角色在 应用程序清单 中的 appRoles 属性下定义。

    2a:创​​建应用程序可以属于的角色

    每个角色都有一个allowedMemberTypes 属性。如果您已经为用户配置了这个应用程序,那么您已经有了这样的东西:

    "allowedMemberTypes": [
        "User"
    ],
    

    要允许将您的应用程序添加到角色,请像这样修改它:

    "allowedMemberTypes": [
        "User",
        "Application"
    ],
    

    或者,您可以拥有一个只允许应用程序的角色。

    "allowedMemberTypes": [
        "Application"
    ],
    

    2b:将应用程序添加到其角色

    既然有应用程序可以属于的角色,您必须将应用程序添加到这些角色中。

    Azure 门户Azure Active Directory > 应用注册 > [您的应用] > API 权限 刀片。

    1. 添加权限按钮。
    2. 选择我的组织使用的API选项卡。
    3. 查找并选择您的应用程序。
    4. 应用程序权限框。
    5. 为此应用程序选择权限(角色)。
    6. 最后,按下添加权限按钮。

    2c:授予管理员同意

    如果这些角色需要管理员同意,那么您现在需要授予管理员同意。

    Azure 门户Azure Active Directory > 应用注册 > [您的应用] > API 权限 刀片 > 同意部分。按为 [您的组织] 授予管理员同意 按钮,然后确认

    如果您没有执行此操作的权限,请寻找具有 应用程序管理员 角色的人员或具有类似权限的其他人员为您执行此操作。

    第 3 步:验证

    此时,您应该能够使用 OAuth 2.0 客户端凭据流来获取访问令牌,将其作为不记名令牌与您对 Web API 服务的请求一起呈现,然后成功。

    如果您想使用 Postman 或类似工具进行验证,请使用 this guide 创建请求。

    当您拿到一个令牌时,您可以使用此工具检查其内容:https://jwt.io/ 验证令牌中是否有 roles 属性,并且它是否填充了您在之前分配的角色一步。

    例如:

    {
        …
      "azpacr": "1",
      "roles": [
        "Approver",
        "Reader"
      ],
      "ver": "2.0"
        …
    }
    

    这里是一个 PowerShell 脚本,展示了如何使用 ADAL.PS 模块执行此操作:

    Import-Module ADAL.PS
    $tenantId = "[tenant id]"
    $authority = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/authorize"
    $resourceUrl = "[resource url]"
    $clientId = "[client id]"
    $secret = ConvertTo-SecureString -String [client secret] -AsPlainText -Force
    $response = Get-ADALToken -Authority $authority -Resource $resourceUrl -ClientId $clientId -ClientSecret $secret
    $token = $response.AccessToken
    $response
    $restResponse = Invoke-RestMethod -Method Get -Uri "[your web api uri]" -ContentType "application/json; charset=utf-8" -Headers @{ Authorization = "Bearer $token" } -Verbose -Debug
    $restResponse
    

    第 4 步:保护您的秘密

    现在,您在无人看管的脚本或工作中掌握了这个秘密。这可能不是一个好主意,所以以某种方式确保安全。你如何做到这一点超出了这个答案的范围。

    【讨论】:

      猜你喜欢
      • 2019-12-03
      • 1970-01-01
      • 1970-01-01
      • 2021-04-10
      • 2019-06-16
      • 2017-03-11
      • 1970-01-01
      • 2018-02-08
      • 2020-02-28
      相关资源
      最近更新 更多