在 Azure AD 中使用无提示身份验证

重要

Microsoft 对 Active Directory 身份验证库 (ADAL) 的支持和开发,包括安全修补程序,将于 2022 年 6 月 30日 结束。 若要继续接收支持,请将应用程序更新为使用 Microsoft 身份验证库 (MSAL) 。请参阅 将应用程序迁移到 Microsoft 身份验证库 (MSAL)

备注

要使身份验证适用于移动客户端上的选项卡,请确保使用的是 Teams JavaScript SDK 版本 1.4.1 或更高版本。

Azure AD 中的无提示身份验证通过无提示刷新身份验证令牌,最大限度地减少了用户需要输入凭据的次数。 有关真正的单一登录支持,请参阅 SSO 文档

若要保留代码客户端,请使用适用于 JavaScript 的 Azure AD 身份验证库以无提示方式获取 Microsoft Azure Active Directory (Azure AD) 访问令牌。 如果用户最近已登录,则看不到弹出对话框。

虽然 Active Directory 身份验证库针对 AngularJS 应用程序进行了优化,它也适用于 JavaScript 单页应用程序 (SPA)。

备注

目前,无提示身份验证仅适用于选项卡。 从机器人登录时,它不起作用。

无提示身份验证的工作原理

Active Directory 身份验证库为 OAuth 2.0 隐式授权流程创建隐藏的 iframe。 但库会指定 prompt=none,因此 Azure AD 不会显示登录页面。 如果用户需要登录或授予对应用程序的访问权限,则可能需要用户交互。 如果需要用户交互,Azure AD 会返回一个错误,由库报告给应用程序。 如有必要,应用现在可以显示登录选项。

如何执行无提示身份验证

本文中的代码来自 Teams 示例应用,即 Teams 身份验证示例节点

使用 Azure AD 启动无提示和简单身份验证可配置选项卡,并按照说明在本地计算机上运行示例。

添加和配置 Active Directory 身份验证库

在选项卡页中添加 Active Directory 身份验证库,并使用客户端 ID 和重定向 URL 配置库:

<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.15/js/adal.min.js" integrity="sha384-lIk8T3uMxKqXQVVfFbiw0K/Nq+kt1P3NtGt/pNexiDby2rKU6xnDY8p16gIwKqgI" crossorigin="anonymous"></script>
<script type="text/javascript">
    // Active Directory Authentication Library configuration
    let config = {
        clientId: "YOUR_APP_ID_HERE",
        // redirectUri must be in the list of redirect URLs for the Azure AD app
        redirectUri: window.location.origin + "/tab-auth/silent-end",
        cacheLocation: "localStorage",
        navigateToLoginRequestUrl: false,
    };
</script>

获取当前上下文的用户

在选项卡的内容页中,调用 app.getContext() 以获取当前用户的登录提示。 该提示在调用 Azure AD 时用作 loginHint

// Set up extra query parameters for Active Directory Authentication Library
// - openid and profile scope adds profile information to the id_token
// - login_hint provides the expected user name
if (loginHint) {
    config.extraQueryParameter = "scope=openid+profile&login_hint=" + encodeURIComponent(loginHint);
} else {
    config.extraQueryParameter = "scope=openid+profile";
}

身份验证

如果 Active Directory 身份验证库为用户缓存了未过期的令牌,请使用该令牌。 或者,调用 acquireToken(resource, callback) 以无提示方式接收令牌。 库使用请求的令牌调用回调函数,或者在身份验证失败时生成错误。

如果回调函数中出现错误,请显示并使用显式登录选项。

let authContext = new AuthenticationContext(config); // from Active Directory Authentication Library
// See if there is a cached user and it matches the expected user
let user = authContext.getCachedUser();
if (user) {
    if (user.profile.oid !== userObjectId) {
        // User doesn't match, clear the cache
        authContext.clearCache();
    }
}

// In this example we are getting an id token (which Active Directory Authentication Library returns if we ask for resource = clientId)
authContext.acquireToken(config.clientId, function (errDesc, token, err, tokenType) {
    if (token) {
        // Make sure Active Directory Authentication Library gave us an ID token
        if (tokenType !== authContext.CONSTANTS.ID_TOKEN) {
            token = authContext.getCachedToken(config.clientId);
        }
        showProfileInformation(idToken);
    } else {
        console.log("Renewal failed: " + err);
        // Failed to get the token silently; show the login button
        showLoginButton();
        // You could attempt to launch the login popup here, but in browsers this could be blocked by
        // a popup blocker, in which case the login attempt will fail with the reason FailedToOpenWindow.
    }
});

处理返回值

Active Directory 身份验证库通过在登录回调页中调用 AuthenticationContext.handleWindowCallback(hash) 来分析 Azure AD 的结果。

检查是否有有效的用户,并调用 authentication.notifySuccess()authentication.notifyFailure() 向主选项卡内容页面报告状态。

import { authentication } from "@microsoft/teams-js";
if (authContext.isCallback(window.location.hash)) {
    authContext.handleWindowCallback(window.location.hash);
    if (window.parent === window) {
        if (authContext.getCachedUser()) {
            authentication.notifySuccess();
        } else {
            authentication.notifyFailure(authContext.getLoginError());
        }
    }
}

处理注销流程

使用以下代码处理 Azure AD 身份验证中的注销流程:

备注

从 Teams 选项卡或机器人注销时,将清除当前会话。

function logout() {
localStorage.clear();
window.location.href = "@Url.Action("<<Action Name>>", "<<Controller Name>>")";
}

另请参阅