Azure 应用服务中的身份验证和授权的高级用法Advanced usage of authentication and authorization in Azure App Service

本文介绍了如何自定义应用服务中的内置身份验证和授权,以及如何从应用程序管理标识。This article shows you how to customize the built-in authentication and authorization in App Service, and to manage identity from your application.

若要快速入门,请参阅以下教程之一:To get started quickly, see one of the following tutorials:

使用多个登录提供程序Use multiple sign-in providers

门户配置不会提供向用户显示多个登录提供程序的统包方式。The portal configuration doesn't offer a turn-key way to present multiple sign-in providers to your users. 但是,将此功能添加到 Web 应用并不困难。However, it isn't difficult to add the functionality to your web app. 步骤概括如下:The steps are outlined as follows:

首先,在 Azure 门户中的“身份验证/授权”页上,配置想要启用的每个标识提供者。First, in the Authentication / Authorization page in the Azure portal, configure each of the identity provider you want to enable.

在“请求未经身份验证时需执行的操作”中,选择“允许匿名请求(无操作)”。In Action to take when request is not authenticated, select Allow Anonymous requests (no action).

在登录页、导航栏或 Web 应用的其他任何位置中,将一个登录链接添加到已启用的每个提供程序 (/.auth/login/<provider>)。In the sign-in page, or the navigation bar, or any other location of your web app, add a sign-in link to each of the providers you enabled (/.auth/login/<provider>). 例如:For example:

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

当用户单击其中一个链接时,系统会打开相应的登录页让用户登录。When the user clicks on one of the links, the respective sign-in page opens to sign in the user.

若要将登录后用户重定向到自定义 URL,请使用 post_login_redirect_url 查询字符串参数(不要与标识提供者配置中的重定向 URI 混淆)。To redirect the user post-sign-in to a custom URL, use the post_login_redirect_url query string parameter (not to be confused with the Redirect URI in your identity provider configuration). 例如,若要在登录后将用户导航至 /Home/Index,使用以下 HTML 代码:For example, to navigate the user to /Home/Index after sign-in, use the following HTML code:

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

验证来自提供程序的令牌Validate tokens from providers

在客户端定向的登录中,应用程序手动将用户登录到提供程序,然后将身份验证令牌提交给应用服务进行验证(请参阅身份验证流)。In a client-directed sign-in, the application signs in the user to the provider manually and then submits the authentication token to App Service for validation (see Authentication flow). 此验证本身不实际向你授予对所需应用资源的访问权限,但成功的验证会向你提供一个会话令牌,可以使用该令牌来访问应用资源。This validation itself doesn't actually grant you access to the desired app resources, but a successful validation will give you a session token that you can use to access app resources.

若要验证提供程序令牌,必须首先为应用服务应用配置所需的提供程序。To validate the provider token, App Service app must first be configured with the desired provider. 在运行时,从你的提供程序检索身份验证令牌后,将令牌发布到 /.auth/login/<provider> 进行验证。At runtime, after you retrieve the authentication token from your provider, post the token to /.auth/login/<provider> for validation. 例如:For example:

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

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

令牌格式根据提供程序而略有不同。The token format varies slightly according to the provider. 有关详细信息,请参阅下表:See the following table for details:

提供程序值Provider value 请求正文中必需的Required in request body 注释Comments
aad {"access_token":"<access_token>"}
microsoftaccount {"access_token":"<token>"} expires_in 属性为可选。The expires_in property is optional.
从 Live 服务请求令牌时,将始终请求 wl.basic 作用域。When requesting the token from Live services, always request the wl.basic scope.

| | | || | | |

如果提供程序令牌成功通过验证,则 API 将在响应正文中返回一个 authenticationToken,这是你的会话令牌。If the provider token is validated successfully, the API returns with an authenticationToken in the response body, which is your session token.

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

