在通过客户端应用程序和Identity Server进行身份验证之后,我想出了正确的方法来将某些角色附加到客户端应用程序用户。我已经做到了,但是我想听听有没有更好的方法来解决这个问题,因为我认为这不是正确的方法。
有用于验证用户身份的客户端应用程序,Web API服务和Identity Server。我使用多种方式对用户进行身份验证(外部提供商-谷歌身份验证和密码身份验证)。所以电流 就像这样:
用户启动Web应用程序,并打开身份验证窗口。对于此示例,我将使用google身份验证。因此,现在请点击“使用Google登录”,并在其中提供用于输入电子邮件和密码的字段。这就是身份验证开始的地方。
因此,在前端,有一些javascript代码用于与Google api通信,并且当用户提交其凭据时,该API正在被调用,并返回给我我现在用来验证客户端身份的google id令牌。身份验证方法如下:
public async Task TryToAuthenticateWithGoogleToken(string accessToken, string email)
{
if (_identitySettings == null)
throw new ArgumentNullException(nameof(_identitySettings));
if (_httpContext == null)
throw new ArgumentNullException(nameof(_httpContext));
if (string.IsNullOrEmpty(accessToken))
throw new Exception("Id token not provided.");
if (String.IsNullOrEmpty(email))
throw new ArgumentNullException("User email not provided.");
var client = new HttpClient();
string identityServerAddress = _identitySettings.Authority.TrimEnd('/');
string identittyServerEndpoint = identityServerAddress + "/connect/token";
// HERE I CALL IDENTITY SERVER FOR AUTEHNICATION
var response = await client.RequestTokenAsync(new TokenRequest()
{
Address = identittyServerEndpoint,
GrantType = "external",
ClientId = _identitySettings.ClientId,
ClientSecret = _identitySettings.ClientSecret,
Parameters =
{
{"provider", "google"},
{"external_token", accessToken }
}
});
if (response.IsError)
throw new Exception(response.ErrorDescription);
// Remove old
if (_usersTokenStore.Keys.Contains(email))
_usersTokenStore.Remove(email);
// Add new into collection for retreiving token later from memory
var singleUserTokenStore = new SingleUserTokenStore(response.AccessToken, response.RefreshToken, response.ExpiresIn);
singleUserTokenStore.TokenVerified = true;
_usersTokenStore.Add(email, singleUserTokenStore);
// Authenticate current user
var authProperties = new AuthenticationProperties
{
ExpiresUtc = DateTimeOffset.UtcNow.AddDays(1),
IsPersistent = true
};
var userInfo = await GetUserInfo(singleUserTokenStore.AccessToken);
var claimsIdentites = new ClaimsIdentity(userInfo.Claims, "Custom", "name", "role");
await _httpContext.HttpContext.SignInAsync("Cookies", new ClaimsPrincipal(claimsIdentites), authProperties);
}
如您所见,我做了两件事。第一个是从Identity Server请求使用Google ID令牌凭证和电子邮件地址对用户进行身份验证。在Identity Server应用程序中,如果验证授权成功,则可以成功;如果将某些角色附加到当前正在发出请求的用户,则第二个验证。我有一个数据库,用于存储允许的用户及其角色(自定义角色)列表,因此,当身份验证成功时,我还将这些自定义角色附加到User,以便稍后向API提出请求时授权一些操作。
所以,我的问题是部分在注释后// //在提供的代码中验证当前用户。在那部分代码中,因为我根本不知道在身份验证时如何持久保留该用户及其附加在Identity Server中的角色,所以我再次调用了Identity Server,但现在使用/ userinfo端点为我提供了用户声明,角色等等,之后我打电话给SignInAsync,以将用户信息从现在到应用程序中的用户会话结束。
那么,有没有一种方法可以处理IdentityServer上的SignInAsync问题(在身份验证时使用ValidateAsync方法),并在再次调用IS以获取用户信息然后使这些新角色和声明保持不变时跳过此额外步骤?希望我足够清楚。