添加其他身份验证提供程序但保留当前会话数据
Add Additional Authentication Provider but keep current session data
我有一个使用 AspNet.Security.OAuth.Twitch. I configured everything and it is working fine, but I want to add the option to link an additional account with other providers, like Twitter. I tried to add Twitter authentication using Microsoft.AspNetCore.Authentication.Twitter 实现 Twitch 身份验证的 .NET5 MVC 项目。还配置了一切。
但是当我使用 Twitter 登录时,我的当前会话丢失并且来自 Twitch 的所有 Claims 都被删除并被 Twitter Claims 取代。我想这是预期的行为,但我不知道我是否可以保留这些声明或仅恢复 Twitter 声明而不存储在用户身份中(例如存储在数据库中)。我的主要目标是使用 Twitch 身份验证作为登录应用程序的唯一方式,但必须选择 link 来自其他提供商的帐户。
我在我的 Startup.cs
中添加了两个提供商(最终可能会在将来的某个时候添加其他提供商)
public void ConfigureServices(IServiceCollection services)
{
// more stuff ...
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddTwitch(options =>
{
options.ClientId = Configuration["Twitch-ClientId"];
options.ClientSecret = Configuration["Twitch-ClientSecret"];
})
.AddTwitter(options =>
{
options.ConsumerKey = Configuration["Twitter-ConsumerKey"];
options.ConsumerSecret = Configuration["Twitter-ConsumerSecret"];
});
}
在我的AuthController.cs
我有对应的Challenge方法
// Default Login using Twitch
[HttpGet("~/signin")]
public IActionResult Login() => RedirectToAction("Login", "Auth", new { provider = "Twitch" });
[HttpPost("~/signin")]
public IActionResult Login([FromForm] string provider)
{
string redirect_uri = Url.Action("Index", "Home");
return Challenge(new AuthenticationProperties() { RedirectUri = redirect_uri }, provider);
}
我不知道是否可以修改或配置 Challenge
以允许此行为。我在 AuthenticationProperties class 中没有看到任何可以使用的 属性。我最初尝试为其他提供者创建另一个 Controller/Action,但结果是一样的。
我们将不胜感激。
只要用户的会话 cookie 有效,您就可以使用多种身份验证方案对其进行身份验证并随时访问这些声明。
But when I login using Twitter, my current session is lost and all the Claims from Twitch were removed and replaced by Twitter Claims.
发生这种情况是因为您试图使用 Cookie
方案来保存 Twitter 和 Twitch 的会话 cookie。当您使用一个登录时,它会覆盖另一个。
要解决此问题,您需要为每个单独的登录选项添加单独的 cookie。
services.AddAuthentication()
.AddCookie("GoogleSession")
.AddCookie("GithubSession")
.AddGoogle(
options => {
// set the app credentials
Configuration.GetSection("Google").Bind(options);
// save session to this cookie
options.SignInScheme = "GoogleSession";
})
.AddGitHub(
options => {
// set the app credentials
Configuration.GetSection("Github").Bind(options);
// save session to this cookie
options.SignInScheme = "GithubSession";
});
然后发出质询以强制用户登录:
[AllowAnonymous]
[HttpGet("login-google")]
public ActionResult LoginGoogle()
{
return Challenge(
new AuthenticationProperties
{
RedirectUri = Url.Action("WhoAmI"),
}, GoogleDefaults.AuthenticationScheme
);
}
[AllowAnonymous]
[HttpGet("login-github")]
public ActionResult LoginGithub()
{
return Challenge(
new AuthenticationProperties
{
RedirectUri = Url.Action("WhoAmI"),
}, GitHubAuthenticationDefaults.AuthenticationScheme
);
}
然后,您可以随时对用户进行身份验证以读取和解析 cookie 以访问声明:
[AllowAnonymous]
[HttpGet("me")]
public async Task<ActionResult> WhoAmI()
{
var googleResult = await HttpContext.AuthenticateAsync(GoogleDefaults.AuthenticationScheme);
if (googleResult.Succeeded)
{
var googlePrincipal = googleResult.Principal;
// ... use google claims
User.AddIdentity((ClaimsIdentity)googlePrincipal.Identity);
}
var githubResult = await HttpContext.AuthenticateAsync(GitHubAuthenticationDefaults.AuthenticationScheme);
if (githubResult.Succeeded)
{
var githubPrincipal = githubResult.Principal;
// ... use google claims
User.AddIdentity((ClaimsIdentity)githubPrincipal.Identity);
}
return Ok(
User.Identities.Select(
id => new
{
id.AuthenticationType,
Claims = id.Claims.Select(c => new { c.Type, c.Value })
}
)
.ToList()
);
现在,当我访问 /me
时,我得到了所有会话中所有声明的列表:
[
{
"authenticationType": null,
"claims": []
},
{
"authenticationType": "Google",
"claims": [
{
"type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
"value": "123131231231312123123123"
},
{
"type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
"value": "My Fullname"
},
{
"type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname",
"value": "MyName"
},
{
"type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname",
"value": "MyLastname"
},
{
"type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"value": "my@gmail.com"
}
]
},
{
"authenticationType": "GitHub",
"claims": [
{
"type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
"value": "1313123123"
},
{
"type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
"value": "abdusco"
},
{
"type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"value": "my@email.com"
},
{
"type": "urn:github:name",
"value": "my name"
},
{
"type": "urn:github:url",
"value": "https://api.github.com/users/abdusco"
}
]
}
]
使用多种身份验证方案手动对用户进行身份验证有点繁琐。我们可以让 ASP.NET Core 为我们做。
定义接受多个身份验证方案的授权策略。
services.AddAuthorization(
options => options.DefaultPolicy = new AuthorizationPolicyBuilder(
GoogleDefaults.AuthenticationScheme,
GitHubAuthenticationDefaults.AuthenticationScheme
).RequireAuthenticatedUser()
.Build()
);
现在,当您使用 [Authorize]
修饰操作时(并在需要时指定策略名称),HttpContext.User
将包含所有会话的身份和声明。
[Authorize]
[HttpGet("me")]
public async Task<ActionResult> WhoAmI()
{
return Ok(
// user has claims from all sessions
User.Identities.Select(
id => new
{
id.AuthenticationType,
Claims = id.Claims.Select(c => new { c.Type, c.Value })
}
)
.ToList()
);
}
这与之前的输出相同,但没有样板文件。
我有一个使用 AspNet.Security.OAuth.Twitch. I configured everything and it is working fine, but I want to add the option to link an additional account with other providers, like Twitter. I tried to add Twitter authentication using Microsoft.AspNetCore.Authentication.Twitter 实现 Twitch 身份验证的 .NET5 MVC 项目。还配置了一切。
但是当我使用 Twitter 登录时,我的当前会话丢失并且来自 Twitch 的所有 Claims 都被删除并被 Twitter Claims 取代。我想这是预期的行为,但我不知道我是否可以保留这些声明或仅恢复 Twitter 声明而不存储在用户身份中(例如存储在数据库中)。我的主要目标是使用 Twitch 身份验证作为登录应用程序的唯一方式,但必须选择 link 来自其他提供商的帐户。
我在我的 Startup.cs
中添加了两个提供商(最终可能会在将来的某个时候添加其他提供商)
public void ConfigureServices(IServiceCollection services)
{
// more stuff ...
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddTwitch(options =>
{
options.ClientId = Configuration["Twitch-ClientId"];
options.ClientSecret = Configuration["Twitch-ClientSecret"];
})
.AddTwitter(options =>
{
options.ConsumerKey = Configuration["Twitter-ConsumerKey"];
options.ConsumerSecret = Configuration["Twitter-ConsumerSecret"];
});
}
在我的AuthController.cs
我有对应的Challenge方法
// Default Login using Twitch
[HttpGet("~/signin")]
public IActionResult Login() => RedirectToAction("Login", "Auth", new { provider = "Twitch" });
[HttpPost("~/signin")]
public IActionResult Login([FromForm] string provider)
{
string redirect_uri = Url.Action("Index", "Home");
return Challenge(new AuthenticationProperties() { RedirectUri = redirect_uri }, provider);
}
我不知道是否可以修改或配置 Challenge
以允许此行为。我在 AuthenticationProperties class 中没有看到任何可以使用的 属性。我最初尝试为其他提供者创建另一个 Controller/Action,但结果是一样的。
我们将不胜感激。
只要用户的会话 cookie 有效,您就可以使用多种身份验证方案对其进行身份验证并随时访问这些声明。
But when I login using Twitter, my current session is lost and all the Claims from Twitch were removed and replaced by Twitter Claims.
发生这种情况是因为您试图使用 Cookie
方案来保存 Twitter 和 Twitch 的会话 cookie。当您使用一个登录时,它会覆盖另一个。
要解决此问题,您需要为每个单独的登录选项添加单独的 cookie。
services.AddAuthentication()
.AddCookie("GoogleSession")
.AddCookie("GithubSession")
.AddGoogle(
options => {
// set the app credentials
Configuration.GetSection("Google").Bind(options);
// save session to this cookie
options.SignInScheme = "GoogleSession";
})
.AddGitHub(
options => {
// set the app credentials
Configuration.GetSection("Github").Bind(options);
// save session to this cookie
options.SignInScheme = "GithubSession";
});
然后发出质询以强制用户登录:
[AllowAnonymous]
[HttpGet("login-google")]
public ActionResult LoginGoogle()
{
return Challenge(
new AuthenticationProperties
{
RedirectUri = Url.Action("WhoAmI"),
}, GoogleDefaults.AuthenticationScheme
);
}
[AllowAnonymous]
[HttpGet("login-github")]
public ActionResult LoginGithub()
{
return Challenge(
new AuthenticationProperties
{
RedirectUri = Url.Action("WhoAmI"),
}, GitHubAuthenticationDefaults.AuthenticationScheme
);
}
然后,您可以随时对用户进行身份验证以读取和解析 cookie 以访问声明:
[AllowAnonymous]
[HttpGet("me")]
public async Task<ActionResult> WhoAmI()
{
var googleResult = await HttpContext.AuthenticateAsync(GoogleDefaults.AuthenticationScheme);
if (googleResult.Succeeded)
{
var googlePrincipal = googleResult.Principal;
// ... use google claims
User.AddIdentity((ClaimsIdentity)googlePrincipal.Identity);
}
var githubResult = await HttpContext.AuthenticateAsync(GitHubAuthenticationDefaults.AuthenticationScheme);
if (githubResult.Succeeded)
{
var githubPrincipal = githubResult.Principal;
// ... use google claims
User.AddIdentity((ClaimsIdentity)githubPrincipal.Identity);
}
return Ok(
User.Identities.Select(
id => new
{
id.AuthenticationType,
Claims = id.Claims.Select(c => new { c.Type, c.Value })
}
)
.ToList()
);
现在,当我访问 /me
时,我得到了所有会话中所有声明的列表:
[
{
"authenticationType": null,
"claims": []
},
{
"authenticationType": "Google",
"claims": [
{
"type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
"value": "123131231231312123123123"
},
{
"type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
"value": "My Fullname"
},
{
"type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname",
"value": "MyName"
},
{
"type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname",
"value": "MyLastname"
},
{
"type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"value": "my@gmail.com"
}
]
},
{
"authenticationType": "GitHub",
"claims": [
{
"type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
"value": "1313123123"
},
{
"type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
"value": "abdusco"
},
{
"type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"value": "my@email.com"
},
{
"type": "urn:github:name",
"value": "my name"
},
{
"type": "urn:github:url",
"value": "https://api.github.com/users/abdusco"
}
]
}
]
使用多种身份验证方案手动对用户进行身份验证有点繁琐。我们可以让 ASP.NET Core 为我们做。
定义接受多个身份验证方案的授权策略。
services.AddAuthorization(
options => options.DefaultPolicy = new AuthorizationPolicyBuilder(
GoogleDefaults.AuthenticationScheme,
GitHubAuthenticationDefaults.AuthenticationScheme
).RequireAuthenticatedUser()
.Build()
);
现在,当您使用 [Authorize]
修饰操作时(并在需要时指定策略名称),HttpContext.User
将包含所有会话的身份和声明。
[Authorize]
[HttpGet("me")]
public async Task<ActionResult> WhoAmI()
{
return Ok(
// user has claims from all sessions
User.Identities.Select(
id => new
{
id.AuthenticationType,
Claims = id.Claims.Select(c => new { c.Type, c.Value })
}
)
.ToList()
);
}
这与之前的输出相同,但没有样板文件。