反向代理后面的 .NET 6 OAuth 身份验证:质询时重定向 url 错误

Posted

技术标签:

【中文标题】反向代理后面的 .NET 6 OAuth 身份验证:质询时重定向 url 错误【英文标题】:.NET 6 OAuth authentication behind reverse proxy: wrong redirect url on challenge 【发布时间】:2022-01-21 12:49:16 【问题描述】:

我正在努力在 Linux 上托管的 .net 6 razor pages 项目上启用 OAuth2,使用 Apache 作为反向代理。

我在 OAuth 质询中遇到了关于“redirect_uri”的问题:我获得的 URI 是本地的,而不是通过反向代理公开的。 基本上:我访问了我的 webapp 访问“login.domain.com”(apache 在本地 kestrel 实例上转发我的请求)。但是一旦我挑战远程登录提供程序,我就会得到

&redirect_uri=http://127.0.0.1:5000/discord-signin

我的反向代理转发的标头似乎是正确的:

2021-12-19 16:11:44.487 +01:00 [WRN] Header: Accept: ["text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: Connection: ["keep-alive"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: Host: ["127.0.0.1:5000"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: User-Agent: ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: Accept-Encoding: ["gzip, deflate, br"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: Accept-Language: ["en-US,en;q=0.9,it;q=0.8,de;q=0.7"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: Cache-Control: ["max-age=0"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: Content-Type: ["application/x-www-form-urlencoded"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: Cookie: ["_ga=GA1.2.542637492.1636097135; .AspNetCore.Antiforgery.DTVEdTt8EGg=CfDJ8MlMA29MyfZGjp9AYHEkO4mfg3bwuzIArowPu6tG3DH6IZfzcsAfWAHKHoMi7NeY_dakBIxSHpBv-l_vrIZER2oU06TRVh9A3shL_H6j6gpj_frjZwyNF8qMNpVws7UCg7GGtDZMQIg92GuFtzmo5S0"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: Origin: ["login.domain.com"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: Referer: ["https://discord.ivao.it/accounts"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: Upgrade-Insecure-Requests: ["1"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: Content-Length: ["182"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: sec-ch-ua: ["\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"96\", \"Microsoft Edge\";v=\"96\""]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: sec-ch-ua-mobile: ["?0"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: sec-ch-ua-platform: ["\"Windows\""]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: Sec-Fetch-Site: ["same-origin"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: Sec-Fetch-Mode: ["navigate"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: Sec-Fetch-User: ["?1"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: Sec-Fetch-Dest: ["document"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: X-Forwarded-Host: ["login.domain.com"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: X-Forwarded-Server: ["login.domain.com"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: X-Original-For: ["127.0.0.1:49194"]

这就是我配置身份验证的方式:

builder.Services.AddAuthentication(options =>

    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = DiscordAuthenticationDefaults.AuthenticationScheme;
)
.AddCookie(opt =>

    opt.LoginPath = "/discordauth/signedin";
)
.AddDiscord(opt =>

    opt.ClientId = "771681863952891944";
    opt.ClientSecret = "vBvBa3OLkydqkMalLQLHxjGmluqiqflC";
);

我还在 Linux 部署过程中启用了 MS 规定的转发头中间件

app.UseCookiePolicy();
app.UseRouting();
app.UseForwardedHeaders(new ForwardedHeadersOptions

    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
);

app.UseAuthorization();
app.UseAuthentication();

那么,我错过了什么?为什么我的质询请求会生成指向本地“localhost:5000”而不是前端 login.domain.com 的 redirect_uri?

提前感谢您的帮助

【问题讨论】:

【参考方案1】:

好的,伙计们。我想我解决了我的错误(因为它是我的错……)。

由于我的反向代理发送了我的 3 个关于正向的标头:

2021-12-19 16:11:44.487 +01:00 [WRN] Header: X-Forwarded-Host: ["login.domain.com"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: X-Forwarded-Server: ["login.domain.com"]
2021-12-19 16:11:44.487 +01:00 [WRN] Header: X-Original-For: ["127.0.0.1:49194"]

我基本上是在告诉 .net 用我的配置处理错误的:

app.UseForwardedHeaders(new ForwardedHeadersOptions

    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
);

在这种情况下,httpContext.Request.Host 没有被 ForwardedHeadersMiddleware 覆盖,因为我忘记告诉它也处理 Host 标头“X-Forwarded-Host”。

这解决了我的问题:

var forwardedHeadersOptions = new ForwardedHeadersOptions

    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost,
;

【讨论】:

以上是关于反向代理后面的 .NET 6 OAuth 身份验证:质询时重定向 url 错误的主要内容,如果未能解决你的问题,请参考以下文章

通过反向代理注入 OAuth2 令牌

在反向代理后面使用 OAuth2 的 Spring Boot

如何使用 OAuth2 身份验证设置 traefik

PHP - 没有密码的身份验证(OAuth 都没有)

在需要身份验证但不返回 407 的代理后面打开 http 连接

在反向代理后面使用 SP 时出现 Spring saml 问题