【发布时间】:2021-07-15 23:19:25
【问题描述】:
我正在关注此处发布的文档 (https://docs.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/oauth?view=azure-devops)。
我在 Azure 中有一个基于 react 的 web 应用和一个基于 powershell 的函数应用。我的函数应用目前正在使用使用我的工作帐户 (AAD) 凭据创建的个人访问令牌,这是不可取的。我的目标是使用 OAuth2 授权我的函数应用代表 webapp 用户对 GIT 存储库进行代码更改。当我按照上面的说明进行操作时,我能够获取看似有效的授权代码、访问令牌和刷新令牌,我从 Azure DevOps 收到以下错误消息:
TF400813:用户 'ffffffff-ffff-ffff-ffff-ffffffffffff' 无权访问此资源。 … 401 - 哦,你没有访问权限。 该请求需要身份验证。 2021 年 4 月 21 日上午 12:04:16 (UTC) ffffffff-ffff-ffff-ffff-ffffffffffff 退出并使用其他帐户登录
我在上面的示例中隐藏了 guid,但是当我调用旧版身份 API (https://docs.microsoft.com/en-us/rest/api/azure/devops/ims/identities/read%20identities?view=azure-devops-rest-6.0) 时,用户 GUID 似乎与我为我的工作帐户找到的 GUID 匹配。 我创建了我的应用程序 (https://app.vsaex.visualstudio.com/app/register),其作用域与用于创建个人访问令牌的作用域相同。我在 dev.azure.com 个人资料中验证了我的应用程序被列为授权 OAuth 应用程序,正如在创建授权请求并收到授权代码后所预期的那样。
上面的错误信息让我很困惑。它说用户(我)无权访问资源,但也说身份验证失败。是哪个?
这与我获取授权/访问令牌的方式有关吗?我是否以某种方式使用了错误的帐户?我的范围错了吗?
问题的再现
这是我注册申请的状态:
My application state:
{
"scopes": "vso.code_full vso.code_status vso.graph_manage vso.identity_manage vso.threads_full vso.tokens",
"tokenUrl": "https://app.vssps.visualstudio.com/oauth2/token",
"state": "foo",
"authCallback": "https://myapp.azurewebsites.net/oauth-callback",
"clientSecret": "S.S.S-S-S",
"authUrl": "https://app.vssps.visualstudio.com/oauth2/authorize",
"appWebsite": "https://myapp.azurewebsites.net/",
"appSecret": "S",
"appId": "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"
}
步骤 1. 授权应用程序。
I invoke the following auth URI from an in-private browser.
I authenticate my work account, and authorize the application for the requested scopes.
I can verify the app is an authorized oauth app in my dev.azure.com profile.
https://app.vssps.visualstudio.com/oauth2/authorize?client_id=FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF&response_type=Assertion&state=foo&scope=vso.code_full%20vso.code_status%20vso.graph_manage%20vso.identity_manage%20vso.threads_full%20vso.tokens&redirect_uri=https://myapp.azurewebsites.net/oauth-callback
I receive an authcode, "A.A.A-A-A-A" (shown decoded/obfuscated below):
{
"typ": "JWT",
"alg": "RS256",
"x5t": "....."
}
{
"cid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
"csi": "ffffffff-ffff-ffff-ffff-ffffffffffff",
"nameid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
"iss": "app.vstoken.visualstudio.com",
"aud": "app.vstoken.visualstudio.com",
"nbf": 1618438026,
"exp": 1776204426
}
步骤 2. 从我的 powershell 函数应用中请求访问令牌和刷新令牌:
I make a rest api call to the token endpoint:
"Uri": "https://app.vssps.visualstudio.com/oauth2/token"
"Method": "POST"
"ContentType": "application/x-www-form-urlencoded"
"Body": "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=S.S.S-S-S&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=A.A.A-A-A-A&redirect_uri=https://myapp.azurewebsites.net/oauth-callback"
…and I get the following JSON response:
Token Response:
{
"access_token": "X.X.X-X-X-X-X-X-X",
"token_type": "jwt-bearer"
"expires_in": 3599,
"refresh_token": "R.R.R-R-R-R",
"scope": "vso.code_full vso.code_status vso.graph_manage vso.identity_manage vso.threads_full vso.tokens vso.authorization_grant"
}
Yielding the following JWT for the access token:
{
"typ": "JWT",
"alg": "RS256",
"x5t": "....."
}
{
"nameid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
"scp": "vso.code_full vso.code_status vso.graph_manage vso.identity_manage vso.threads_full vso.tokens",
"aui": "ffffffff-ffff-ffff-ffff-ffffffffffff",
"appid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
"iss": "app.vstoken.visualstudio.com",
"aud": "app.vstoken.visualstudio.com",
"nbf": 1618963456,
"exp": 1618967056
}
第 3 步。调用 DevOps REST API。
In this case, I am requesting a list of respositories in my org/project:
"Uri": "https://dev.azure.com/myorg/myproj/_apis/git/repositories?api-version=6.0"
"Method": "GET"
"Headers": {"Authorization": "Bearer X.X.X-X-X-X-X-X-X"}
This is where things go wrong. DevOps returns a 401 error indicating that my account is not authorized.
TF400813: The user 'ffffffff-ffff-ffff-ffff-ffffffffffff' is not authorized to access this resource.
如果我在第 3 步中创建了完全相同的 http GET,但我将 PAT 替换为与注册应用程序相同的范围,则调用成功。 PAT 似乎是使用第 1 步中授权的完全相同的配置文件/帐户创建的。
【问题讨论】:
标签: azure-devops oauth-2.0 azure-devops-rest-api