获得此会话令牌后,你可以通过向 HTTP 请求中添加 X-ZUMO-AUTH 标头来访问受保护的应用资源。Once you have this session token, you can access protected app resources by adding the X-ZUMO-AUTH header to your HTTP requests. 例如:For example:

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

注销会话Sign out of a session

用户可通过向应用的 /.auth/logout 终结点发送 GET 请求来启动注销。Users can initiate a sign-out by sending a GET request to the app's /.auth/logout endpoint. GET 请求可执行以下操作:The GET request does the following:

  • 清除当前会话中的身份验证 Cookie。Clears authentication cookies from the current session.
  • 从令牌存储中删除当前用户的令牌。Deletes the current user's tokens from the token store.
  • 对于 Azure Active Directory 和 Google,请对标识提供程序执行服务器端的注销。For Azure Active Directory and Google, performs a server-side sign-out on the identity provider.

以下是网页中一个简单的注销链接:Here's a simple sign-out link in a webpage:

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

默认情况下,成功注销后,客户端会重定向到 URL /.auth/logout/doneBy default, a successful sign-out redirects the client to the URL /.auth/logout/done. 通过添加 post_logout_redirect_uri 查询参数可更改注销后的重定向页面。You can change the post-sign-out redirect page by adding the post_logout_redirect_uri query parameter. 例如:For example:

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

建议对 post_logout_redirect_uri 的值进行编码It's recommended that you encode the value of post_logout_redirect_uri.

使用完全限定的 URL 时,URL 必须托管在同一域中,或配置为允许应用访问的外部重定向 URL。When using fully qualified URLs, the URL must be either hosted in the same domain or configured as an allowed external redirect URL for your app. 在以下示例中,若要重定向到未托管在同一域中的 https://myexternalurl.comIn the following example, to redirect to https://myexternalurl.com that's not hosted in the same domain:

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

必须在 Azure CLI 中运行以下命令:You must run the following command in the Azure CLI :

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

保留 URL 片段Preserve URL fragments

用户登录应用后,通常希望会重定向到同一页面的同一部分,例如 /wiki/Main_Page#SectionZAfter users sign in to your app, they usually want to be redirected to the same section of the same page, such as /wiki/Main_Page#SectionZ. 然而,由于从未向服务器发送 URL 片段(例如,#SectionZ),因此默认情况下,OAuth 登录完成并重定向回应用后,会保留这些片段。However, because URL fragments (for example, #SectionZ) are never sent to the server, they are not preserved by default after the OAuth sign-in completes and redirects back to your app. 然后,当用户需再次导航到所需定位点时,他们无法获得最佳体验。Users then get a suboptimal experience when they need to navigate to the desired anchor again. 此限制存在于所有服务器端身份验证解决方案中。This limitation applies to all server-side authentication solutions.

在应用服务身份验证中,可跨 OAuth 登录保留 URL 片段。In App Service authentication, you can preserve URL fragments across the OAuth sign-in. 为此,请将名为 WEBSITE_AUTH_PRESERVE_URL_FRAGMENT 的应用设置设为 trueTo do this, set an app setting called WEBSITE_AUTH_PRESERVE_URL_FRAGMENT to true. 可在 Azure 门户 中执行此操作,或只需在 Azure CLI 中运行以下命令:You can do it in the Azure portal, or simply run the following command in the Azure CLI:

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

访问用户声明Access user claims

应用服务使用特殊的标头将用户声明传递给应用程序。App Service passes user claims to your application by using special headers. 不允许外部请求设置这些标头,因此,只会提供应用服务设置的标头。External requests aren't allowed to set these headers, so they are present only if set by App Service. 部分标头示例如下:Some example headers include:

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

使用任何语言或框架编写的代码均可从这些标头获取所需信息。Code that is written in any language or framework can get the information that it needs from these headers. 对于 ASP.NET 4.6 应用, ClaimsPrincipal 会自动设置为相应的值。For ASP.NET 4.6 apps, the ClaimsPrincipal is automatically set with the appropriate values.

