英文:
Correct SSO OAuth flow for azure web application and azure function web API
问题
我觉得联邦/Oauth身份验证非常令人困惑。我有一个Web应用程序,它使用Azure AD来认证用户。我还有一个Azure函数,用于对同一个Azure AD进行身份验证。我可以分别访问它们并进行身份验证和访问。
但现在我希望Web应用程序以Web应用程序中登录的用户身份向Azure函数发出请求。这样API可以返回特定于用户的信息。
需要哪种Oauth流程以及如何实现它?
尽管目前的问题是关于单租户应用程序注册,但将来可能需要更改为多租户。可以选择在答案中考虑这一点。
Azure函数API正在运行.NET 6独立版本。因此,在Azure管理门户中,许多简化配置向导不适用。
英文:
I find federated/Oauth authentication highly confusing. I have a web application that is using an azure AD to authenticate users. I also have a azure function that authenticates against the same Azure AD. I can reach both independently and authenticate and access them.
But now I want the web application to make requests to the azure function as the user logged in to the web application. This is so that the API can return user specific information.
What Oauth ?flow is required and how do I implement it.
Though the question for now is about a single tenant app registrations. I may need to change that to multi-tenant in the future. Optionally consider this for the answer.
The Azure function API is running .net6 ISOLATED. So much of the easy config wizards don't work for that in the azure admin portal.
答案1
得分: 0
以下是您要翻译的内容:
情况您描述的涉及身份验证的两个关键阶段:
- 通过Azure AD在Web应用程序中验证用户的身份(您已经完成了此步骤)以及
- 将该用户的身份传递给Azure函数以验证代表用户的Web应用程序的请求。
此场景最适合的OAuth 2.0机制是On-Behalf-Of(OBO)。这允许您的Web应用程序获取Azure函数('downstream' API)的访问令牌,代表用户。
以下是此过程操作的简要摘要:
- 用户登录Web应用程序,随后从Azure AD获取访问令牌。
- 如果Web应用程序需要调用Azure函数,它将向Azure AD提供用户的访问令牌并请求Azure函数的新令牌。
- Azure AD验证用户的访问令牌并生成Azure函数的新令牌。
- Web应用程序使用新获取的令牌调用Azure函数,代表用户执行操作。
需要对您的Azure AD应用程序注册进行一些修改,包括Web应用程序和Azure函数。此外,您的Web应用程序的令牌检索逻辑也需要进行调整。
1. 应用程序注册的调整:
在Azure门户中,找到Web应用程序的应用程序注册。
- 转到“API权限”选项卡并添加新权限。
- 不要选择Microsoft提供的API,而是点击“我们的组织使用的API”选项卡,并找到Azure函数的应用程序注册。
- 添加“access_as_user”权限。
此调整使您的Web应用程序能够请求Azure函数的令牌。
2. 令牌检索的修改:
在您的Web应用程序内获取令牌的逻辑中,当需要调用Azure函数时:
- 使用“AcquireTokenOnBehalfOf”方法(或根据您使用的SDK选择等效方法)为Azure函数获取令牌。
- 此方法的参数应包括用户的访问令牌和Azure函数的范围(通常为“
/access_as_user”,其中“ ”是Azure函数应用程序注册的Application(client)ID URI)。
以下是使用“Microsoft.Identity.Web”库的示例:
string[] scopes = new string[] { "<AppIdUri>/access_as_user" };
// 假设“userAccessToken”是经过身份验证的用户的令牌
AuthenticationResult result = await _tokenAcquisition
.AcquireTokenOnBehalfOf(scopes, new UserAssertion(userAccessToken))
.ExecuteAsync();
// 使用“result.AccessToken”调用Azure函数
3. Azure函数的更改:
通常,会使用“Microsoft.Identity.Web”库来验证传入的令牌。但是,Azure Functions的隔离模型不直接支持它。相反,需要手动验证令牌。
为此,请使用“System.IdentityModel.Tokens.Jwt”库。这需要您:
- 从Azure AD的元数据端点(https://login.microsoftonline.com/
/v2.0/.well-known/openid-configuration)检索签名密钥。 - 验证令牌的签名、发行者、受众和其他声明。
关于多租户性质,如果您希望使您的应用程序可供来自不同租户的用户访问,您应该:
- 更改应用程序注册中的“支持的帐户类型”设置为“任何组织目录中的帐户”。
- 更新Azure函数中的令牌验证逻辑,以接受来自多个发行者的令牌。
您还需要考虑您的Web应用程序是否是编写为单页Web应用程序或者是否使用后端服务器端代码进行用户身份验证或调用Azure函数。以上方法适用于您的Web应用程序使用服务器端代码调用Azure函数的情况。如果您的Web应用程序是单页应用程序,您需要根据情况调整方法,因为您可能不希望通过浏览器JavaScript代码公开客户端ID和密钥等信息。
对于单页应用程序,通常会使用OAuth 2.0 Implicit Grant或Authorization Code with PKCE(Proof Key for Code Exchange)流程来验证用户。
通过此方法,单页应用程序可以获取用户的访问令牌,然后可用于调用Azure函数。
然而,单页应用程序无法使用On-Behalf-Of(OBO)流程,因为这需要应用程序访问客户端秘密或证书,这对于公共客户端(例如单页应用程序)不适用。
在这种情况下,您应该:
-
实现Azure函数以接受来自Web应用程序(对于服务器端应用程序)和用户(对于单页应用程序)的令牌。这意味着验证令牌中的“scp”或“roles”声明,以确保用户具有必要的权限。
-
使用用户的访问令牌直接从单页应用程序调用Azure函数。Azure函数应验证令牌并使用“sub”或“oid”声明来确定用户的身份并返回特定于用户的信息。
通过这种方式,Azure函数可以在两种情况下提供特定于用户的信息:在从单页应用程序直接调用时以及在代表用户从Web应用程序调用时。
英文:
The situation you're describing involves two key phases of authentication:
- Verifying the user's identity through Azure AD within the web application (which you've already completed), and
- Conveying that user's identity to the Azure function to authenticate the web application's requests made on behalf of the user.
The most suitable OAuth 2.0 mechanism for this scenario is the On-Behalf-Of (OBO). This permits your web application to obtain an access token for the Azure function (the 'downstream' API), representing the user.
Here's a brief summary of how this process operates:
- The user logs into the web application, which subsequently retrieves an access token from Azure AD.
- If the web application needs to call the Azure function, it provides Azure AD with the user's access token and requests a new one for the Azure function.
- Azure AD verifies the user's access token and generates a new one for the Azure function.
- The web application employs this newly obtained token to call the Azure function, acting on behalf of the user.
some modifications are needed in your Azure AD app registrations for both your web application and Azure function. Additionally, adjustments are required in the token retrieval logic in your web application.
1. Adjustments to the app registration:
In the Azure portal, locate the app registration for your web application.
- Navigate to the 'API permissions' blade and add a new permission.
- Instead of selecting an API provided by Microsoft, click on the 'APIs my organization uses' tab and locate your Azure function's app registration.
- Add the 'access_as_user' permission.
This adjustment enables your web application to request tokens for the Azure function.
2. Modifications to token retrieval:
In the logic for obtaining tokens within your web application, when the Azure function needs to be called:
- Employ the 'AcquireTokenOnBehalfOf' method (or an equivalent depending on the SDK you're using) to secure a token for the Azure function.
- The arguments for this method should include the user's access token and the Azure function's scope (which is typically '<AppIdUri>/access_as_user', where '<AppIdUri>' refers to the Application (client) ID URI of the Azure function's app registration).
Here's an example using the 'Microsoft.Identity.Web' library:
string[] scopes = new string[] { "<AppIdUri>/access_as_user" };
// Assuming 'userAccessToken' is the token of the authenticated user
AuthenticationResult result = await _tokenAcquisition
.AcquireTokenOnBehalfOf(scopes, new UserAssertion(userAccessToken))
.ExecuteAsync();
// Use 'result.AccessToken' to call the Azure function
3. Changes to the Azure Function:
Usually, the 'Microsoft.Identity.Web' library would be used to validate incoming tokens. However, Azure Functions' isolated model doesn't directly support it. Instead, manual validation of the tokens is required.
To do this, use the 'System.IdentityModel.Tokens.Jwt' library. This requires you to:
- Retrieve the signing keys from Azure AD's metadata endpoint (https://login.microsoftonline.com/<TenantId>/v2.0/.well-known/openid-configuration).
- Validate the token's signature, issuer, audience, and other claims.
Regarding multi-tenancy, if you want to make your application accessible to users from various tenants, you should:
- Alter the 'Supported account types' setting in your app registrations to 'Accounts in any organizational directory'.
- Update the token validation logic in your Azure function to accept tokens from multiple issuers.
You also have to consider if your web application is an application which is written as a Single Page Web App or Is using Backend server side code for authenticating user or making a the call to azure function. Above Approach is suitable if your web application is using server side code to all the azure function. If you are having the web application which is a Single Page Application, you will have to adjust your approach as you may not want to expose the client id and secret etc via browser java script code.
For a SPA, you would typically use the OAuth 2.0 Implicit Grant or Authorization Code with PKCE (Proof Key for Code Exchange) flow to authenticate the user.
With this approach, the SPA can obtain an access token for the user, which can then be used to call the Azure function.
However, SPA cannot use the On-Behalf-Of (OBO) flow, as this requires the application to have access to the client secret or a certificate, which is not suitable for a public client like a SPA.
In this scenario you should:
-
Implement the Azure function to accept tokens from both the web application (in case of a server-side app) and the user (in case of a SPA). This means validating the
scp
orroles
claim in the token to ensure the user has the necessary permissions. -
Use the user's access token to call the Azure function directly from the SPA. The Azure function should validate the token and use the
sub
oroid
claim to determine the user's identity and return user-specific information.
This way, the Azure function can provide user-specific information in both scenarios: when called directly from the SPA and when called from the web application on behalf of the user.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论