【问题标题】:IdentityServer4 and external oauth privider: The oauth state was missing or invalidIdentityServer4 和外部 oauth privider:oauth 状态丢失或无效
【发布时间】:2022-02-07 14:21:25
【问题描述】:

我正在尝试在 IdentityServer4 中实现外部 oauth 身份验证。 所有身份验证请求都成功。我在应用程序日志中有一条消息 AuthenticationScheme: Identity.External signed in.。 但是,当身份验证过程尝试返回到 ExternalLoginCallback 操作时,它会在 HTTP 302 之后出现错误 500(oauth 状态丢失或无效)。 Screenshot is here

  1. 结果 302。请求 https://localhost:5999/Account/ExternalLoginCallback?state=xxx&code=xxx&session_state=xxx
  2. 然后请求转到 https://localhost:5999/Account/ExternalLoginCallback(不带任何参数)

我的 IS4 启动

IdentityServerConfiguration.AddIdentityServer(services, _configuration);

        services
            .AddAuthentication()
            .AddTinkoff(_configuration)
            .AddSber(_configuration)
            .AddEsia(_configuration);

AddTinkoff 扩展方法:

public static AuthenticationBuilder AddTinkoff(this AuthenticationBuilder builder, IConfiguration config)
    {
        return builder.AddOAuth("TinkoffId", "Tinkoff ID", options =>
        {
            options.AuthorizationEndpoint = "https://id.tinkoff.ru/auth/authorize?response_type=code";
            options.TokenEndpoint = "https://id.tinkoff.ru/auth/token?grant_type=authorization_code";
            options.UserInformationEndpoint = "https://id.tinkoff.ru/userinfo/userinfo";
            options.CallbackPath = "/Account/ExternalLoginCallback";
            options.ClientId = "xxx";
            options.ClientSecret = "xxxx";
            options.SaveTokens = true;
            options.SignInScheme = IdentityConstants.ExternalScheme;
            options.BackchannelHttpHandler = new TinkoffAuthorizingHandler(new HttpClientHandler(), options);
            options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "name");
            options.ClaimActions.MapJsonKey(ClaimTypes.Email, "email", ClaimValueTypes.Email);
            options.ClaimActions.MapAll();


            options.Events = new OAuthEvents
            {
                 
                OnCreatingTicket = async context =>
                {
                    var request = new HttpRequestMessage(HttpMethod.Post, context.Options.UserInformationEndpoint);
                    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);

                    request.Headers.Add(
                       HttpRequestHeader.ContentType.ToString(),
                       "application/x-www-form-urlencoded"
                    );

                    request.Content = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>() {
                            new KeyValuePair<string, string>("client_id",options.ClientId),
                            new KeyValuePair<string, string>("client_secret",options.ClientSecret)
                        });

                    var response = await context.Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, context.HttpContext.RequestAborted);
                    response.EnsureSuccessStatusCode();

                    var user = JsonDocument.Parse(await response.Content.ReadAsStringAsync());

                    context.RunClaimActions(user.RootElement);
                },
                //OnTicketReceived = async context =>
                //{
                //    context.HttpContext.User = context.Principal;
                //    //context.SkipHandler();
                //}
            };
            //options.Scope.Add("profile");
            //options.Scope.Add("email");
            //options.Scope.Add("phone");
        });
    }

我的 ExternalLogin 操作:

[HttpPost]
    [HttpGet]
    [AllowAnonymous]
    public IActionResult ExternalLogin(string provider, string returnUrl = null)
    {
        _logger.LogInformation($"External login fired. ReturnUrl='{returnUrl}'. Provider='{provider}'");
        var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
        var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
        return Challenge(properties, provider);
    }

在调试时未触发 ExternalLoginCallback 操作。

我做错了什么。为什么请求在没有参数的情况下重定向到自身?

谢谢。

【问题讨论】:

    标签: oauth identityserver4 .net-5


    【解决方案1】:

    我为我解决了一个问题。 我加了

    OnTicketReceived = async context =>
                    {
                        context.HttpContext.User = context.Principal;
                        //context.SkipHandler();
                        context.ReturnUri += $"/{context.Request.QueryString}";
                    }
    

    现在它按预期工作了

    【讨论】:

      猜你喜欢
      • 2021-04-26
      • 2023-01-31
      • 2017-09-22
      • 2020-04-14
      • 2021-11-06
      • 2019-02-02
      • 2021-11-12
      • 1970-01-01
      • 2021-12-27
      相关资源
      最近更新 更多