Identity Server 4 - 资源所有者密码授予和 Google 身份验证
Identity Server 4 - Resource Owner Password Grant and Google Authentication
我有一个应用程序当前使用资源所有者密码授权类型来允许用户通过单页应用程序登录。身份服务器目前托管在与 Web API 相同的项目中。但是,我们想添加用户使用他们的 Google 帐户注册/登录的功能。目前,用户数据存储在表中并由 ASP.NET Core Identity 管理。
有没有办法让 'local' 的用户在应用程序中既可以使用资源所有者密码授予类型,又可以通过 Google 启用第三方身份验证?目前,我们使用用户名和密码访问 Identity Server 令牌端点,并将令牌存储在浏览器中。然后它被传递到任何需要授权的端点。在集成 Google 身份验证和检索 Google 令牌时,同样的流程是否仍然有效?
所有功劳都归功于 Behrooz Dalvandi,因为 this 太棒了 post。
此问题的解决方案是创建自定义授权并实施 IExtensionGrantValidator。
public class GoogleGrant : IExtensionGrantValidator
{
private readonly IGoogleService _googleService;
private readonly IAccountService _accountService;
public GoogleGrant(IGoogleService googleService, IAccountService accountService)
{
_googleService = googleService;
_accountService = accountService;
}
public string GrantType
{
get
{
return "google_auth";
}
}
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
var userToken = context.Request.Raw.Get("id_token");
if (string.IsNullOrEmpty(userToken))
{
//You may want to add some claims here.
context.Result = new GrantValidationResult(TokenErrors.InvalidGrant, null);
return;
}
//Validate ID token
GoogleJsonWebSignature.Payload idTokenData = await _googleService.ParseGoogleIdToken(userToken);
if (idTokenData != null)
{
//Get user from the database.
ApplicationUser user = await _accountService.FindByEmail(idTokenData.Email);
if(user != null)
{
context.Result = new GrantValidationResult(user.Id, "google");
return;
}
else
{
return;
}
}
else
{
return;
}
}
}
在启动中配置这个验证器
var builder = services.AddIdentityServer()
.AddInMemoryIdentityResources(Config.Ids)
.AddInMemoryApiResources(Config.Apis)
.AddInMemoryClients(Config.Clients)
.AddResourceOwnerValidator<CustomResourceOwnerPasswordValidator>()
.AddExtensionGrantValidator<GoogleGrant>();//Custom validator.
最后但并非最不重要的一点。
在配置文件中添加以下代码。注意 'google_auth' 授权类型。
new Client
{
ClientId = "resourceownerclient",
AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials.Append("google_auth").ToList(),
AccessTokenType = AccessTokenType.Jwt,
AccessTokenLifetime = 3600,
IdentityTokenLifetime = 3600,
UpdateAccessTokenClaimsOnRefresh = true,
SlidingRefreshTokenLifetime = 30,
AllowOfflineAccess = true,
RefreshTokenExpiration = TokenExpiration.Absolute,
RefreshTokenUsage = TokenUsage.OneTimeOnly,
AlwaysSendClientClaims = true,
Enabled = true,
ClientSecrets= new List<Secret> { new Secret("dataEventRecordsSecret".Sha256()) },
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.OfflineAccess,
"api1"
}
}
我有一个应用程序当前使用资源所有者密码授权类型来允许用户通过单页应用程序登录。身份服务器目前托管在与 Web API 相同的项目中。但是,我们想添加用户使用他们的 Google 帐户注册/登录的功能。目前,用户数据存储在表中并由 ASP.NET Core Identity 管理。
有没有办法让 'local' 的用户在应用程序中既可以使用资源所有者密码授予类型,又可以通过 Google 启用第三方身份验证?目前,我们使用用户名和密码访问 Identity Server 令牌端点,并将令牌存储在浏览器中。然后它被传递到任何需要授权的端点。在集成 Google 身份验证和检索 Google 令牌时,同样的流程是否仍然有效?
所有功劳都归功于 Behrooz Dalvandi,因为 this 太棒了 post。
此问题的解决方案是创建自定义授权并实施 IExtensionGrantValidator。
public class GoogleGrant : IExtensionGrantValidator
{
private readonly IGoogleService _googleService;
private readonly IAccountService _accountService;
public GoogleGrant(IGoogleService googleService, IAccountService accountService)
{
_googleService = googleService;
_accountService = accountService;
}
public string GrantType
{
get
{
return "google_auth";
}
}
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
var userToken = context.Request.Raw.Get("id_token");
if (string.IsNullOrEmpty(userToken))
{
//You may want to add some claims here.
context.Result = new GrantValidationResult(TokenErrors.InvalidGrant, null);
return;
}
//Validate ID token
GoogleJsonWebSignature.Payload idTokenData = await _googleService.ParseGoogleIdToken(userToken);
if (idTokenData != null)
{
//Get user from the database.
ApplicationUser user = await _accountService.FindByEmail(idTokenData.Email);
if(user != null)
{
context.Result = new GrantValidationResult(user.Id, "google");
return;
}
else
{
return;
}
}
else
{
return;
}
}
}
在启动中配置这个验证器
var builder = services.AddIdentityServer()
.AddInMemoryIdentityResources(Config.Ids)
.AddInMemoryApiResources(Config.Apis)
.AddInMemoryClients(Config.Clients)
.AddResourceOwnerValidator<CustomResourceOwnerPasswordValidator>()
.AddExtensionGrantValidator<GoogleGrant>();//Custom validator.
最后但并非最不重要的一点。 在配置文件中添加以下代码。注意 'google_auth' 授权类型。
new Client
{
ClientId = "resourceownerclient",
AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials.Append("google_auth").ToList(),
AccessTokenType = AccessTokenType.Jwt,
AccessTokenLifetime = 3600,
IdentityTokenLifetime = 3600,
UpdateAccessTokenClaimsOnRefresh = true,
SlidingRefreshTokenLifetime = 30,
AllowOfflineAccess = true,
RefreshTokenExpiration = TokenExpiration.Absolute,
RefreshTokenUsage = TokenUsage.OneTimeOnly,
AlwaysSendClientClaims = true,
Enabled = true,
ClientSecrets= new List<Secret> { new Secret("dataEventRecordsSecret".Sha256()) },
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.OfflineAccess,
"api1"
}
}