当站点隐藏在 WAF/网关后面时,通过 Oracle Oauth 验证 ASP.NET Core 时出现问题

问题描述 投票:0回答:1

我有一个使用 C# .NET 后端的前端 (JavaScript) 应用程序。身份验证是通过 OAuth (Oracle IDCS) 实现的。它运行良好,但现在后端应用程序位于 API 网关/WAF(可通过互联网访问)后面。假设公共主机是

public-host.com
。网关将公共地址转换为我的后端应用程序正在接收请求的本地主机(因此我的后端“认为”它托管在与实际不同的 URL 下)。假设私人主机是
private-host.io
。现在,后端在调用 Oracle 时使用了错误的
redirect_uri
OAuth 参数(
https://idcs-xxx.identity.oraclecloud.com/oauth2/v1/authorize?client_id=...&scope=...&...&redirect_uri=http://private-host.io/authorization_code/callback&...
- 没有 url 编码的示例)。在公开场合是
https
,但在本地/内部是
http

我尝试通过以下方式解决此问题:

        services
            .AddAuthentication(options =>
            {
                /*...*/
            })
            .AddOAuth("Oracle", options =>
            {
                options.Events = new OAuthEvents
                {
                    OnRedirectToAuthorizationEndpoint = context =>
                    {
                        // Replace the `redirect_uri` query string parameter found in `context.RedirectUri` with the public one
                        // so replace "http://internal-host.io/" with "https://public-host.com/" when redirecting to Oracles OAuth endpoint
                        // context.RedirectUri holds the full redirect URL like: https://idcs-xxx.identity.oraclecloud.com/oauth2/v1/authorize?client_id=...&scope=...&...&redirect_uri=http://internal-host.io/authorization_code/callback
                        // this is more of a pseudo-code because we have to deal with encoding the URL/query string
                        context.RedirectUri = context.RedirectUri.Replace("http://internal-host.io/", "https://public-host.com/");
                        context.Response.Redirect(context.RedirectUri);
                        return Task.CompletedTask;
                    }
                };
            });

现在发送 OAuth 请求时使用了正确的

redirect_uri
参数,Oracle 中的身份验证成功(我认为)并且 Oracle 重定向回正确的地址(
https://public-host.com/authorization-code/callback?code=XXX
但现在 C# 代码抛出两个错误

An error was encountered while handling the remote login. Correlation failed.
Microsoft.AspNetCore.Authentication.AuthenticationFailureException:
   at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1+<HandleRequestAsync>d__12.MoveNext (Microsoft.AspNetCore.Authentication, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)

Microsoft.AspNetCore.Authentication.AuthenticationFailureException: An error was encountered while handling the remote login.
---> Microsoft.AspNetCore.Authentication.AuthenticationFailureException: OAuth token endpoint failure: invalid_redirect_uri;Description=Client XXXX requested an invalid redirect URL: http://internal-host.io:443/authorization-code/callback.

(请注意

http://internal-host.io

所以我怀疑,尽管我更改了

redirect_uri
中的
OnRedirectToAuthorizationEndpoint
,但 OAuth 处理代码以某种方式期望 local-host.io 而不是 public-host.com 并且失败,因为它是不同的......


更多配置:

services.AddAuthentication(options => {...}) 
.AddOAuth("Oracle", options =>
{
    Uri apiAddress = configuration.OracleApiAddress;
    options.AuthorizationEndpoint = $"{apiAddress}/oauth2/v1/authorize";
    options.Scope.Add("openid");
    options.Scope.Add("urn:opc:idm:__myscopes__");
    options.CallbackPath = new PathString("/authorization-code/callback");
    options.ClientId = configuration.OracleApplicationId;
    options.ClientSecret = configuration.OracleApplicationSecret;
    options.TokenEndpoint = $"{apiAddress}/oauth2/v1/token";
    options.UserInformationEndpoint = $"{apiAddress}/oauth2/v1/userinfo";
    // ...
}
c# asp.net-core oauth oracle-cloud-infrastructure
1个回答
0
投票

解决方案是在自定义中间件中修改请求主机/方案/端口。就我而言,由于 API 网关包含的标头,外部/原始主机是已知的。

public class CustomMiddleware(RequestDelegate next)
{
    public async Task InvokeAsync(HttpContext context)
    {
        // Header from the API gateway
        string originalHost = context.Request.Headers["x-original-host"].ToString();
        context.Request.Scheme = "https";
        context.Request.Host = new HostString(originalHost, 443);
        await next(context);
    }
}

用途

Program.cs

    public static void Main(string[] args)
    {
        WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
        /* ... */
        WebApplication app = builder.Build();
        app.UseMiddleware<CustomMiddleware>();
        /* ... */
        app.UseAuthentication();
        app.UseAuthorization();
        /* ... */
        app.Run();
    }
© www.soinside.com 2019 - 2024. All rights reserved.