asp.net-core - ASP.NET Core OAuth 不适用于 Safari
问题描述
我们最近发现 OAuth 的某些东西(包括 facebook/google)在桌面 Safari(12.x 和 13.x)上不起作用。该系统在 Chrome、Firefox 和移动 Safari 上运行良好。
我们不确定它是什么时候坏的,但它在 2 周前还在工作,昨晚它没有工作。
这是我们在 Startup.cs 中配置 OAuth 的地方
.AddFacebook(options => {
options.AppId = SecretSettings.GetSecret("FacebookAppId");
options.AppSecret = SecretSettings.GetSecret("FacebookAppSecret");
options.Scope.Add("email");
options.AuthorizationEndpoint = "https://www.facebook.com/v2.8/dialog/oauth";
options.TokenEndpoint = "https://graph.facebook.com/v2.8/oauth/access_token";
options.BackchannelHttpHandler = new FacebookBackChannelHandler();
options.UserInformationEndpoint = "https://graph.facebook.com/v2.8/me?fields=id,name,email,first_name,last_name";
options.RemoteAuthenticationTimeout = remoteAuthTimeout;
options.SignInScheme = IdentityConstants.ExternalScheme;
options.AccessDeniedPath = "/account/login?returnUrl=%2F";
})
.AddGoogle(options => {
options.ClientId = SecretSettings.GetSecret("GoogleOAuth2ClientId");
options.ClientSecret = SecretSettings.GetSecret("GoogleOAuth2ClientSecret");
options.RemoteAuthenticationTimeout = remoteAuthTimeout;
options.SignInScheme = IdentityConstants.ExternalScheme;
options.AccessDeniedPath = "/account/login?returnUrl=%2F";
})
我们使用以下代码生成挑战:
return Challenge(new AuthenticationProperties { RedirectUri = redirectUrl }, authenticationScheme);
据我们所知,通常的流程是:
- 使用 Google 登录,生成挑战令牌
- 重定向到google oauth,用户登录并返回
- 重定向到 /signin-google(中间件路由)以确认给定的代码
- 重定向到sso返回动作,处理用户登录或注册
Chrome 正确地点击了所有这些,但 Safari 卡在 3 上。浏览器没有被重定向回我们的 sso 返回操作,而是被丢弃在网站的主页上。
我检查了所涉及的 url,看起来状态、范围和代码正在正确传递,只是中间件内部发生了一些事情,将用户踢到了网站的根目录。
我们正在使用 ASP.NET Core 3.0
有谁知道可能出了什么问题?或者我们可以探索的途径来解决这个问题?
解决方案
我遇到了同样的问题。我使用此处找到的解决方案修复了它:https ://github.com/dotnet/aspnetcore/issues/18362
在 Startup.cs 中添加 SameSite cookie 建议代码:
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
以及以下方法:
private void CheckSameSite(HttpContext httpContext, CookieOptions options)
{
if (options.SameSite == SameSiteMode.None)
{
var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
if (DisallowsSameSiteNone(userAgent))
{
options.SameSite = SameSiteMode.Unspecified;
}
}
}
public static bool DisallowsSameSiteNone(string userAgent)
{
// Cover all iOS based browsers here. This includes:
// - Safari on iOS 12 for iPhone, iPod Touch, iPad
// - WkWebview on iOS 12 for iPhone, iPod Touch, iPad
// - Chrome on iOS 12 for iPhone, iPod Touch, iPad
// All of which are broken by SameSite=None, because they use the iOS networking
// stack.
if (userAgent.Contains("CPU iPhone OS 12") ||
userAgent.Contains("iPad; CPU OS 12"))
{
return true;
}
// Cover Mac OS X based browsers that use the Mac OS networking stack.
// This includes:
// - Safari on Mac OS X.
// This does not include:
// - Chrome on Mac OS X
// Because they do not use the Mac OS networking stack.
if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") &&
userAgent.Contains("Version/") && userAgent.Contains("Safari"))
{
return true;
}
// Cover Chrome 50-69, because some versions are broken by SameSite=None,
// and none in this range require it.
// Note: this covers some pre-Chromium Edge versions,
// but pre-Chromium Edge does not require SameSite=None.
if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))
{
return true;
}
return false;
}
这将禁止将相同站点策略发送到与其不兼容的浏览器。
推荐阅读
- c# - 如何在 WPF XAML 中为视图构建 SDK
- graphql - 对相同 __typename 数据的不同查询从缓存中返回未定义的 Apollo Graphql
- c# - 如何在 .Net Core 中重新制作我的包装器代码?
- laravel - 如何处理自定义 HTTP 异常?
- python - 使用正则表达式匹配两个特定字符
- amazon-web-services - AWS CDK 设置第二个侦听器 + 目标会忽略目标端口
- java - 通过 Odoo XML-RPC API 和 false 检索模型字段
- swagger-ui - connexion 在另一个 url 服务 swagger ui
- oauth-2.0 - 从 AzureAD 请求短期 accessToken
- angular - Angular + Jasmine:如何忽略/模拟测试组件中的一个函数(不在依赖项中)?