Joã*_*hin 6 c# authentication oauth oauth-2.0 .net-core
我正在努力用OAuth和JWT实现自定义身份验证流。基本上应该如下:
我一直在遵循有关如何构建OAuth身份验证的出色教程,唯一不同的部分是Jerrie正在使用Cookies。
到目前为止,我所做的是:
services.AddAuthentication(options =>
{
options.DefaultChallengeScheme = "3rdPartyOAuth";
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie() // Added only because of the DefaultSignInScheme
.AddJwtBearer(options =>
{
options.TokenValidationParameters = // Ommited for brevity
})
.AddOAuth("3rdPartyOAuth", options =>
{
options.ClientId = securityConfig.ClientId;
options.ClientSecret = securityConfig.ClientSecret;
options.CallbackPath = new PathString("/auth/oauthCallback");
options.AuthorizationEndpoint = securityConfig.AuthorizationEndpoint;
options.TokenEndpoint = securityConfig.TokenEndpoint;
options.UserInformationEndpoint = securityConfig.UserInfoEndpoint;
// Only this for testing for now
options.ClaimActions.MapJsonKey("sub", "sub");
options.Events = new OAuthEvents
{
OnCreatingTicket = async context =>
{
// Request for user information
var request = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
var response = await context.Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, context.HttpContext.RequestAborted);
response.EnsureSuccessStatusCode();
var user = JObject.Parse(await response.Content.ReadAsStringAsync());
context.RunClaimActions(user);
}
};
});
Run Code Online (Sandbox Code Playgroud)
[AllowAnonymous]
[HttpGet("login")]
public IActionResult LoginIam(string returnUrl = "/auth/loginCallback")
{
return Challenge(new AuthenticationProperties() {RedirectUri = returnUrl});
}
[AllowAnonymous]
[DisableRequestSizeLimit]
[HttpGet("loginCallback")]
public IActionResult IamCallback()
{
// Here is where I expect to get the user info, create my JWT and send it back to the client
return Ok();
}
Run Code Online (Sandbox Code Playgroud)
免责声明:此OAuth流程现已合并。我有创建和使用自己的JWT工作及所有内容的流程。我不会在这里发布,因为我的问题在此之前。
在杰里(Jerrie)的帖子中,您可以看到他的位置DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;。这样,/auth/loginCallback到达时,我就会在中声明用户的权利HttpContext。问题是我DefaultAuthenticateScheme设置为JwtBearersDefault,当loginCallback调用时,我看不到用户在中没有声明Request。OnCreatingTicketEvent在这种情况下,我如何访问在回调中获得的信息?
额外的问题:我对OAuth不太了解(请确保现在已经清楚)。你可能已经注意到,我的options.CallbackPath上不同于RedirectUri在传递Challenge的login终点。我希望option.CallbackPath第3部分的OAuth提供者可以调用,但这显然不会发生。我必须将其CallbackPath设置为与OAuth提供程序配置(如GitHub的Jerries教程)中设置的相同的值,才能使其正常工作。那正确吗?回调仅用于匹配配置吗?我什CallbackPath至可以注释端点指向的端点,并且端点保持不变。
谢谢!
小智 1
授权
正如 Jerrie 在他的文章中链接的那样,关于身份验证中间件有一个很好的解释: https: //digitalmccullough.com/posts/aspnetcore-auth-system-demystified.html
您可以在身份验证和授权流程部分中查看流程图
第二步是Authentication 中间件调用 Default Handler 的 Authenticate。
由于您的默认身份验证处理程序是 Jwt,因此在 oauth 流之后不会使用用户数据填充上下文,因为它使用CookieAuthenticationDefaults.AuthenticationScheme
尝试:
[AllowAnonymous]
[DisableRequestSizeLimit]
[HttpGet("loginCallback")]
public IActionResult IamCallback()
{
//
// Read external identity from the temporary cookie
//
var result = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
if (result?.Succeeded != true)
{
throw new Exception("Nein");
}
var oauthUser = result.Principal;
...
return Ok();
}
Run Code Online (Sandbox Code Playgroud)
优秀方案总结:ASP.NET Core 2 AuthenticationSchemes
奖金
我确实必须将 CallbackPath 设置为与 OAuth 提供程序配置中设置的值相同的值(如 GitHub 上的 Jerries 教程)才能正常工作。是对的吗?”
是的。出于安全原因,注册的回调 uri(在授权服务器上)和提供的回调 uri(由客户端发送)必须匹配。所以你不能随意改变它,或者如果你改变它,你也必须在认证服务器上改变它。
如果不存在此限制,则带有邮件格式链接(带有修改后的回调 URL)的电子邮件可以获得授权。这称为开放重定向,rfc 也引用它: https: //www.rfc-editor.org/rfc/rfc6749#section-10.15
OWASP 有一个很好的描述:https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md
我什至可以评论 CallbackPath 指向的端点,并且它继续以相同的方式工作......”
这是因为您的客户端是可信的(您提供了您的秘密,并且您不是一个完全前端的单页应用程序)。因此您可以选择发送回调 uri。但如果您发送它,它必须与服务器上注册的匹配。如果您不发送它,身份验证服务器将重定向到在其一侧注册的 url。
https://www.rfc-editor.org/rfc/rfc6749#section-4.1.1
redirect_uri 可选。如第 3.1.2 节所述。
https://www.rfc-editor.org/rfc/rfc6749#section-3.1.2
授权服务器将用户代理重定向到先前在客户端注册过程中或发出授权请求时与授权服务器建立的客户端重定向端点。
https://www.rfc-editor.org/rfc/rfc6749#section-3.1.2.2
授权服务器必须要求以下客户端注册其重定向端点:
您的客户是保密的并使用授权代码授予类型(https://www.rfc-editor.org/rfc/rfc6749#section-1.3.1)
https://www.rfc-editor.org/rfc/rfc6749#section-3.1.2.3
如果已注册多个重定向 URI,如果仅注册了部分重定向 URI,或者如果未注册重定向 URI,则客户端必须使用“redirect_uri”请求参数在授权请求中包含重定向 URI。
您已经注册了重定向 uri,这就是身份验证服务器不会引发错误的原因。
| 归档时间: |
|
| 查看次数: |
234 次 |
| 最近记录: |