Azure 应用服务中的身份验证和授权的高级用法

本文介绍了如何自定义应用服务中的内置身份验证和授权,以及如何从应用程序管理标识。

若要快速入门,请参阅以下教程之一:

使用多个登录提供程序

门户配置不会提供向用户显示多个登录提供程序的统包方式。 但是,将此功能添加到 Web 应用并不困难。 步骤概括如下:

首先,在 Azure 门户中的“身份验证/授权”页上,配置想要启用的每个标识提供者。

在“请求未经身份验证时需执行的操作”中,选择“允许匿名请求(无操作)”。

在登录页、导航栏或 Web 应用的其他任何位置中,将一个登录链接添加到已启用的每个提供程序 (/.auth/login/<provider>)。 例如:

<a href="/.auth/login/aad">Log in with Azure AD</a>
<a href="/.auth/login/microsoftaccount">Log in with Microsoft Account</a>

当用户单击其中一个链接时,系统会打开相应的登录页让用户登录。

若要将登录后用户重定向到自定义 URL,请使用 post_login_redirect_url 查询字符串参数(不要与标识提供者配置中的重定向 URI 混淆)。 例如,若要在登录后将用户导航至 /Home/Index,使用以下 HTML 代码:

<a href="/.auth/login/<provider>?post_login_redirect_url=/Home/Index">Log in</a>

验证来自提供程序的令牌

在客户端定向的登录中,应用程序手动将用户登录到提供程序,然后将身份验证令牌提交给应用服务进行验证(请参阅身份验证流)。 此验证本身不实际向你授予对所需应用资源的访问权限,但成功的验证会向你提供一个会话令牌,可以使用该令牌来访问应用资源。

若要验证提供程序令牌,必须首先为应用服务应用配置所需的提供程序。 在运行时,从你的提供程序检索身份验证令牌后,将令牌发布到 /.auth/login/<provider> 进行验证。 例如:

POST https://<appname>.chinacloudsites.cn/.auth/login/aad HTTP/1.1
Content-Type: application/json

{"id_token":"<token>","access_token":"<token>"}

令牌格式根据提供程序而略有不同。 有关详细信息,请参阅下表:

提供程序值 请求正文中必需的 注释
aad {"access_token":"<access_token>"}
microsoftaccount {"access_token":"<token>"} expires_in 属性为可选。
从 Live 服务请求令牌时,将始终请求 wl.basic 作用域。

如果提供程序令牌成功通过验证,则 API 将在响应正文中返回一个 authenticationToken,这是你的会话令牌。

{
    "authenticationToken": "...",
    "user": {
        "userId": "sid:..."
    }
}

获得此会话令牌后,你可以通过向 HTTP 请求中添加 X-ZUMO-AUTH 标头来访问受保护的应用资源。 例如:

GET https://<appname>.chinacloudsites.cn/api/products/1
X-ZUMO-AUTH: <authenticationToken_value>

注销会话

用户可通过向应用的 /.auth/logout 终结点发送 GET 请求来启动注销。 GET 请求可执行以下操作:

  • 清除当前会话中的身份验证 Cookie。
  • 从令牌存储中删除当前用户的令牌。
  • 对于 Azure Active Directory,请对标识提供程序执行服务器端的注销。

以下是网页中一个简单的注销链接:

<a href="/.auth/logout">Sign out</a>

默认情况下,成功注销后,客户端会重定向到 URL /.auth/logout/done。 通过添加 post_logout_redirect_uri 查询参数可更改注销后的重定向页面。 例如:

GET /.auth/logout?post_logout_redirect_uri=/index.html

建议对 post_logout_redirect_uri 的值进行编码

使用完全限定的 URL 时,URL 必须托管在同一域中,或配置为允许应用访问的外部重定向 URL。 在以下示例中,若要重定向到未托管在同一域中的 https://myexternalurl.com

GET /.auth/logout?post_logout_redirect_uri=https%3A%2F%2Fmyexternalurl.com

必须在 Azure CLI 中运行以下命令:

az webapp auth update --name <app_name> --resource-group <group_name> --allowed-external-redirect-urls "https://myexternalurl.com"

保留 URL 片段

用户登录应用后,通常希望会重定向到同一页面的同一部分,例如 /wiki/Main_Page#SectionZ。 然而,由于从未向服务器发送 URL 片段(例如,#SectionZ),因此默认情况下,OAuth 登录完成并重定向回应用后,会保留这些片段。 然后,当用户需再次导航到所需定位点时,他们无法获得最佳体验。 此限制存在于所有服务器端身份验证解决方案中。

