使用cURL通过AzureAd鉴权调用ASP.NET Core Web API

写在前面

为了深刻理解以AzureAD为代表的API鉴权功能,决定使用VisualStudio的WebAPI模板实践一下,最终目标是使用Swagger页面完成鉴权,这部分还在探索中,姑且先将cURL调用的的这部分发布出来。

本篇内容主要参考了微软官方文档,更改了其中一些不符合本地情况的内容。作为个人记录,会改用一些并不标准的表述,敬请见谅。

流程概述

  1. 将微软账号进行Azure认证;(期间需要进行VISA信用卡信息认证,如果不打算长期使用的话可以直接淘宝买一套信息)
  2. 在Azure Active Directory(上称AzureAD,下称AAD)分别注册服务端应用(同Web API)和客户端应用,为服务端应用建立作用域(操作名)的公开API,为客户端申请密码并在客户端获取公开API相应的权限;
  3. 创建VisualStudio(下称VS)的WebAPI模板,用注册好的服务端应用信息配置appsettings.json,并运行;
  4. 通过终端分别获取授权代码、访问令牌,并用访问令牌调用Web API。

在AAD中,我们所说的在API调用中的服务端和客户端是等价的,对于注册的应用,页面中有一个叫做应用程序(客户端)ID的字段,下面全部使用应用ID代替;

指令/URL中有一些字段需要替换,在此篇内容中均用{}包括,替换时请一并替换掉{}

详细流程

注册服务端应用

从Azure主页,点击Azure Active Directory图标进入AAD默认目录,左侧栏>管理>应用注册,点击新注册

使用学校邮箱注册的账号可能存在无权限进入AAD的问题

名称仅作标记,这里取YT-Service受支持的账户类型重定向URL保持默认即可,点击注册

YT-Service左侧栏>管理>公开API界面,点击添加范围

应用程序ID URL保持默认,结构大致为api://{YT-Service_应用ID},点击保存并继续

作用域名称代表调用API时进行的操作,在VS的WebAPI模板中,这一操作为access_as_user谁能同意?选择管理员和用户管理员/用户 同意 显示名称/说明在此实践中不重要,随意填写即可。状态选择已启用。点击添加作用域

注册客户端应用

返回主页,同样地,点击Azure Active Directory图标进入AAD默认目录,左侧栏>管理>应用注册,点击新注册

名称这里取YT-Client受支持的账户类型保持默认即可,重定向URL中,选择平台选择Web,值填入http://localhost,点击注册

YT-Client左侧栏>管理>证书和密码客户端密码一栏点击新客户端密码说明截止期限保持默认即可,点击添加,获得密码的字段一定妥善保管,再次进入此页面时将无法查看;

YT-Client左侧栏>管理>API权限,点击添加权限,选择我的API栏,选择刚才注册的YT-Service,勾选access_as_user,点击添加权限

至此在AAD上面的操作已经全部完成,观察YT-ServiceYT-Client左侧栏>概述中,目录(租户)ID应该相同,下称此字段为用户ID

生成并配置VS .NET Core Web APi模板

启动VS,创建新项目,选择ASP .NET Core Web API模板,项目名称仅作标记,这里取TY-API,点击下一步

框架默认,身份验证类型选择Microsoft标识平台,其余选择默认,点击创建

有三种方式进行模板配置:

  1. 登录刚才注册应用的微软账户,选择租户(一般默认),在拥有的应用程序一栏中选择YT-Service,点击下一步

    均默认即可,点击完成,等待配置结束。

  2. 解决方案资源管理器Connected Services菜单中,右键点击Microsoft标识平台,选择编辑,其余步骤与方法1相同。

  3. 解决方案资源管理器中进入appsettings.json,更改AzureAd的值:

    Instance"https://login.microsoftonline.com/"参考

    Domain的值参考在AAD界面鼠标悬停在右上角头像处的提示栏中字段的值,参考格式为"{xxx}.onmicrosoft.com"

    TenantId"{用户ID}"

    ClientId"{TY-Service_应用ID}"

    CallbackPath保持默认为"/signin-oidc"

    Scopes保持默认为"access_as_user"

    ClientSecret无需配置,保持默认提示值即可;

    ClientCertificates无需配置,保持默认空值即可;

在VS的调试菜单选择开始执行(不调试),浏览器会跳转到Swagger界面,记录此页面的{端口号},此时测试API应该会获得401代码,因为我们并没有进行鉴权。

通过终端使用cURL获得鉴权并调用API

此段的{授权代码}和{访问令牌}可能会很长(1300~和1700~)

在浏览器中替换并访问以下网址:

https://login.microsoftonline.com/{用户ID}/oauth2/v2.0/authorize?client_id={TY-Client_应用ID}&response_type=code&redirect_uri=http://localhost&response_mode=query&scope=api://{TY-Service_应用ID}/{作用域名称}

此处作用域名称为access_as_user

以注册应用的 Azure AD 租户中的用户身份登录。 如有必要,可同意任何访问请求。

浏览器将会重定向到http://localhost/,请观察浏览器的地址栏, URL 格式如下:

http://localhost/?code={授权代码}&session_state={会话状态}

请复制两个参数在接下来的步骤中使用;

在终端中替换并执行以下命令:

curl -X POST https://login.microsoftonline.com/{用户ID}/oauth2/v2.0/token -d "api://{TY-Service_应用ID}/{作用域名称}&client_id={TY-Client_应用ID}&code={授权代码}&session_state={会话状态}&redirect_uri=http://localhost&grant_type=authorization_code&client_secret={TY-Client_应用密码}"

如果输入正确,应会收到类似于以下输出的 JSON 响应:

1
2
3
4
5
6
7
{
"token_type": "Bearer",
"scope": "api://{TY-Service_应用ID}/{作用域名称}",
"expires_in": 5214,
"ext_expires_in": 5214,
"access_token": "{访问令牌}"
}

记下{访问令牌},在终端中替换并执行以下命令:

curl -X GET https://localhost:{端口号}/WeatherForecast -ki -H 'Content-Type: application/json' -H "Authorization: Bearer {访问令牌}" -H 'accept: text/plain'

我们得到了如下结果:

1
2
3
4
5
6
7
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Thu, 06 Jul 2023 13:17:31 GMT
Server: Kestrel
Transfer-Encoding: chunked

[{"date":"2023-07-07","temperatureC":36,"temperatureF":96,"summary":"Cool"},{"date":"2023-07-08","temperatureC":0,"temperatureF":32,"summary":"Cool"},{"date":"2023-07-09","temperatureC":-11,"temperatureF":13,"summary":"Warm"},{"date":"2023-07-10","temperatureC":-10,"temperatureF":15,"summary":"Scorching"},{"date":"2023-07-11","temperatureC":-15,"temperatureF":6,"summary":"Bracing"}]

标志着API调用成功。


使用cURL通过AzureAd鉴权调用ASP.NET Core Web API
https://tanyuu.github.io/2023.07-12/使用cURL通过AzureAd鉴权调用ASP.NET Core Web API/
作者
F Juny
发布于
2023年7月6日
许可协议