在AWS Lambda上登录后Identity Server 4不重定向

时间:2020-06-10 16:59:30

标签: identityserver4

在localhost上一切正常。

一旦部署到AWS Lambda,我注意到的第一个问题是返回URL缺少以正斜杠开头的“ connect / authorize / ...”而不是“ / connect / authorize”。 这是完整的网址“帐户/登录?ReturnUrl = connect%2Fauthorize%2Fcallback%3Fclient_id%3D89F3BD2C-C7FE-443C-B5AA-20241BB8A728%26nonce%3DyrOeuRsqk22SyZidU7gFPwydULf5ygpXH %%% F%_%2 %% F%_3 %% 26%A2 %% 2 %% 2%F3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D 2520token%26scope%3Dopenid%2520profile%2520offline_access%26state%3DyrOeuRsqk22SyZidU7gFPwydULf5ygpXH9nSGPUj“

所以我必须在代码中手动添加正斜杠。那么我可以看到用户已成功通过身份验证。在本地主机上,在响应标题中,我将获得两个set-cookie

Set-Cookie:idsrv.session = sK-Bo4lSJ3CS1289AC5aXw;路径= /; samesite = none

的Set-Cookie:idsrv = CfDJ8B3Fm0L2YmhJjEx10Gqzt669qjVDxEbr_Gi8Myuwq2YLZBBpQMzbwDK9ItkNMDWbXq46rXRsfC8FmXs28oFcIfhLpWg-6Yzyx1AutK5SoOvaZlvI3Y0Hmus0LKOXJCXXdBtiT1dlzr6BbEwH5TWPRhzRmfXGZRCDV2qS-azGMRfuXl-B-bPq_2Bb9a29VWw9rUMAXioXrhXq83BEEngi7UuAOZPfPu88QqTk55m4T4qJYD0X9lCJdiC33Z3IbmVq88TEYmDlzXvE2MGeloyVMg-GZzZj8JuPNuH6-qMLon55zBG4G-cEFh77lWkT3oGDu9sV6zBrSihljkfV87iMV7lQz0lTG3Db6fvqGJxQPmEOmX7-HBc_8jV5Jh5jznYckHyfgdIPaVrgG1dGe68FEyO1L0XkMCWNhZhcYET6IMAISmMAXKUXX6E3C90uSANo5VgumUe5qofdNzHBmloL9uc9fmpaWleMZg1SNPFI27SjQo2B4ZrDHDH5-R2uAqzRAQ;路径= /; samesite = none; httponly

但是在服务器上,我只有第一个

set-cookie:idsrv.session = GAAHJhReZicjWjNcMaN2eg;路径= /;安全; samesite = none

没有将第二个set-cookie传递回“ / connect / authorize”,它只是重定向回到登录页面。 我已经将samesite设置为none。 ID服务器位于https上,并且应该是安全的。

下面是代码

Startup.cs

    public void ConfigureServices(IServiceCollection services)
    {

        var builder = services.AddIdentityServer(options =>
            {
                options.Events.RaiseErrorEvents = true;
                options.Events.RaiseInformationEvents = true;
                options.Events.RaiseFailureEvents = true;
                options.Events.RaiseSuccessEvents = true;
                options.UserInteraction.LoginUrl = "/Account/Login";
                options.UserInteraction.LogoutUrl = "/Account/Logout";
                options.Authentication = new AuthenticationOptions()
                {
                    CookieLifetime = TimeSpan.FromHours(10), // ID server cookie timeout set to 10 hours
                    CookieSlidingExpiration = true
                };
            })
            .AddInMemoryIdentityResources(Config.Ids);

        builder.Services.ConfigureExternalCookie(options => {
            options.Cookie.IsEssential = true;
            options.Cookie.SameSite = (SameSiteMode)(-1); //SameSiteMode.Unspecified in .NET Core 3.1
        });

        builder.Services.ConfigureApplicationCookie(options => {
            options.Cookie.IsEssential = true;
            options.Cookie.SameSite = (SameSiteMode)(-1); //SameSiteMode.Unspecified in .NET Core 3.1
        });


        if (_environment.IsDevelopment())
        {
            builder.AddDeveloperSigningCredential();
        }
        else
        {
            var cert = new X509Certificate2(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Cert", Configuration.GetSection("AppSettings")["CertificateName"]),
                Configuration.GetSection("AppSettings")["CertificatePassword"]);
            builder.AddSigningCredential(cert);
        }
        services.AddTransient<IProfileService, ProfileService>();
        services.AddTransient<IClientStore, ClientService>();
        services.AddTransient<ICorsPolicyService, CorsService>();
        services.AddTransient<IPersistedGrantStore, PersistedGrantService>();
        services.AddTransient<IEventSink, SeqEventService>();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            //launched in debug build from VS2017
        #if DEBUG
            app.UseDeveloperExceptionPage();
        #endif
        }
        else
        {
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseExceptionHandler("/Error");
            app.UseHsts();
            app.UseStartUpWarmer<IEntityConfigurationApi<FilePurposeData>>(api =>
            {
                api.ListIdValueModels(new IdValueRequest()
                {
                    ValuePropertyName = "Name"
                });
            });
        }

        app.UseStaticFiles();
        app.UseRouting();
        app.UseIdentityServer();
        app.UseAuthorization();
        app.UseEndpoints(endPoints =>
        {
            endPoints.MapControllerRoute("default", "{controller=Home}/{action=Index}");
        });

        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger(opt =>
        {
            opt.RouteTemplate = "Help/swagger/{documentName}/swagger.json";
        });

        // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), 
        // specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/Help/swagger/v1/swagger.json", $"/{GetType().Namespace}");
            c.RoutePrefix = "Help";
        });
    }

