asp.net-mvc - 如何在多个网站 OpenIdConnect Azure AD B2C 中登录用户?
问题描述
我想OpenIdConnectAuthentication
用于多个项目。我正在使用以下代码对我的用户进行身份验证,website1
这工作正常,但是如何在website2
同一个访问令牌中访问和管理它以对另一个网站中的用户进行身份验证?
public void ConfigureAuth(IAppBuilder app) {
// Required for Azure webapps, as by default they force TLS 1.2 and this project attempts 1.0
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions {
// Generate the metadata address using the tenant and policy information
MetadataAddress = String.Format(Globals.WellKnownMetadata, Globals.Tenant, Globals.DefaultPolicy),
// These are standard OpenID Connect parameters, with values pulled from web.config
ClientId = Globals.ClientId,
RedirectUri = Globals.RedirectUri,
PostLogoutRedirectUri = Globals.RedirectUri,
AuthenticationType = Globals.DefaultPolicy,
// Specify the callbacks for each type of notifications
Notifications = new OpenIdConnectAuthenticationNotifications {
RedirectToIdentityProvider = OnRedirectToIdentityProvider,
AuthorizationCodeReceived = OnAuthorizationCodeReceived,
AuthenticationFailed = OnAuthenticationFailed,
},
Scope = "openid",
ResponseType = "id_token",
// Specify the claim type that specifies the Name property.
TokenValidationParameters = new TokenValidationParameters {
NameClaimType = "name",
SaveSigninToken = true,
ValidateIssuer = false
}//,
// Specify the scope by appending all of the scopes requested into one string (separated by a blank space)
//Scope = $"openid profile offline_access {Globals.ReadTasksScope} {Globals.WriteT//asksScope}"
});
注意:网站 1 是 MVC 项目,网站 2 是用于验证 api 调用的 API 项目。我们该如何管理呢?
解决方案
我可以看到您需要更改一些内容才能使其正常工作。首先,由于这是您正在使用的服务器应用程序,您可以使用authorization code flow
或hybrid flow
来验证用户身份。
可以这样实现:
// for authorization code flow
ResponseType = "code",
// for hybrid flow
ResponseType = "code id_token"
请注意,在使用这两个流程时,您还需要提供客户端密码。
一旦用户在身份提供者上通过身份验证,它将使用授权代码重定向回您的应用程序,您可以使用该授权代码将其交换为 access_token 和 refresh_token。
所以,在OnRedirectToIdentityProvider
方法中
OnAuthorizationCodeReceived = async n =>
{
// swap authorization code for an access token
// i think for AAD B2C the endpoint for retreiving tokens is (not sure though you'll need to double check)
// https://<tenant-name>.b2clogin.com/<tenant-name>.onmicrosoft.com/<policy-name>/oauth2/v2.0/token
var tokenClient = new TokenClient("http://localhost:5000/connect/token", Globals.ClientId, Globals.ClientSecret);
var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(
n.Code, n.RedirectUri);
// use access token to call the user info endpoint
// also check what the userinfo endpoint URL is
var userInfoClient = new UserInfoClient("http://localhost:5000/connect/userinfo");
var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);
// create a new identity using the claims from the user info endpoint (including tokens)
var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
id.AddClaims(userInfoResponse.Claims);
id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
n.AuthenticationTicket = new AuthenticationTicket(
new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType),
n.AuthenticationTicket.Properties);
}
您可以从元数据端点获取所需的所有 URL。
完成所有这些操作后,访问令牌将成为用户声明的一部分,并将存储在身份验证 cookie 中。
然后,一旦你完成了所有这些,你就可以使用 access_token 来调用你JwtBearerAuthentication
设置的 API 上提供的受保护 API,方法是在对所述 API 的请求的标头中提供 access_token。
该类TokenClient
是名为 IdentityModel 的库的一部分,它可以更轻松地与 openidconnect 端点进行通信
推荐阅读
- javascript - Nightwatch JS 中的异步命令执行
- r - 有没有办法创建一个循环来查找数据集中的特定方法?
- python - 烧瓶如何在扩展模板中获取变量
- python - 代码没有读取 Elif 或 Else 语句
- javascript - 静态包含 HTML 代码而不是在实时环境中的方法?
- visual-studio-code - 如果 VS Code 扩展选项卡没有打开,有没有办法打开它?
- python - 将 .TXT 数据作为一列拆分为“n”行,如 Python 中的 CSV?
- c - 编写一个文本文件以在 C 程序中保存向量和其他变量
- javascript - 类组件不等待函数返回
- flutter - 有没有办法为 Flutter StatefulBuilder 设置一个定期计时器,每 1 秒用 setState() 更新一次?