我的任务是实现这一目标:Outlook 插件以及非 Microsoft API 的 OIDC 身份验证。 任务窗格将用 Angular 编写,我已经使用
angular-auth-oidc-client
作为其他项目的客户端 OIDC 身份验证包,所以我想我也会在这里使用它。
我已经能够加载 Outlook 加载项,它使用 Office.UI.displayDialogAsync
打开对话框窗口供用户登录,并使用 Office.UI.messageParent
将访问令牌发送到任务窗格。
但是然后呢?当我在任务窗格中获得访问令牌后,我该如何处理它?我必须手动存储并跟踪过期情况,并手动触发刷新?无法将访问令牌加载到任务窗格上的客户端身份验证包中。
我遇到了文档的问题,因为我找不到像我这样的场景的任何示例。所有文档说的是:
对话框窗口中的代码将访问令牌发送到主机窗口,方法是使用 messageParent 发送字符串化的访问令牌,或者将访问令牌存储在主机窗口可以检索的位置(并使用 messageParent 告诉主机窗口令牌可用)。令牌有时间限制,但在其持续期间,主机窗口可以使用它直接访问用户的资源,而无需任何进一步的提示。
Here 它说不存储访问令牌,但我想这只是在使用 SSO 的情况下?这是另一个令人困惑的地方。 Microsoft 是否将特定于 Office 的身份验证方案称为“SSO”(例如外部身份验证的通用术语)?这使得所有信息混杂在一起,因此很难区分 SSO™ 和 SSO。
主要问题是:
Office 加载项的非 SSO 文档位于在不使用 SSO 的情况下向 Microsoft Graph 授权,以及该文章末尾列出的示例。端点是 Microsoft,但理论上它与您正在尝试做的事情是并行的。您可以实现令牌存储(最好在服务器端以确保安全)并在每次使用令牌时检查过期情况。或者,您可以捕获端点将从过期令牌中获取的任何错误,并在错误处理程序中获取新令牌。
好吧,各位。经过几天不间断的研究,我已经弄清楚如何让它一切顺利。
所以。使用
angular-auth-oidc-client
,这是使其全部正常工作的代码。
app.module.ts:
AuthModule.forRoot({
config: {
authority: authorityUrl,
redirectUrl: callbackUrl,
postLogoutRedirectUri: postLogoutRedirectUrl,
clientId: client_id,
scope: "openid offline_access otherscopes",
responseType: "code",
useRefreshToken: true,
renewTimeBeforeTokenExpiresInSeconds: renewTimeBeforeTokenExpiresS,
logLevel: LogLevel.Debug,// convertLogLevel(logLevel),
maxIdTokenIatOffsetAllowedInSeconds: allowedIatOffsetSeconds,
}
}),
记下提供给redirectUrl 的
callbackUrl
。
app.component.ts:
constructor(private router: Router, private oidcSecurityService: OidcSecurityService) {
this.oidcSecurityService.checkAuth().subscribe(checkRes => {
if (checkRes.isAuthenticated) {
this.redirectToMain();
}
else {
this.oidcSecurityService.getAuthorizeUrl().subscribe(url => {
Office.context.ui.displayDialogAsync(url, res => {
const dialog = res.value;
dialog.addEventHandler(Office.EventType.DialogMessageReceived, e => {
console.debug(`Message received from authentication dialog: ${JSON.stringify(e)}`);
if ("message" in e) {
dialog.close();
const oidcRespUrl = e.message;
this.oidcSecurityService.checkAuth(oidcRespUrl).subscribe(checkRes2 => {
if (checkRes2.isAuthenticated) {
this.redirectToMain();
}
else {
// do what you gotta do
}
});
}
else if ("error" in e) {
console.error(e.error);
}
});
});
})
}
});
}
现在,一旦用户登录 Office 对话框窗口,它将重定向到
callbackUrl
,查询参数包括 code=blahblah。您需要做的就是将该 URL 发送回父窗口,如下所示:
html 位于
callbackUrl
:
<html>
<head>
<script src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js" type="text/javascript"></script>
<script>
Office.onReady(function (info) {
const urlWithOidcResp = window.location.href;
Office.context.ui.messageParent(window.location.href);
});
</script>
</head>
<body>
Transmitting authentication result ... (this popup will be closed automatically).
</body>
</html>
就是这样。这似乎是一个相当不错的解决方案,无需诉诸任何有问题的黑客或任何东西。
喝威士忌的时间到了。