在AccountController中

    [HttpPost]        
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Login(LoginInputModel model)
    {
        // check if we are in the context of an authorization request
        var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);

        // the user clicked the "cancel" button
        if (model.Button != "login")
        {
            if (context != null)
            {
                // if the user cancels, send a result back into IdentityServer as if they 
                // denied the consent (even if this client does not require consent).
                // this will send back an access denied OIDC error response to the client.
                await _interaction.GrantConsentAsync(context, ConsentResponse.Denied);

                //// we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                if (await _clientStore.IsPkceClientAsync(context.ClientId))
                {
                    // if the client is PKCE then we assume it's native, so this change in how to
                    // return the response is for better UX for the end user.
                    return View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl });
                }

                return Redirect(model.ReturnUrl);
            }
            else
            {
                // since we don't have a valid context, then we just go back to the home page
                return Redirect("~/");
            }
        }

        var errorMessage = string.Empty;
        if (ModelState.IsValid)
        {
            if (model.ReturnUrl.ToLower().StartsWith("connect/authorize"))
            {
                model.ReturnUrl = "/" + model.ReturnUrl;
            }
            try
            {
                var authResult = DoInService(svc =>
                {
                    return svc.AuthenticateUser(new AuthenticateUserRequest
                    {
                        LoginName = model.Username,
                        Password = model.Password
                    });
                });

                if (authResult?.IsAuthenticated == true)
                {
                    var lst = authResult.Claims
                        .Where(cl => cl.Type != "Organization")
                        .ToList();
                    var userId = lst.First(f => f.Type == "Payliance.UserIdentifier").Value;
                    await _events.RaiseAsync(new UserLoginSuccessEvent(model.Username, userId, model.Username, clientId: context?.ClientId));

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

                    // issue authentication cookie with subject ID and username
                    await HttpContext.SignInAsync(userId, model.Username, props);
                    Logger.LogItem("99999 - Authentication Cookie issued");
                    Logger.LogItem($"99999 - ReturnURL: {model.ReturnUrl}");

                    if (context != null)
                    {
                        Logger.LogItem("99999 - Redirect with context");
                        // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                        return Redirect(model.ReturnUrl);

                    }

                    // request for a local page
                    if (Url.IsLocalUrl(model.ReturnUrl))
                    {
                        Logger.LogItem("99999 - Redirect without context");
                        return Redirect(model.ReturnUrl);

                    }
                    else if (string.IsNullOrEmpty(model.ReturnUrl))
                    {
                        return Redirect("~/");
                    }
                    else
                    {
                        // user might have clicked on a malicious link - should be logged
                        errorMessage = "invalid return URL";
                    }


                }
                else
                {

                    await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials", clientId: context?.ClientId));
                    errorMessage = "Invalid login. Check your username/password and try again. \nIf you need further assistance, please contact us at 800-634-4484.";
                }

            }
            catch (Exception e)
            {
                await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials", clientId: context?.ClientId));
                errorMessage =
                    "Login problems. Please try again. \nIf you need further assistance, please contact us at 800-634-4484.";
            }


        }

        // something went wrong, show form with error
        var vm = await BuildLoginViewModelAsync(model);
        vm.ErrorMessage = errorMessage;
        return View(vm);
    }

0 个答案:

没有答案
相关问题