来自Blazor的API在Azure API管理背后使用Validate-JWT的呼叫

发布于 2025-01-27 13:13:25 字数 4946 浏览 4 评论 0原文

在Azure API管理的后面,我有一堆API。我所有的应用程序都使用身份服务器4来验证和身份验证用户和应用程序。当对API的请求到来时,我喜欢在继续前进之前验证jwt令牌。

因此,在API管理中,在“安全性”部分下,我选择了OpenID Connect,然后选择了我的身份服务器。

在API的设计中,我添加了验证-jwt

”

,策略就是这样。

<policies>
    <inbound>
        <validate-jwt header-name="Authorization" 
             failed-validation-httpcode="401" require-scheme="Bearer" 
             output-token-variable-name="jwt">
            <openid-config url="https://idsrv4/.well-known/openid-configuration" />
        </validate-jwt>
        <cors>
            <allowed-origins>
                <origin>*</origin>
            </allowed-origins>
            <allowed-methods preflight-result-max-age="300">
                <method>GET</method>
                <method>POST</method>
            </allowed-methods>
            <allowed-headers>
                <header>*</header>
            </allowed-headers>
            <expose-headers>
                <header>*</header>
            </expose-headers>
        </cors>
        <base />
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

然后,在我的jullazor webAssembly的program.cs中,我最终添加了以下代码

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

string apiEndpoint = builder.Configuration["Api:EndpointsUrl"];
string apiScope = builder.Configuration["Api:Scope"];

builder.Services.AddScoped<APIService>();

#region Configure HTTP Client
builder.Services.AddHttpClient("companiesAPI", cl =>
{
    cl.BaseAddress = new Uri(apiEndpoint);
})
.AddHttpMessageHandler(sp =>
{
    var handler = sp.GetService<AuthorizationMessageHandler>()
    .ConfigureHandler(
        authorizedUrls: new[] { "https://localhost:7241" },
        scopes: new[] { "220005_api" }
     );
    return handler;
});
builder.Services.AddScoped(sp => sp.GetService<IHttpClientFactory>().CreateClient("companiesAPI"));
#endregion
#region Configure Authentication and Authorization
builder.Services.AddOidcAuthentication(options =>
{
    builder.Configuration.Bind("oidc", options.ProviderOptions);
    options.UserOptions.RoleClaim = "role";
})
.AddAccountClaimsPrincipalFactory<MultipleRoleClaimsPrincipalFactory<RemoteUserAccount>>();

builder.Services.AddAuthorizationCore();
#endregion

await builder.Build().RunAsync();

,在API服务中,我阅读了API。

public class APIService
{
    private readonly HttpClient _httpClient;

    private readonly JsonSerializerOptions _options;

    public APIService(HttpClient httpClient)
    {
        _httpClient = httpClient;
        _options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
    }

    public async Task<APIResponse> GetAttributeAsync(APIRequest apirequest)
    {
        try
        {
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, $"typing");
            var content = 
                new StringContent(JsonSerializer.Serialize(apirequest), 
                Encoding.UTF8, "application/json");
            request.Content = content;

            HttpResponseMessage responseMessage;
            responseMessage = await _httpClient.SendAsync(request);
            responseMessage.EnsureSuccessStatusCode();

            if (responseMessage.IsSuccessStatusCode)
            {
                var responseContent = await responseMessage.Content.ReadAsStringAsync();
                return JsonSerializer.Deserialize<APIResponse>(responseContent, _options);
            }
            else
                return new APIResponse() { Success = false };
        }
        catch (Exception ex)
        {
            return new APIResponse() { Success = false };
        }
    }
}

现在,如果我调用API,我有以下错误:

TypeError:无法获取

,则无法获取validate-jwt,该应用程序调用API并在没有问题的情况下接收答案。

API管理的正确配置是什么?通过jwt令牌的大火项目中的正确代码是什么?

Behind an Azure API Management I have a bunch of APIs. All my applications are using an Identity Server 4 to validate and authenticate users and applications. When a request to the API comes, I like to validate the jwt token before proceeding.

For this reason , in the API Management, under the Security section, I selected OpenID connect and then my Identity Server.

enter image description here

In the design of the APIs, I added the validation-jwt

enter image description here

enter image description here

and the policy is like that

<policies>
    <inbound>
        <validate-jwt header-name="Authorization" 
             failed-validation-httpcode="401" require-scheme="Bearer" 
             output-token-variable-name="jwt">
            <openid-config url="https://idsrv4/.well-known/openid-configuration" />
        </validate-jwt>
        <cors>
            <allowed-origins>
                <origin>*</origin>
            </allowed-origins>
            <allowed-methods preflight-result-max-age="300">
                <method>GET</method>
                <method>POST</method>
            </allowed-methods>
            <allowed-headers>
                <header>*</header>
            </allowed-headers>
            <expose-headers>
                <header>*</header>
            </expose-headers>
        </cors>
        <base />
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

Then, in the Program.cs of my Blazor WebAssembly, I added the following code

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

