bra*_*buz 6 curl azure azure-active-directory .net-core azure-ad-msal
我们有一个 .net core 应用程序,它使用 Azure AD 进行身份验证 (MSAL/v2.0)。我们希望 Linux 应用程序能够从第一个应用程序访问 API。第二个应用程序没有用户上下文,并且将像curl 脚本一样进行交互。
通过阅读文档,我认为我应该使用 azure ad 注册第二个应用程序。我可以获得将目标应用程序作为受众的 JWT 令牌,但无法访问 api。我们已经能够使用从登录用户捕获的访问令牌从脚本访问(真实)api。
我创建了一个测试环境来寻找解决方案。
创建了一个由azure ad验证的.net core项目。它从我的工作站本地运行,未部署到天蓝色。Azure 身份验证适用于交互式用户。
注册了第二个应用程序并为其创建了一个秘密。
第一个应用程序配置了 id 和访问令牌以进行隐式授予,但未将其设置为公共客户端。
我在清单中定义了一个 approle“access_as_application”。
在“公开 API”下,我创建了一个范围“api”,并将另一个应用程序添加为授权客户端应用程序。
在 API 权限下,我添加了一个权限,选择了应用程序权限并检查了我之前创建的 approle。
我可以运行一个curl脚本并检索一个不记名令牌,该令牌在解码时会显示与我的应用程序匹配的受众。当我在curl 脚本中使用该令牌时,它会被重定向以登录。
显现:
{
"id": "33b*******************************",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": null,
"appId": "3d8*******************************",
"appRoles": [
{
"allowedMemberTypes": [
"Application"
],
"description": "Access webapp as an application.",
"displayName": "access_as_application",
"id": "ff5ea9b2*******************************",",
"isEnabled": true,
"lang": null,
"origin": "Application",
"value": "access_as_application"
}
],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2019-10-29T16:49:37Z",
"groupMembershipClaims": null,
"identifierUris": [
"api://3d8*******************************"
],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": "https://localhost:44321/signout-callback-oidc",
"name": "WebApp",
"oauth2AllowIdTokenImplicitFlow": true,
"oauth2AllowImplicitFlow": true,
"oauth2Permissions": [
{
"adminConsentDescription": "consent for api",
"adminConsentDisplayName": "consent for api",
"id": "a4b2*******************************",",
"isEnabled": true,
"lang": null,
"origin": "Application",
"type": "Admin",
"userConsentDescription": null,
"userConsentDisplayName": null,
"value": "api"
}
],
"oauth2RequirePostResponse": false,
"optionalClaims": null,
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [
{
"customKeyIdentifier": null,
"endDate": "2299-12-31T05:00:00Z",
"keyId": "e03c4*******************************",",
"startDate": "2019-10-31T20:05:42.56Z",
"value": null,
"createdOn": "2019-10-31T20:05:42.7555795Z",
"hint": "00_",
"displayName": "webappsecret"
}
],
"preAuthorizedApplications": [
{
"appId": "a4b*******************************",
"permissionIds": [
"23b*******************************"
]
},
{
"appId": "3d8*******************************",
"permissionIds": [
"23b*******************************"
]
}
],
"publisherDomain": "brainbuzgmail.onmicrosoft.com",
"replyUrlsWithType": [
{
"url": "https://localhost:44321/signin-oidc",
"type": "Web"
},
{
"url": "https://localhost:44321/",
"type": "Web"
}
],
"requiredResourceAccess": [
{
"resourceAppId": "3d8*******************************",
"resourceAccess": [
{
"id": "23b*******************************",
"type": "Scope"
},
{
"id": "ff5ea*******************************",",
"type": "Role"
}
]
},
{
"resourceAppId": "a4b*******************************",
"resourceAccess": [
{
"id": "a37a*******************************",",
"type": "Scope"
},
{
"id": "ccf78*******************************",",
"type": "Role"
}
]
},
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "e1fe*******************************",",
"type": "Scope"
}
]
}
],
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADMyOrg",
"tags": [],
"tokenEncryptionKeyId": null
}
Run Code Online (Sandbox Code Playgroud)
变量 $ 在环境中设置。令牌从成功的请求中捕获并设置为 $TOKEN。由于本地应用程序使用自签名证书,因此在curl中使用了-k不安全标志。
curl -X POST -d "grant_type=client_credentials&client_id=$CLIENTID&client_secret=$SECRET&resource=$SCOPE" https://login.microsoftonline.com/$TENANT/oauth2/token
curl -k 'https://localhost:44321/api/' \
-H 'Accept: application/json' \
-H "Authorization: Bearer $TOKEN" \
-H 'Sec-Fetch-Mode: cors' -H 'Content-Type: application/json' --compressed
Run Code Online (Sandbox Code Playgroud)
部分响应重定向到登录页面,看起来客户端被要求获取 id 令牌,即使它具有有效的访问令牌:
< HTTP/2 302
< location: https://login.microsoftonline.com/****/oauth2/v2.0/authorize?client_id=***&redirect_uri=https%3A%2F%2Flocalhost%3A44321%2Fsignin-oidc&response_type=id_token
Run Code Online (Sandbox Code Playgroud)
如果您只想让 Linux 应用程序调用受 Azure AD 保护的 .net core 应用程序的 API,这是服务调用流程的服务,无需重定向到/authorize端点,因为通常此端点是用户的步骤之一登录。
根据您的描述,您已成功获取访问令牌,您可以在 API 请求中使用此令牌作为 Authorization Bearer header 直接调用您的 .net core 应用程序。
TodoListService该演示的 peoject是一个示例 API 端演示,将对您有所帮助。在您的情况下,您应该做一些修改以使服务到服务调用工作。
Controllers/TodoListController.cs1.将其中的内容替换TodoListService 为以下代码:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Identity.Web.Resource;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using TodoListService.Models;
namespace TodoListService.Controllers
{
[Authorize]
[Route("api/[controller]")]
public class TodoListController : Controller
{
static readonly ConcurrentBag<TodoItem> TodoStore = new ConcurrentBag<TodoItem>();
/// <summary>
/// The Web API will only accept tokens 1) for users, and
/// 2) having the access_as_user scope for this API
/// </summary>
static readonly string[] scopeRequiredByApi = new string[] { "access_as_application" };
// GET: api/values
[HttpGet]
public IEnumerable<TodoItem> Get()
{
// HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
string owner = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
return TodoStore.Where(t => t.Owner == owner).ToList();
}
// POST api/values
[HttpPost]
public void Post([FromBody]TodoItem todo)
{
//check roles claim in token start
Claim scopeClaim = HttpContext.User?.FindFirst("http://schemas.microsoft.com/ws/2008/06/identity/claims/role");
if (scopeClaim == null || !scopeClaim.Value.Split(' ').Intersect(scopeRequiredByApi).Any())
{
HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
string message = $"The 'roles' claim does not contain scopes '{string.Join(",", scopeRequiredByApi)}' or was not found";
throw new HttpRequestException(message);
}
//check roles claim end
string owner = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
TodoStore.Add(new TodoItem { Owner = owner, Title = "test!!" });
}
}
}
Run Code Online (Sandbox Code Playgroud)
在项目WebApiServiceCollectionExtensions.cs的Microsoft.Identity.Web第 80 行中,替换为以下代码以确保检查您的角色声明:
&& !context.Principal.Claims.Any(y => y.Type == " http://schemas.microsoft.com/ws/2008/06/identity/claims/role "))
希望能帮助到你 。
| 归档时间: |
|
| 查看次数: |
13000 次 |
| 最近记录: |