在无人值守程序(服务)中调用Microsoft Graph
我在此前用了几篇文章分别介绍了在桌面应用程序(控制台),Web应用程序(ASP.NET MVC),以及PowerSehll脚本中如何访问Microsoft Graph,今天这一篇要继续讲一个场景:在无人值守程序中访问Microsoft Graph。那么什么是无人值守程序呢?通常我们将此类程序定义为不需要(不允许)用户进行干预,一般用来在后台自动化运行的程序。在英文文档中,我们将其称之为daemon application,广义上说,也包括了服务这种特殊的应用程序。
无人值守程序与Microsoft Graph的集成,要遵守一般的流程,但也有自己的一些特点,总结起来有如下的步骤
- 注册应用程序
- 配置应用程序权限
- 获得管理员同意
- 获得访问令牌
注册应用程序
针对Azure AD的不同版本,注册应用程序的过程我此前已经有专门的文章介绍了,请参考
- 注册Azure AD 2.0应用程序(支持国际版,支持Office 365账号以及个人账号登录,功能可能有所缺失,但这个是以后的方向),
- 注册Azure AD 1.0应用程序(支持国际版和中国版,仅支持Office 365账号登录,功能最全),文章链接1,
本文先演示注册Azure AD 2.0应用,具体的步骤就不做截图了,唯一要提醒的是
- 应用程序类型设置为Web
- ReplyUrl可以设置为一个通用的地址,我喜欢设置为 https://developer.microsoft.com/en-us/graph/
这是无人值守应用程序注册的时候,要特别注意的。由于该程序是没有用户参与的,所以它无法使用某个特定用户的身份做什么事情,而是使用一个统一的身份,该身份我们称为Application Identity,而相应的,我们要为程序申请的权限也是所谓的“Application Permissions”,而不是“Delegated Permissions”。
本例中,我想为应用程序申请两个权限:一个是用来获取所有用户信息的,另外一个是用来代替任何用户发送邮件。
获得管理员同意
由于无人值守的程序其实是自动化运行的,无需用户进行参与进行授权,而它进行的操作,却又有可能要代表用户的行为。所以通常这些权限都需要得到真正的Office 365 Tenant管理员同意才能真正生效。
要获得管理员同意,你可以将下面的这个链接发送给用户的Office 365 Tenant管理员
管理员需要在下面这样的界面中对应用程序所申请的权限进行确认
正常情况下,完成授权后页面会被导航到下面的地址,请确认admin_consent的值为true,并记录下来tenant的值。这个表示用户的Office 365 Tenant的编号,后面我们需要用到。
无人值守应用程序,不需要用户参与进行授权,所以它获取令牌的方式也略有不同。你可以在应用程序里面使用下面的方式发起一个POST请求来获得访问令牌(Access Token)。
正常情况下,这个请求将返回如下的结果
请复制得到的这个access_token的值。请注意,默认情况下,这个access_token会在1个小时后过期。至于怎么刷新token,我会在后续文章中介绍。
使用令牌访问资源
有了这个access_token,应用程序就可以尽情地访问Microsoft Graph的资源了。例如,通过下面的请求可以获取到对应的Office 365 Tenant中的所有用户信息。
上面演示的时候,我用了Fiddler这个小工具来模拟发起请求,并且快速地查看到结果。下面用一个简单的应用程序,来实现代码逻辑,给大家参考。
使用Azure AD 1.0
上面的例子很简单易懂,但如果我们使用的是Azure AD 1.0(国际版同时支持1.0和2.0,中国版则只支持1.0),则注册应用程序和使用Microsoft Graph的方式会略有不同。
请参考之前的两篇文章了解如何在Azure 1.0的环境中注册应用程序
- 国际版
- 中国版 链接
和上面提到的一样,有两点需要注意
- 应用程序类型设置为Web
- ReplyUrl可以设置为一个通用的地址,我喜欢设置为
和上面提到的一样,这里需要申请Application permission,而不是delegation permission
这里需要注意修改Manifest文件(先下载,然后编辑,最后上传),允许隐式授权
和Azure AD 2.0明显不同的是,在1.0中,获取管理员同意,需要使用如下的链接
此处的关键在于有一个prompt=admin_consent的参数,正常情况下,管理员进行授权确认后会跳转到下面这样的地址,里面已经包含了一个access_token
如果我们将代码再演化一下,使用Microsoft.Graph进行访问的话,会更加轻松惬意,因为可以完全基于强类型的方式进行操作