gpt4 book ai didi

c# - 手动生成 IdentityServer4 引用 token 并保存到 PersistedGrants 表

转载 作者:太空宇宙 更新时间:2023-11-03 12:05:05 26 4
gpt4 key购买 nike

我学会了IdentityServer4一个星期,并成功地使用 ResourceOwnedPassword 实现了一个简单的身份验证流程流。

现在,我正在按照 this tutorial 实现 使用 IdentityServer4 的 Google 身份验证

这就是我正在做的:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
//...

const string connectionString = @"Data Source=.\SQLEXPRESS;database=IdentityServer4.Quickstart.EntityFramework-2.0.0;trusted_connection=yes;";
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddProfileService<IdentityServerProfileService>()
.AddResourceOwnerValidator<IdentityResourceOwnerPasswordValidator>()
// this adds the config data from DB (clients, resources)
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
{
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
};

})
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 30;
});

// Add jwt validation.
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddIdentityServerAuthentication(options =>
{
// base-address of your identityserver
options.Authority = "https://localhost:44386";

options.ClaimsIssuer = "https://localhost:44386";

// name of the API resource
options.ApiName = "api1";
options.ApiSecret = "secret";

options.RequireHttpsMetadata = false;

options.SupportedTokens = SupportedTokens.Reference;

});

//...
}

** Google Controller (用于处理从 Google ** 返回的 token

public class GLoginController : Controller
{
#region Properties

private readonly IPersistedGrantStore _persistedGrantStore;

private readonly IUserFactory _userFactory;

private readonly IBaseTimeService _baseTimeService;

private readonly ITokenCreationService _tokenCreationService;

private readonly IReferenceTokenStore _referenceTokenStore;

private readonly IBaseEncryptionService _baseEncryptionService;

#endregion

#region Constructor

public GLoginController(IPersistedGrantStore persistedGrantStore,
IBaseTimeService basetimeService,
ITokenCreationService tokenCreationService,
IReferenceTokenStore referenceTokenStore,
IBaseEncryptionService baseEncryptionService,
IUserFactory userFactory)
{
_persistedGrantStore = persistedGrantStore;
_baseTimeService = basetimeService;
_userFactory = userFactory;
_tokenCreationService = tokenCreationService;
_referenceTokenStore = referenceTokenStore;
_baseEncryptionService = baseEncryptionService;
}

#endregion

#region Methods

[HttpGet("login")]
[AllowAnonymous]
public IActionResult Login()
{
var authenticationProperties = new AuthenticationProperties
{
RedirectUri = "/api/google/handle-external-login"
};

return Challenge(authenticationProperties, "Google");
}

[HttpGet("handle-external-login")]
//[Authorize("ExternalCookie")]
[AllowAnonymous]
public async Task<IActionResult> HandleExternalLogin()
{
//Here we can retrieve the claims
var authenticationResult = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
var principal = authenticationResult.Principal;

var emailAddress = principal.FindFirst(ClaimTypes.Email)?.Value;
if (string.IsNullOrEmpty(emailAddress))
return NotFound(new ApiMessageViewModel("Email is not found"));

// Find user by using username.
var loadUserConditions = new LoadUserModel();
loadUserConditions.Usernames = new HashSet<string> { emailAddress };
loadUserConditions.Pagination = new PaginationValueObject(1, 1);

// Find users asynchronously.
var loadUsersResult = await _userFactory.FindUsersAsync(loadUserConditions);
var user = loadUsersResult.FirstOrDefault();

// User is not defined.
if (user == null)
{
user = new User(Guid.NewGuid(), emailAddress);
user.Email = emailAddress;
user.HashedPassword = _baseEncryptionService.Md5Hash("abcde12345-");
user.JoinedTime = _baseTimeService.DateTimeUtcToUnix(DateTime.UtcNow);
user.Kind = UserKinds.Google;
user.Status = UserStatuses.Active;

//await _userFactory.AddUserAsync(user);
}
else
{
// User is not google account.
if (user.Kind != UserKinds.Google)
return Forbid("User is not allowed to access system.");
}

var token = new Token(IdentityServerConstants.TokenTypes.IdentityToken);
var userCredential = new UserCredential(user);

token.Claims = userCredential.GetClaims();
token.AccessTokenType = AccessTokenType.Reference;
token.ClientId = "ro.client";
token.CreationTime = DateTime.UtcNow;
token.Audiences = new[] {"api1"};
token.Lifetime = 3600;


return Ok();
}

#endregion
}

一切都很好,我可以得到从 Google OAuth2 返回的声明,使用 Google 电子邮件地址在数据库中查找用户并在他们没有任何帐户时注册他们。

我的问题是:如何使用我在 HandleExternalLogin 中收到的 Google OAuth2 声明?方法生成一个Reference Token,保存到PersistedGrants表并返回给客户端。

这意味着当用户访问 https://localhost:44386/api/google/login ,在被重定向到谷歌同意屏幕后,他们可以收到 access_token , refresh_tokenIdentityServer4 生成.

谢谢,

最佳答案

  • 在 IdentityServer 中, token 的种类(jwt of reference)是可配置 for each client (应用程序),请求 token 。
  • AccessTokenType.ReferenceTokenTypes.AccessToken 有效TokenTypes.IdentityToken 在您的代码段中。

一般来说,遵循 original quickstart 会更简单然后扩展 the generic code取决于您的需要。我现在在上面的代码片段中看到的只是您的特定内容,而不是默认部分,负责创建 IdSrv session 并重定向回客户端。

如果您仍然喜欢手动创建 token :

  • ITokenService 注入(inject)到您的 Controller 中。
  • 修复我上面提到的错误:TokenTypes.AccessToken 而不是 TokenTypes.IdentityToken
  • 调用 var tokenHandle = await TokenService.CreateAccessTokenAsync(token);

tokenHandlePersistedGrantStore

中的键

关于c# - 手动生成 IdentityServer4 引用 token 并保存到 PersistedGrants 表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55466479/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com