Dar*_*ord 5 c# identityserver4
我将 IdentityServer4 作为身份验证系统运行,以使用 Google 和 Amazon 以及本地帐户。我有一个单独的网络应用程序,使用 IdentityServer4 系统作为 oidc 身份验证提供程序,并且似乎可以进行身份验证和颁发令牌。问题是它在身份验证后不维护 returnUrl。我正在使用通过 Redis 分布式缓存内置到 Id4 的 OIDC StateDataFormatterCache,并在 Redis 中验证它正在写入重定向,甚至是我在挑战时添加的测试参数。
身份验证后,它不会将我重定向回原始网址,并且当我尝试访问质询中设置的参数和 AuthenticationProperties 时,它们在身份验证后似乎不存在。
我已经单步执行了 IdentityServer4 端的代码,其中本地和外部回调的登录信息以及 returnUrl 从未显示在那里。我假设 OIDC StateDataFormatterCache 拦截此行为是为了防止潜在的长 url 问题,并且应该拦截响应并注入返回 url。这部分似乎不起作用,所以我试图看看是否可以将自己的自定义参数粘贴到 auth props 中,并在 auth 发生后将其取出,但结果是空的。AuthenticationProperties 似乎只有 access_token、refresh_token、id_token 等,但缺少重定向 url 和我的自定义参数。
services.AddOidcStateDataFormatterCache("oidc");
...
var authProps = new AuthenticationProperties { RedirectUri = originalPath + context.Request.QueryString };
Microsoft.Extensions.Primitives.StringValues stateValue;
if (context.Request.Query.TryGetValue("state", out stateValue))
{
authProps.SetParameter("itk", stateValue);
}
await Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions.ChallengeAsync(context,"oidc", authProps); //authProps has custom parameter 'itk' and a redirect
...
var authContext = await context.AuthenticateAsync("oidc");
//authContext.Properties has data but not the RedirectUri or the custom parameter I set and verified to exist in the redis store
Run Code Online (Sandbox Code Playgroud)
以下是 Redis 中显示的内容:
{
"Items": {
".redirect": "/?state=foo",
".xsrf": "DkRjG29eE4qDFaNLSktyTDKfhdzXH8FfVpAwBbje6tc",
"OpenIdConnect.Code.RedirectUri": "https://localhost/signin-oidc"
},
"Parameters": {
"itk": [
"foo"
]
},
"RedirectUri": "/?state=foo"
}
Run Code Online (Sandbox Code Playgroud)
关于为什么我无法检索状态数据格式化程序放入 Redis 的信息有什么想法吗?
我需要能够获取参数中“itk”的值。
我发现重定向未通过的问题,但我仍然需要能够获取该参数。
该行为是设计使然,除了持久化到 Redis 之外。评论里说Parameters:
传递给身份验证处理程序的参数集合。它们不适用于序列化或持久性,仅用于在调用站点之间流动数据。
我们必须使用Items集合来进行序列化或持久化。
它对我有用的方式:
//configuration
services.AddOidcStateDataFormatterCache(Constants.MyExternalIdIdpName);
Run Code Online (Sandbox Code Playgroud)
//AccountController
[HttpGet]
public IActionResult Login(string returnUrl)
{
string provider = Constants.MyExternalIdIdpName;
string returnUrl2 = Url.Action("ExternalLoginCallback", new { returnUrl = returnUrl });
// start challenge and roundtrip the return URL
var props = new AuthenticationProperties
{
RedirectUri = returnUrl2,
Items = { { "scheme", provider } }
};
return new ChallengeResult(provider, props);
}
Run Code Online (Sandbox Code Playgroud)
进而
[HttpGet]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl)
{
// read external identity from the temporary cookie
var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);
// retrieve claims of the external user
var claims = result.Principal.Claims.ToList();
var userIdClaim = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject);
var user = <users>.FindByExternalProvider(provider, userIdClaim.Value);
await _events.RaiseAsync(new UserLoginSuccessEvent(provider, userId, user.SubjectId, user.Username));
await HttpContext.SignInAsync(user.SubjectId, user.Username, provider, props, additionalClaims.ToArray());
// delete temporary cookie used during external authentication
await HttpContext.SignOutAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);
// validate return URL and redirect back to authorization endpoint or a local page
if (_interaction.IsValidReturnUrl(returnUrl) || Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
return Redirect("~/");
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3474 次 |
| 最近记录: |