【问题标题】:IdentityServer4 authenticating against an external apiIdentityServer4 针对外部 api 进行身份验证
【发布时间】:2020-07-10 21:59:07
【问题描述】:

我们需要根据外部 API 对 IdentityServer4 中的用户进行身份验证。场景是这样的:

  1. 用户访问 Javascript 客户端应用程序并单击登录按钮以重定向到 IdentityServer 登录页面(与文档中提供的完全相同的客户端 here
  2. 用户输入他们的用户名(电子邮件)和密码

  3. IdentityServer4 连接到外部 API 以验证凭据

  4. 用户被重定向回 JavaScript 应用程序

在使用快速入门中提供的 TestUser 时,上述过程非常完美。但是,当使用 API 时,登录页面会重置并且不会将用户重定向回 JavaScript 客户端。唯一的变化是下面的代码和 IProfileService 的自定义实现。

以下是登录操作中的自定义代码(仅显示相关部分):

            var apiClient = _httpClientFactory.CreateClient("API");
            var request = new HttpRequestMessage(HttpMethod.Post, "/api/auth");

            var loginModel = new LoginModel
            {
                Email = model.Email,
                Password = model.Password
            };
            var content = new StringContent(JsonConvert.SerializeObject(loginModel), 
                                                Encoding.UTF8, "application/json");

            request.Content = content;

            HttpResponseMessage result = await apiClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);

            var loginStatus = JsonConvert.DeserializeObject<ApiLoginStatus>(
                                    await result.Content.ReadAsStringAsync());

            if (loginStatus.LoginSuccess)
            {
                await _events.RaiseAsync(new UserLoginSuccessEvent(model.Email, model.Email, loginStatus.Name, clientId: context?.ClientId));

                AuthenticationProperties props = null;
                if (AccountOptions.AllowRememberLogin && model.RememberLogin)
                {
                    props = new AuthenticationProperties
                    {
                        IsPersistent = true,
                        ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
                    };
                };

                var user = new IdentityServerUser(loginStatus.SubjectId)
                {
                    DisplayName = loginStatus.Name
                };

                await HttpContext.SignInAsync(user, props);
                if (context != null)
                {
                    if (await _clientStore.IsPkceClientAsync(context.ClientId))
                    {
                        return View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl });
                    }

                    return Redirect(model.ReturnUrl);
                }

代码实际上命中了返回 View() 路径,但由于某种原因它重置并再次显示登录页面。

Startup.cs 中的代码:

var builder = services.AddIdentityServer()
            .AddInMemoryIdentityResources(Config.Ids)
            .AddInMemoryApiResources(Config.Apis)
            .AddInMemoryClients(Config.Clients) 
            .AddProfileService<ProfileService>()
            .AddDeveloperSigningCredential();

ProfileService.cs 中的代码:

public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
    var profile = await GetUserProfile(context.Subject.GetSubjectId());

    var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Email, profile.Email),
            new Claim(ClaimTypes.Name, profile.Name)
        };

    context.IssuedClaims.AddRange(claims);
}

public async Task IsActiveAsync(IsActiveContext context)
{
    var profile = await GetUserProfile(context.Subject.GetSubjectId());
    context.IsActive = (profile != null);
}

网上有多个来源展示了如何使用自定义商店进行身份验证,但它们似乎都使用 ResourceOwnerPasswordValidator。如果有人能指出这里缺少什么,那将有很大帮助。谢谢。

【问题讨论】:

  • 鉴于您说它正在访问“重定向”视图,并且该视图非常简单(只是元刷新),您是否确认传入的 ReturnUrl 值是您所期望的?您可能希望使用 Fiddler 之类的工具查看网络流量,以确保实际上只发生了一个重定向。有没有可能它实际上正确地将您重定向回您的 SPA,然后以某种方式将您弹回登录页面(在重定向循环中)?
  • @BryanLewis 感谢您的回复。我确实检查了重定向,一切都设置正确。这个问题原来是下面的答案中提到的其他问题。

标签: authentication asp.net-core identityserver4


【解决方案1】:

所以问题变得非常简单。在 Startup.cs 中设置 IdentityServer 时,我们错过了删除 builder.AddTestUsers(TestUsers.Users) 行。

查看代码here,结果发现该行使用测试用户配置文件服务覆盖了我们的配置文件服务。删除该行解决了问题。

【讨论】:

    猜你喜欢
    • 2016-01-17
    • 2019-04-12
    • 2018-07-19
    • 2019-05-08
    • 2020-04-22
    • 1970-01-01
    • 1970-01-01
    • 2016-11-01
    • 1970-01-01
    相关资源
    最近更新 更多