我已成功閱讀并實施了本地開發專案以匹配 Auth0 的使用 Auth0 回應用戶身份驗證的完整指南。我對實作充滿信心,因為登錄和路由保護的所有方面都正常作業,并且本地快速服務器成功驗證了使用通過 Auth0 React SDK 生成的身份驗證令牌的 API 呼叫。
我在示例專案的 external-apis.js 視圖中添加了第三個按鈕,用于呼叫我試圖與之集成的另一個 API,它是一個 Azure Functions 應用程式。我想以與快速服務器相同的方式將 Auth0 用于此 API,并利用 Azure 的“Easy Auth”功能,如本 MS 檔案中所述。我已經在我的 Azure Function 應用程式中實作了一個 OpenID Connect 提供程式,它指向我的 Auth0 應用程式,每個 MS doc。
這是呼叫此 Azure Function 應用程式 API 的函式的樣子:
const callAzureApi = async () => {
try {
const token = await getAccessTokenSilently();
await fetch(
'https://example.azurewebsites.net/api/ExampleEndPoint',
{
method: 'GET',
headers: {
'content-type': 'application/json',
authorization: `Bearer ${token}`,
},
}
)
.then((response) => response.json())
.then((response) => {
setMessage(JSON.stringify(response));
})
.catch((error) => {
setMessage(error.message);
});
} catch (error) {
setMessage(error.message);
}
};
我的問題是呼叫此 Azure 函式應用程式 API 始終回傳 401(未授權)回應,即使正在發送授權令牌也是如此。如果我將 Azure 門戶中的授權設定更改為不需要身份驗證,則代碼會正確檢索資料,因此我確信代碼是正確的。
但是,為了將 Auth0 用作 Azure 后端的身份驗證提供程式,我在設定中是否還遺漏了什么?
uj5u.com熱心網友回復:
通過持續的檔案和博客閱讀,我能夠確定我的原始實作中缺少什么。簡而言之,在閱讀了 Azure 的 tge“Easy Auth”功能后,我的期望有點過高,至少在使用像 Auth0 這樣的 OpenID Connect 提供程式時是這樣。具體來說,JSON Web Token (JWT) 的驗證不是免費的,需要進一步實施。
我的應用程式使用 React Auth0 SDK 將用戶登錄到身份提供者并獲取授權令牌以發送其 API 請求。客戶端導向的登錄流程的 Azure 檔案討論了使用特定 POST 呼叫對帶有 JWT 的身份驗證端點的 JWT 進行驗證的能力,但即使此功能在這里似乎也無法實作,因為 OpenID Connect 不是列在提供程式串列中,無論如何我嘗試嘗試它繼續產生 401s。
那么,答案是直接在 Azure 函式本身中實作 ??JWT 驗證,并且只有在請求標頭中的 JWT 可以被驗證時才回傳正確的回應。我想感謝Boris Wilhelm和Ben Chartrand 的博客文章,他們幫助最終理解如何正確使用 Auth0 用于 Azure Functions 后端 API。
我創建了以下 Security 物件來執行令牌驗證。ConfigurationManager 的靜態特性對于快取配置以減少對提供者的 HTTP 請求很重要。(我的 Azure Functions 專案是用 C# 撰寫的,而不是 React JS 前端應用程式。)
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
namespace ExampleProject.Common {
public static class Security {
private static readonly IConfigurationManager<OpenIdConnectConfiguration> _configurationManager;
private static readonly string ISSUER = Environment.GetEnvironmentVariable("Auth0Url", EnvironmentVariableTarget.Process);
private static readonly string AUDIENCE = Environment.GetEnvironmentVariable("Auth0Audience", EnvironmentVariableTarget.Process);
static Security()
{
var documentRetriever = new HttpDocumentRetriever {RequireHttps = ISSUER.StartsWith("https://")};
_configurationManager = new ConfigurationManager<OpenIdConnectConfiguration> (
$"{ISSUER}.well-known/openid-configuration",
new OpenIdConnectConfigurationRetriever(),
documentRetriever
);
}
public static async Task<ClaimsPrincipal> ValidateTokenAsync(AuthenticationHeaderValue value) {
if(value?.Scheme != "Bearer")
return null;
var config = await _configurationManager.GetConfigurationAsync(CancellationToken.None);
var validationParameter = new TokenValidationParameters {
RequireSignedTokens = true,
ValidAudience = AUDIENCE,
ValidateAudience = true,
ValidIssuer = ISSUER,
ValidateIssuer = true,
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
IssuerSigningKeys = config.SigningKeys
};
ClaimsPrincipal result = null;
var tries = 0;
while (result == null && tries <= 1) {
try {
var handler = new JwtSecurityTokenHandler();
result = handler.ValidateToken(value.Parameter, validationParameter, out var token);
} catch (SecurityTokenSignatureKeyNotFoundException) {
// This exception is thrown if the signature key of the JWT could not be found.
// This could be the case when the issuer changed its signing keys, so we trigger
// a refresh and retry validation.
_configurationManager.RequestRefresh();
tries ;
} catch (SecurityTokenException) {
return null;
}
}
return result;
}
}
}
然后,在運行任何其他代碼來處理請求之前,我在任何 HTTP 觸發的函式的頂部添加了一小段樣板代碼:
ClaimsPrincipal principal;
if ((principal = await Security.ValidateTokenAsync(req.Headers.Authorization)) == null) {
return new UnauthorizedResult();
}
有了這個,我終于有了我正在尋找的實作。我想用更通用的東西來改進實作,比如自定義屬性,但我不確定這對于 OpenID Connect 提供者是否可行。盡管如此,這對我來說仍然是一個完全可以接受的解決方案,并且在使用 React 前端和 Azure Functions 后端時為我提供了我正在尋找的安全級別。
干杯!
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/381738.html