在应用服务身份验证中,可跨 OAuth 登录保留 URL 片段。 为此,请将名为 WEBSITE_AUTH_PRESERVE_URL_FRAGMENT 的应用设置设为 true。 可在 Azure 门户 中执行此操作,或只需在 Azure CLI 中运行以下命令:

az webapp config appsettings set --name <app_name> --resource-group <group_name> --settings WEBSITE_AUTH_PRESERVE_URL_FRAGMENT="true"

访问用户声明

应用服务使用特殊的标头将用户声明传递给应用程序。 不允许外部请求设置这些标头,因此,只会提供应用服务设置的标头。 部分标头示例如下:

  • X-MS-CLIENT-PRINCIPAL-NAME
  • X-MS-CLIENT-PRINCIPAL-ID

使用任何语言或框架编写的代码均可从这些标头获取所需信息。 对于 ASP.NET 4.6 应用, ClaimsPrincipal 会自动设置为相应的值。

应用程序也可以通过调用 /.auth/me 来获取有关经过身份验证的用户的其他详细信息。 移动应用服务器 SDK 提供处理该数据的帮助器方法。 有关详细信息,请参阅如何使用 Azure 移动应用 Node.js SDK使用适用于 Azure 移动应用的 .NET 后端服务器 SDK

检索应用代码中的令牌

在服务器代码中,提供程序特定的令牌将注入到请求标头中,使你可以轻松访问这些令牌。 下表显示了可能的令牌标头名称:

提供程序 标头名称
Azure Active Directory X-MS-TOKEN-AAD-ID-TOKEN
X-MS-TOKEN-AAD-ACCESS-TOKEN
X-MS-TOKEN-AAD-EXPIRES-ON
X-MS-TOKEN-AAD-REFRESH-TOKEN
Microsoft 帐户 X-MS-TOKEN-MICROSOFTACCOUNT-ACCESS-TOKEN
X-MS-TOKEN-MICROSOFTACCOUNT-EXPIRES-ON
X-MS-TOKEN-MICROSOFTACCOUNT-AUTHENTICATION-TOKEN
X-MS-TOKEN-MICROSOFTACCOUNT-REFRESH-TOKEN

在客户端代码(例如移动应用或浏览器中 JavaScript)中,将 HTTP GET 请求发送到 /.auth/me。 返回的 JSON 包含提供程序特定的令牌。

Note

访问令牌用于访问提供程序资源,因此,仅当使用客户端机密配置了提供程序时,才提供这些令牌。 若要了解如何获取刷新令牌,请参阅“刷新访问令牌”。

刷新标识提供程序令牌

当提供程序的访问令牌过期时,需要重新对用户进行身份验证。 向应用程序的 /.auth/refresh 终结点发出 GET 调用可以避免令牌过期。 调用应用服务时,应用服务会自动刷新已身份验证用户的令牌存储中的访问令牌。 应用代码发出的后续令牌请求将获取刷新的令牌。 但是,若要正常刷新令牌,令牌存储必须包含提供程序的刷新令牌。 每个提供程序会阐述获取刷新令牌的方式。以下列表提供了简短摘要:

配置提供程序以后,即可在令牌存储中找到访问令牌的刷新令牌和过期时间

若要随时刷新访问令牌,只需以任何语言调用 /.auth/refresh。 以下代码片段从 JavaScript 客户端使用 jQuery 刷新访问令牌。

function refreshTokens() {
  var refreshUrl = "/.auth/refresh";
  $.ajax(refreshUrl) .done(function() {
    console.log("Token refresh completed successfully.");
  }) .fail(function() {
    console.log("Token refresh failed. See application logs for details.");
  });
}

如果用户撤销了授予应用的权限,对 /.auth/me 的调用可能会失败并返回 403 Forbidden 响应。 若要诊断错误,请检查应用程序日志了解详细信息。

延长会话令牌过期宽限期

经过身份验证的会话会在 8 小时后过期。 经过身份验证的会话过期后,默认会提供 72 小时的宽限期。 在此宽限期内,可以使用应用服务刷新会话令牌,而无需重新对用户进行身份验证。 会话令牌失效后,只需调用 /.auth/refresh,而不需要自行跟踪令牌过期时间。 72 小时的宽限期过后,用户必须重新登录才能获取有效的会话令牌。

如果 72 小时的时间不够,可以延长此过期期限。 大大延长过期时间可能会造成严重的安全风险(例如身份验证令牌泄密或被盗)。 因此,应将宽限期保留为默认 72 小时,或者将延期设为最小值。

若要延长默认的过期期限,请运行以下命令。

az webapp auth update --resource-group <group_name> --name <app_name> --token-refresh-extension-hours <hours>

Note

宽限期仅适用于应用服务的已经身份验证的会话,而不适用于来自标识提供者的令牌。 已过期的提供程序令牌没有宽限期。