string apiEndpoint = builder.Configuration["Api:EndpointsUrl"];
string apiScope = builder.Configuration["Api:Scope"];

builder.Services.AddScoped<APIService>();

#region Configure HTTP Client
builder.Services.AddHttpClient("companiesAPI", cl =>
{
    cl.BaseAddress = new Uri(apiEndpoint);
})
.AddHttpMessageHandler(sp =>
{
    var handler = sp.GetService<AuthorizationMessageHandler>()
    .ConfigureHandler(
        authorizedUrls: new[] { "https://localhost:7241" },
        scopes: new[] { "220005_api" }
     );
    return handler;
});
builder.Services.AddScoped(sp => sp.GetService<IHttpClientFactory>().CreateClient("companiesAPI"));
#endregion
#region Configure Authentication and Authorization
builder.Services.AddOidcAuthentication(options =>
{
    builder.Configuration.Bind("oidc", options.ProviderOptions);
    options.UserOptions.RoleClaim = "role";
})
.AddAccountClaimsPrincipalFactory<MultipleRoleClaimsPrincipalFactory<RemoteUserAccount>>();

builder.Services.AddAuthorizationCore();
#endregion

await builder.Build().RunAsync();

Finally, in the API service, I read the API.

public class APIService
{
    private readonly HttpClient _httpClient;

    private readonly JsonSerializerOptions _options;

    public APIService(HttpClient httpClient)
    {
        _httpClient = httpClient;
        _options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
    }

    public async Task<APIResponse> GetAttributeAsync(APIRequest apirequest)
    {
        try
        {
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, 
quot;typing");
            var content = 
                new StringContent(JsonSerializer.Serialize(apirequest), 
                Encoding.UTF8, "application/json");
            request.Content = content;

            HttpResponseMessage responseMessage;
            responseMessage = await _httpClient.SendAsync(request);
            responseMessage.EnsureSuccessStatusCode();

            if (responseMessage.IsSuccessStatusCode)
            {
                var responseContent = await responseMessage.Content.ReadAsStringAsync();
                return JsonSerializer.Deserialize<APIResponse>(responseContent, _options);
            }
            else
                return new APIResponse() { Success = false };
        }
        catch (Exception ex)
        {
            return new APIResponse() { Success = false };
        }
    }
}

Now, if I call the API, I have the following error:

TypeError: Failed to fetch

If from the API Management, I remove the validate-jwt, the application calls the API and receives the answer with no issues.

What is the correct configuration for the API Management? What is the correct code in the Blazor project to pass the jwt token?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

甜`诱少女 2025-02-03 13:13:25

获得这样的JWT

// This gets the UserToken (JWT) to get data from Microsoft Graph for the scopes: User.Read & Mail.Read
// scope for API: API/GUID [YOUR API-URL-FROM-YOUR-APPREGISTRATION-IN-AAD]
var token = await _tokenAcquisition.GetAccessTokenForUserAsync(new string[] { "User.Read", "Mail.Read", "api://12345678-1234-1234-1234-123456789012/products" });

在您的应用程序代码中,您应该在apim =&gt中 ;在入站中,您缺少所需的索赔

 <inbound>
    <validate-jwt header-name="Authorization" 
                  failed-validation-httpcode="401" 
                  failed-validation-error-message="Unauthorized. Access token is missing or invalid!!!">
    <openid-config url="https://login.microsoftonline.com/11a14169-89cc-44e8-95d7-xxxxxxxxxxxx/v2.0/.well-known/openid-configuration" />
      <required-claims>
        <claim name="aud">
            <value>{client-id-of-Client-API-1-on-App-Registration}</value>
        </claim>
    </required-claims>

请查看此问题以获取更多代码详细信息。代码很好!
如何在具有Microsoft Identity平台(AAD)的Blazor Server应用中获取JWT来进行外部API管理调用并授权使用JWT

In your application code you should get the JWT like this

// This gets the UserToken (JWT) to get data from Microsoft Graph for the scopes: User.Read & Mail.Read
// scope for API: API/GUID [YOUR API-URL-FROM-YOUR-APPREGISTRATION-IN-AAD]
var token = await _tokenAcquisition.GetAccessTokenForUserAsync(new string[] { "User.Read", "Mail.Read", "api://12345678-1234-1234-1234-123456789012/products" });

In the APIM => In the Inbound you are missing the required claims

 <inbound>
    <validate-jwt header-name="Authorization" 
                  failed-validation-httpcode="401" 
                  failed-validation-error-message="Unauthorized. Access token is missing or invalid!!!">
    <openid-config url="https://login.microsoftonline.com/11a14169-89cc-44e8-95d7-xxxxxxxxxxxx/v2.0/.well-known/openid-configuration" />
      <required-claims>
        <claim name="aud">
            <value>{client-id-of-Client-API-1-on-App-Registration}</value>
        </claim>
    </required-claims>

Check your JWT over here to set the right claim for 'aud' in your APIM

Have a look at this question for more code details. The code is GOOD!
How do I get the JWT in a Blazor Server App with Microsoft Identity Platform (AAD) to make external API-Management call and authorize with the jwt

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文