Asp.Net 核心 Google 身份验证
Asp.Net Core Google authentication
我的应用在 Google Compute Engine 上运行。 Nginx 用作代理服务器。 Nginx 配置为使用 SSL。下面是/etc/nginx/sites-available/default的内容:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name mywebapp.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
include snippets/ssl-mywebapp.com.conf;
include snippets/ssl-params.conf;
root /home/me/MyWebApp/wwwroot;
location /.well-known/ {
}
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
在Startup.cs我有:
app.UseGoogleAuthentication(new GoogleOptions()
{
ClientId = Configuration["Authentication:Google:ClientId"],
ClientSecret = Configuration["Authentication:Google:ClientSecret"],
});
现在在 Google Cloud Platform 中,我需要指定授权的重定向 URI。如果我输入以下内容,我的网络应用程序将按预期运行:
http://mywebapp.com/signin-google
但是,如果用https
就不行了;浏览器显示以下错误:
The redirect URI in the request, http://mywebapp.com/signin-google, does
not match the ones authorized for the OAuth client.
在这种情况下,使用 http 作为授权重定向 uri 是否安全?如果我想让它成为https,我需要什么配置?
发生这种情况是因为您的 运行 在反向代理服务器后面的应用程序不知道最初的请求来自 HTTPS。
SSL/TLS 终止代理
题中描述的反向代理配置称为SSL/TLS终止反向代理。这意味着在客户端和代理服务器之间建立了安全流量。代理服务器解密请求,然后通过 HTTP 协议将其转发给应用程序。
此配置的问题在于它背后的应用程序不知道客户端通过 HTTPS 发送了请求。因此,当涉及重定向到自身时,它使用 HttpContext.Request.Scheme
、HttpContext.Request.Host
和 HttpContext.Request.Port
为重定向构建有效的 URL。
X-Forwarded-* HTTP Headers
这就是 X-Forwarded-*
header 发挥作用的地方。为了让应用程序知道请求最初是通过 HTTPS 上的代理服务器发出的,我们必须配置代理服务器以设置 X-Forwarded-For
和 X-Forwarded-Proto
HTTP headers。
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
好的,现在如果我们回到 ASP.NET 核心应用程序并查看传入的 HTTP 请求,我们将看到 X-Forwarded-*
header 都已设置,但是重定向 URL 仍然使用 HTTP 方案。
已转发Headers中间件
基本上这个中间件会覆盖 HttpContext.Request.Scheme
和 HttpContext.Connection.RemoteIpAddress
到 X-Forwarded-Proto
和 X-Forwarded-For
header 提供的值。为了实现它,让我们通过在 Startup.Configure()
方法开头的某处添加以下行来将其添加到管道中。
var forwardedHeadersOptions = new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
RequireHeaderSymmetry = false
};
forwardedHeadersOptions.KnownNetworks.Clear();
forwardedHeadersOptions.KnownProxies.Clear();
app.UseForwardedHeaders(forwardedHeadersOptions);
这应该最终使您的应用程序使用 HTTPS 方案构建有效的 URLs。
我的故事
上面的代码看起来与 Microsoft 建议的不同。如果我们看一下 documentation 他们的代码看起来有点短:
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
但是这对我不起作用。另外根据 this issue 下的评论,我并不孤单。
我在 Docker 容器中将 nginx 设置为 ASP.NET 核心应用程序 运行 的反向代理。在我把所有东西都放在 Amazon Load Balancer (ELB) 之后,它变得更加复杂。
我首先遵循了文档中的建议,但它对我不起作用。我的应用程序中收到以下警告:
Parameter count mismatch between X-Forwarded-For and X-Forwarded-Proto
然后我查看了我的 X-Forwarded-*
headers 并意识到它们的长度不同。 X-Forwarded-For
header 包含 2 条记录(逗号分隔的 IP 地址),而 X-Forwarded-Proto
只有一条记录 https
。这就是我将 属性 RequireHeaderSymmetry
设置为 false
的方式。
好吧,我摆脱了 'Parameter count...' 警告消息,但紧接着我又遇到了另一条奇怪的调试消息:
Unknown proxy: 172.17.0.6:44624
在查看 ForwardedHeadersMiddleware 的源代码后,我终于明白我必须清理 KnownNetworks
和 KnownProxies
collections 的 ForwardedHeadersOptions
或将我的 docker 网络 172.17.0.1/16
添加到已知网络列表中。在那之后我终于让它工作了。
PS:对于那些在负载均衡器(例如 Amazon Load Balancer 或 ELB)上设置 SSL/TLS 终止的人 不要 设置 header X-Forwarded-Proto
在 nginx 配置中。这将覆盖来自负载平衡的正确 https
值到 http
方案并且重定向 url 将是错误的。我还没有找到如何将 nginx 中使用的方案附加到 header 而不是覆盖它。
对于apache用户,只需要添加一个header:
RequestHeader 设置 X-Forwarded-Proto "https"
首先需要确保mod_headers已启用。
我的应用在 Google Compute Engine 上运行。 Nginx 用作代理服务器。 Nginx 配置为使用 SSL。下面是/etc/nginx/sites-available/default的内容:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name mywebapp.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
include snippets/ssl-mywebapp.com.conf;
include snippets/ssl-params.conf;
root /home/me/MyWebApp/wwwroot;
location /.well-known/ {
}
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
在Startup.cs我有:
app.UseGoogleAuthentication(new GoogleOptions()
{
ClientId = Configuration["Authentication:Google:ClientId"],
ClientSecret = Configuration["Authentication:Google:ClientSecret"],
});
现在在 Google Cloud Platform 中,我需要指定授权的重定向 URI。如果我输入以下内容,我的网络应用程序将按预期运行:
http://mywebapp.com/signin-google
但是,如果用https
就不行了;浏览器显示以下错误:
The redirect URI in the request, http://mywebapp.com/signin-google, does
not match the ones authorized for the OAuth client.
在这种情况下,使用 http 作为授权重定向 uri 是否安全?如果我想让它成为https,我需要什么配置?
发生这种情况是因为您的 运行 在反向代理服务器后面的应用程序不知道最初的请求来自 HTTPS。
SSL/TLS 终止代理
题中描述的反向代理配置称为SSL/TLS终止反向代理。这意味着在客户端和代理服务器之间建立了安全流量。代理服务器解密请求,然后通过 HTTP 协议将其转发给应用程序。
此配置的问题在于它背后的应用程序不知道客户端通过 HTTPS 发送了请求。因此,当涉及重定向到自身时,它使用 HttpContext.Request.Scheme
、HttpContext.Request.Host
和 HttpContext.Request.Port
为重定向构建有效的 URL。
X-Forwarded-* HTTP Headers
这就是 X-Forwarded-*
header 发挥作用的地方。为了让应用程序知道请求最初是通过 HTTPS 上的代理服务器发出的,我们必须配置代理服务器以设置 X-Forwarded-For
和 X-Forwarded-Proto
HTTP headers。
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
好的,现在如果我们回到 ASP.NET 核心应用程序并查看传入的 HTTP 请求,我们将看到 X-Forwarded-*
header 都已设置,但是重定向 URL 仍然使用 HTTP 方案。
已转发Headers中间件
基本上这个中间件会覆盖 HttpContext.Request.Scheme
和 HttpContext.Connection.RemoteIpAddress
到 X-Forwarded-Proto
和 X-Forwarded-For
header 提供的值。为了实现它,让我们通过在 Startup.Configure()
方法开头的某处添加以下行来将其添加到管道中。
var forwardedHeadersOptions = new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
RequireHeaderSymmetry = false
};
forwardedHeadersOptions.KnownNetworks.Clear();
forwardedHeadersOptions.KnownProxies.Clear();
app.UseForwardedHeaders(forwardedHeadersOptions);
这应该最终使您的应用程序使用 HTTPS 方案构建有效的 URLs。
我的故事
上面的代码看起来与 Microsoft 建议的不同。如果我们看一下 documentation 他们的代码看起来有点短:
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
但是这对我不起作用。另外根据 this issue 下的评论,我并不孤单。
我在 Docker 容器中将 nginx 设置为 ASP.NET 核心应用程序 运行 的反向代理。在我把所有东西都放在 Amazon Load Balancer (ELB) 之后,它变得更加复杂。
我首先遵循了文档中的建议,但它对我不起作用。我的应用程序中收到以下警告:
Parameter count mismatch between X-Forwarded-For and X-Forwarded-Proto
然后我查看了我的 X-Forwarded-*
headers 并意识到它们的长度不同。 X-Forwarded-For
header 包含 2 条记录(逗号分隔的 IP 地址),而 X-Forwarded-Proto
只有一条记录 https
。这就是我将 属性 RequireHeaderSymmetry
设置为 false
的方式。
好吧,我摆脱了 'Parameter count...' 警告消息,但紧接着我又遇到了另一条奇怪的调试消息:
Unknown proxy: 172.17.0.6:44624
在查看 ForwardedHeadersMiddleware 的源代码后,我终于明白我必须清理 KnownNetworks
和 KnownProxies
collections 的 ForwardedHeadersOptions
或将我的 docker 网络 172.17.0.1/16
添加到已知网络列表中。在那之后我终于让它工作了。
PS:对于那些在负载均衡器(例如 Amazon Load Balancer 或 ELB)上设置 SSL/TLS 终止的人 不要 设置 header X-Forwarded-Proto
在 nginx 配置中。这将覆盖来自负载平衡的正确 https
值到 http
方案并且重定向 url 将是错误的。我还没有找到如何将 nginx 中使用的方案附加到 header 而不是覆盖它。
对于apache用户,只需要添加一个header: RequestHeader 设置 X-Forwarded-Proto "https"
首先需要确保mod_headers已启用。