authentication - 基于 JWT 的外部 oauth 登录,没有 cookie 和重定向?
问题描述
我只是找不到合适的术语来搜索以找到我需要的答案,所以我只想在这里尝试解释一下。
我正在尝试让基于 JWT 的登录名适用于没有实际 cookie 或浏览器的应用程序(例如电子)。当我想添加诸如不和谐、谷歌等外部登录时,就会出现问题...
我不确定我正在尝试的方法是否根本不是这样做的方法,或者我是否遗漏了一些东西。
作为我正在尝试做的一个例子,我有一个基于 cookie 的身份验证的工作解决方案(全部基于 asp.net Identity 和标准 .net 提供的功能)。
启动.cs
services.ConfigureApplicationCookie(options =>
{
options.ExpireTimeSpan = TimeSpan.FromDays(7);
options.SlidingExpiration = true;
options.LoginPath = "/login";
options.AccessDeniedPath = "/access-denied";
options.LogoutPath = "/logout";
});
services.AddAuthentication()
.AddDiscord(options =>
{
options.ClientId = "xxx";
options.ClientSecret = "xxx";
options.CallbackPath = "/api/id/external/discord/callback";
options.Scope.Add("identify");
options.Scope.Add("email");
});
身份控制器.cs
public async Task<LoginResult> Login([FromBody] LoginModel model)
{
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, true, false);
if (result.Succeeded)
{
return new LoginResult { Success = true };
}
}
return new LoginResult();
}
[Route("external/login-discord")]
public IActionResult LoginExternal(string returnUrl = null)
{
var url = "/api/id/external/discord";
if (!string.IsNullOrEmpty(returnUrl))
{
url += $"?returnUrl={WebUtility.UrlEncode(returnUrl)}";
}
var properties = _signInManager.ConfigureExternalAuthenticationProperties("Discord", url);
return Challenge(properties, "Discord");
}
[HttpGet]
[Route("external/discord")]
public async Task<IActionResult> LoginWithDiscord(string returnUrl = null)
{
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
var loginUrl = "/login";
if (returnUrl != null && returnUrl != loginUrl)
{
loginUrl += $"?returnUrl={WebUtility.UrlEncode(returnUrl)}";
}
return Redirect(loginUrl);
}
var discordClaims = info.Principal.Claims.Where(c => c.Type.Contains("discord"));
var user = await UserManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey);
var create = user == null;
if (create)
{
user = new User
{
EmailConfirmed = true,
LockoutEnabled = false
};
}
user.DisplayName = info.Principal.FindFirst(ClaimTypes.Name).Value + "#" + info.Principal.FindFirst("urn:discord:user:discriminator").Value;
user.UserName = info.Principal.FindFirst(ClaimTypes.Email).Value;
user.Email = info.Principal.FindFirst(ClaimTypes.Email).Value;
if (create)
{
var createResult = await UserManager.CreateAsync(user);
if (!createResult.Succeeded)
{
createResult.Errors.AddToModelState(ModelState);
return new BadRequestObjectResult(ModelState);
}
createResult = await UserManager.AddLoginAsync(user, info);
if (!createResult.Succeeded)
{
createResult.Errors.AddToModelState(ModelState);
return new BadRequestObjectResult(ModelState);
}
}
else
{
var result = await UserManager.UpdateAsync(user);
if (!result.Succeeded)
{
result.Errors.AddToModelState(ModelState);
return new BadRequestObjectResult(ModelState);
}
}
await UserManager.RemoveClaimsAsync(user, discordClaims);
await UserManager.AddClaimsAsync(user, discordClaims);
await _signInManager.UpdateExternalAuthenticationTokensAsync(info);
await _signInManager.SignInAsync(user, true);
return Redirect(returnUrl ?? "/");
}
这让我可以处理服务器上的所有身份验证内容并使用重定向。
现在我可以轻松地使用 JWT 进行基于密码的登录,因为我只需要在一个请求中返回令牌。但是我如何让外部登录以相同的方式工作?我不想仅将外部身份提供者用于授权,而是将其用于身份验证并创建一个本地用户,就像我的 cookie 示例中一样。
当我在我的应用程序中并单击“使用 X 登录”时,我将打开一个新窗口,该窗口从外部提供商打开登录,但是我如何从外部提供商所做的重定向转到将 JWT 发送给我的客户?
解决方案
推荐阅读
- sass - SCSS if/else 大于
- json - 如何更新以“@”开头的 JSonProperty
- wcf - Windows Server 2016 IIS 10 WCF 服务调用失败并显示“无法建立安全通道”
- python - 问题连接大量不同的 CSV
- r - 在R中的雄蕊图上绘制多边形
- c# - 在 Visual Studio 中获取预生成事件命令行的活动解决方案配置名称
- cytoscape.js - 有没有办法在节点内部的顶部显示节点标签?
- python - 检查嵌套列表是否为空
- java - 同步方法参数
- typescript - Typescript 剥离所有类型信息并仅输出普通 JS - 忽略所有导入和其他错误