应用程序也可以通过调用 /.auth/me 来获取有关经过身份验证的用户的其他详细信息。Your application can also obtain additional details on the authenticated user by calling /.auth/me. 移动应用服务器 SDK 提供处理该数据的帮助器方法。The Mobile Apps server SDKs provide helper methods to work with this data. 有关详细信息,请参阅如何使用 Azure 移动应用 Node.js SDK使用适用于 Azure 移动应用的 .NET 后端服务器 SDKFor more information, see How to use the Azure Mobile Apps Node.js SDK, and Work with the .NET backend server SDK for Azure Mobile Apps.

检索应用代码中的令牌Retrieve tokens in app code

在服务器代码中,提供程序特定的令牌将注入到请求标头中,使你可以轻松访问这些令牌。From your server code, the provider-specific tokens are injected into the request header, so you can easily access them. 下表显示了可能的令牌标头名称:The following table shows possible token header names:

提供程序Provider 标头名称Header names
Azure Active DirectoryAzure 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 帐户Microsoft Account 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/meFrom your client code (such as a mobile app or in-browser JavaScript), send an HTTP GET request to /.auth/me. 返回的 JSON 包含提供程序特定的令牌。The returned JSON has the provider-specific tokens.

Note

访问令牌用于访问提供程序资源,因此,仅当使用客户端机密配置了提供程序时,才提供这些令牌。Access tokens are for accessing provider resources, so they are present only if you configure your provider with a client secret. 若要了解如何获取刷新令牌,请参阅“刷新访问令牌”。To see how to get refresh tokens, see Refresh access tokens.

刷新标识提供程序令牌Refresh identity provider tokens

当提供程序的访问令牌(而不是会话令牌)到期时,需要在再次使用该令牌之前重新验证用户。When your provider's access token (not the session token) expires, you need to reauthenticate the user before you use that token again. 向应用程序的 /.auth/refresh 终结点发出 GET 调用可以避免令牌过期。You can avoid token expiration by making a GET call to the /.auth/refresh endpoint of your application. 调用应用服务时,应用服务会自动刷新已身份验证用户的令牌存储中的访问令牌。When called, App Service automatically refreshes the access tokens in the token store for the authenticated user. 应用代码发出的后续令牌请求将获取刷新的令牌。Subsequent requests for tokens by your app code get the refreshed tokens. 但是,若要正常刷新令牌,令牌存储必须包含提供程序的刷新令牌However, for token refresh to work, the token store must contain refresh tokens for your provider. 每个提供程序会阐述获取刷新令牌的方式。以下列表提供了简短摘要:The way to get refresh tokens are documented by each provider, but the following list is a brief summary:

  • Microsoft 帐户配置 Microsoft 帐户身份验证设置时,请选择 wl.offline_access 范围。Microsoft Account: When configuring Microsoft Account Authentication Settings, select the wl.offline_access scope.
  • Azure Active Directory:在 https://resources.azure.com 中,执行以下步骤:Azure Active Directory: In https://resources.azure.com, do the following steps:
    1. 在页面顶部,选择“读/写”。At the top of the page, select Read/Write.

    2. 在左侧浏览器中,导航到 subscriptions > <subscription_name > resourceGroups > <resource_group_name> > providers > Microsoft.Web > sites > <app_name> > config > authsettingsIn the left browser, navigate to subscriptions > <subscription_name > resourceGroups > <resource_group_name> > providers > Microsoft.Web > sites > <app_name> > config > authsettings.

    3. 单击“编辑”。Click Edit.

    4. 修改以下属性。Modify the following property. <app_id> 替换为要访问的服务的 Azure Active Directory 应用程序 ID。Replace <app_id> with the Azure Active Directory application ID of the service you want to access.

      "additionalLoginParams": ["response_type=code id_token", "resource=<app_id>"]
      
    5. 单击“放置”。Click Put.

