首页 > 解决方案 > 静默登录身份服务器 4 出现不适当的错误响应问题

问题描述

我正在尝试在 oidc-client 中实现静默登录以与 Angular 9 一起使用,并希望用户在电子邮件验证后在 ASP.NET Core 应用程序中注册后自动登录。

除了最后一步,我已经完成了所有工作,即得到实际错误作为响应,以便根据可能的错误为客户端显示适当的消息。有两个可能的错误需要处理:

1) 短信一次码不正确;

2) 一个时间码过期。

这就是为什么我必须在服务器端传递准确的代码描述,然后在客户端处理它。

客户端代码:

export function getClientSettings(identityBaseUrl: string): UserManagerSettings {
  const baseUrl = window.location.origin;

  return {
    authority: identityBaseUrl,
    client_id: 'test.admin.spa',
    redirect_uri: `${baseUrl}/auth-callback`,
    post_logout_redirect_uri: baseUrl,
    response_type: 'id_token token',
    scope: 'openid profile test.admin.api',
    filterProtocolClaims: true,
    loadUserInfo: true,
    userStore: new WebStorageStateStore({ store: window.localStorage }),
    automaticSilentRenew: true,
    silent_redirect_uri: `${baseUrl}/silent-refresh.html`,
  };
}

这是我在自定义 AuthorizeInteractionResponseGenerator 中覆盖 ProcessInteractionAsync 方法的方式:

        public override async Task<InteractionResponse> ProcessInteractionAsync(ValidatedAuthorizeRequest request, ConsentResponse consent = null)
        {
            var processOtcRequest = !_httpContextAccessor.HttpContext.User.Identity.IsAuthenticated;

            var acrValues = request.GetAcrValues().ToList();
            if (acrValues.Any() == false)
            {
                processOtcRequest = false;
            }

            var userEmailAcr = acrValues.FirstOrDefault(x => x.StartsWith("user_email"));
            var oneTimeCodeAcr = acrValues.FirstOrDefault(x => x.StartsWith("one_time_code"));

            if (userEmailAcr != null && oneTimeCodeAcr != null && processOtcRequest)
            {
                var userEmail = userEmailAcr.Split(':').Last();
                var oneTimeCode = oneTimeCodeAcr.Split(':').Last();
                var currDate = DateTime.UtcNow;

                var user = await _users.GetUserByEmailAsync(userEmail);

                if (user != null)
                {
                    // 1) texted one time code is not correct
                    if (user.OneTimeCode != oneTimeCode)
                    {
                        return GetErrorResponse("invalid_code");
                    }

                    // 2) one time code is expired
                    if (user.OneTimeCodeExpiredAt < currDate)
                    {
                        return GetErrorResponse("expired_code");
                    }

                    user.EmailConfirmed = true;
                    user.OneTimeCode = null;
                    user.OneTimeCodeExpiredAt = null;
                    user.SecurityStamp = Guid.NewGuid().ToString().ToUpper();
                    user.ConcurrencyStamp = Guid.NewGuid().ToString().ToUpper();
                    user.NormalizedEmail = user.Email.ToUpper();
                    user.NormalizedUserName = user.UserName.ToUpper();

                    if (request != null)
                    {
                        request.Subject = new ClaimsPrincipal({{building my principal}});
                    }

                    await _users.UpdateAsync(user);
                    await _users.CommitAsync();

                    var props = new AuthenticationProperties
                    {
                        ExpiresUtc = DateTimeOffset.UtcNow.AddHours(2),
                        AllowRefresh = true,
                        RedirectUri = request.RedirectUri
                    };

                    await _loginService.SignInAsync(user, props);

                    return new InteractionResponse
                    {
                        IsLogin = false,
                        IsConsent = false
                    };
                }

            }

            return await base.ProcessInteractionAsync(request, consent);
        }

        private InteractionResponse GetErrorResponse(string errorCode)
        {
            return new InteractionResponse
            {
                Error = errorCode
            };
        }

因此,它看起来很合乎逻辑,但是当我发短信一次代码不正确并尝试在客户端处理错误时:

  sendRequest(postModel: RegisterCompanyConfirbut mationViewModel) {
    this.authService.startSilentAuthentication(this.userEmail, this.form.value.oneTimeCode).then(
      (result) => {
        this.router.navigate(['', 'company-details']);
      },
      (error) => {
        console.log(error);
      }
    );
  }

我在错误部分观察到这样奇怪的事情:

窗口超时异常

另一方面,当我查看网络部分并单击此记录时

网络部分错误

我看到我的错误代码仍然被发送:

预期错误

我看到这样的简单返回错误

            return new InteractionResponse
            {
                Error = errorCode
            };

没有给我带来我预期的错误(它只给我带来了“框架窗口超时”)。

目的是在客户端部分中使用一个时间码检索有关错误的信息:

      (error) => {
        console.log(error);
      }

也许有人遇到过这样的问题?任何指点都将不胜感激 - 这个简单的问题让我大吃一惊..提前致谢!

标签: angularasp.net-coreerror-handlingidentityserver4openid-connect

解决方案


推荐阅读