配置提供程序以后,即可在令牌存储中找到访问令牌的刷新令牌和过期时间Once your provider is configured, you can find the refresh token and the expiration time for the access token in the token store.

若要随时刷新访问令牌,只需以任何语言调用 /.auth/refreshTo refresh your access token at anytime, just call /.auth/refresh in any language. 以下代码片段从 JavaScript 客户端使用 jQuery 刷新访问令牌。The following snippet uses jQuery to refresh your access tokens from a JavaScript client.

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 响应。If a user revokes the permissions granted to your app, your call to /.auth/me may fail with a 403 Forbidden response. 若要诊断错误,请检查应用程序日志了解详细信息。To diagnose errors, check your application logs for details.

延长会话令牌过期宽限期Extend session token expiration grace period

经过身份验证的会话会在 8 小时后过期。The authenticated session expires after 8 hours. 经过身份验证的会话过期后,默认会提供 72 小时的宽限期。After an authenticated session expires, there is a 72-hour grace period by default. 在此宽限期内,可以使用应用服务刷新会话令牌,而无需重新对用户进行身份验证。Within this grace period, you're allowed to refresh the session token with App Service without reauthenticating the user. 会话令牌失效后,只需调用 /.auth/refresh,而不需要自行跟踪令牌过期时间。You can just call /.auth/refresh when your session token becomes invalid, and you don't need to track token expiration yourself. 72 小时的宽限期过后,用户必须重新登录才能获取有效的会话令牌。Once the 72-hour grace period is lapses, the user must sign in again to get a valid session token.

如果 72 小时的时间不够,可以延长此过期期限。If 72 hours isn't enough time for you, you can extend this expiration window. 大大延长过期时间可能会造成严重的安全风险(例如身份验证令牌泄密或被盗)。Extending the expiration over a long period could have significant security implications (such as when an authentication token is leaked or stolen). 因此,应将宽限期保留为默认 72 小时,或者将延期设为最小值。So you should leave it at the default 72 hours or set the extension period to the smallest value.

若要延长默认的过期期限,请运行以下命令。To extend the default expiration window, run the following command.

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

Note

宽限期仅适用于应用服务的已经身份验证的会话,而不适用于来自标识提供者的令牌。The grace period only applies to the App Service authenticated session, not the tokens from the identity providers. 已过期的提供程序令牌没有宽限期。There is no grace period for the expired provider tokens.

限制登录帐户的域Limit the domain of sign-in accounts

Microsoft 帐户和 Azure Active Directory 都允许从多个域登录。Both Microsoft Account and Azure Active Directory lets you sign in from multiple domains. 例如,Microsoft 帐户允许 outlook.comlive.comhotmail.com 帐户。For example, Microsoft Account allows outlook.com, live.com, and hotmail.com accounts. Azure Active Directory 允许对登录帐户使用任意数量的自定义域。Azure Active Directory allows any number of custom domains for the sign-in accounts. 对于内部应用,此行为可能不符合需要,因为你不希望具有 outlook.com 帐户的任何人都拥有访问权限。This behavior may be undesirable for an internal app, which you don't want anyone with an outlook.com account to access. 若要限制登录帐户的域名,请执行以下步骤。To limit the domain name of the sign-in accounts, follow these steps.

https://resources.azure.com 中,导航到 subscriptions > <subscription_name > resourceGroups > <resource_group_name> > providers > Microsoft.Web > sites > <app_name> > config > authsettingsIn https://resources.azure.com, navigate to subscriptions > <subscription_name > resourceGroups > <resource_group_name> > providers > Microsoft.Web > sites > <app_name> > config > authsettings.

单击“编辑”,修改以下属性,然后单击“放置”。Click Edit, modify the following property, and then click Put. 请务必将 <domain_name> 替换为所需的域。Be sure to replace <domain_name> with the domain you want.

"additionalLoginParams": ["domain_hint=<domain_name>"]

后续步骤Next steps