C# Razor页面授权卡在带有外部cookie的循环中

C# Razor页面授权卡在带有外部cookie的循环中,c#,authentication,asp.net-core,auth0,C#,Authentication,Asp.net Core,Auth0,我有一个ASP.NET核心应用程序,我正在与Auth0集成。在身份验证之后,我想重定向到一个页面来收集信息以创建一个本地帐户,就像默认的Facebook和Google扩展一样 我设置了一个主cookie、一个外部cookie和我的Auth0点。然后它回调到页面(/Account/ExternalLogin),在那里我在完成主cookie所需的操作后登录到主cookie,并重定向到需要授权的页面(/Profile)。这一切都可以正常工作 然而,如果我只是尝试进入该页面,而不是通过登录路径,我就会陷

我有一个ASP.NET核心应用程序,我正在与Auth0集成。在身份验证之后,我想重定向到一个页面来收集信息以创建一个本地帐户,就像默认的Facebook和Google扩展一样

我设置了一个主cookie、一个外部cookie和我的Auth0点。然后它回调到页面(/Account/ExternalLogin),在那里我在完成主cookie所需的操作后登录到主cookie,并重定向到需要授权的页面(/Profile)。这一切都可以正常工作

然而,如果我只是尝试进入该页面,而不是通过登录路径,我就会陷入一个循环中

我很确定我错过了一件愚蠢的事情,但我似乎无法得到它

我已经尝试了几乎所有我能想到的事情的组合,我相信这是愚蠢的

这是我在startup.cs的相关部分

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    // Add authentication services
    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = "MainCookie";
        options.DefaultChallengeScheme = "Auth0";
    })
    .AddCookie("MainCookie", options =>
    {
        options.ForwardChallenge = "Auth0";
    })
    .AddCookie("External", options =>
    {
    })
    .AddOpenIdConnect("Auth0", options =>
    {
        // Set the authority to your Auth0 domain
        options.Authority = $"https://{Configuration["Auth0:Domain"]}";

        // Configure the Auth0 Client ID and Client Secret
        options.ClientId = Configuration["Auth0:ClientId"];
        options.ClientSecret = Configuration["Auth0:ClientSecret"];

        // Set response type to code
        options.ResponseType = "code";

        // Configure the scope
        options.Scope.Clear();
        options.Scope.Add("openid");
        options.Scope.Add("profile");
        options.Scope.Add("email");

        options.SignInScheme = "External";

        // Set the callback path, so Auth0 will call back to http://localhost:3000/callback
        // Also ensure that you have added the URL as an Allowed Callback URL in your Auth0 dashboard
        options.CallbackPath = new PathString("/callback");

        // Configure the Claims Issuer to be Auth0
        options.ClaimsIssuer = "Auth0";

        options.Events = new OpenIdConnectEvents
        {
            // handle the logout redirection
            OnRedirectToIdentityProviderForSignOut = (context) =>
                    {
                        var logoutUri = $"https://{Configuration["Auth0:Domain"]}/v2/logout?client_id={Configuration["Auth0:ClientId"]}";

                        var postLogoutUri = context.Properties.RedirectUri;
                        if (!string.IsNullOrEmpty(postLogoutUri))
                        {
                            if (postLogoutUri.StartsWith("/"))
                            {
                                // transform to absolute
                                var request = context.Request;
                                postLogoutUri = $"{request.Scheme}://{request.Host}{request.PathBase}{postLogoutUri}";
                            }
                            logoutUri += $"&returnTo={ Uri.EscapeDataString(postLogoutUri) }";
                        }

                        context.Response.Redirect(logoutUri);
                        context.HandleResponse();

                        return Task.CompletedTask;
                    }
        };
    });


    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
            .AddRazorPagesOptions(options =>
            {
                options.Conventions.AuthorizePage("/Profile");
            });
}
因此,我们重定向到ExternalLogin回调。目前,只有一个提交按钮转到完成登录的确认回调。这最终将替换为检查我是否有他们的帐户,并强制他们注册

public class ExternalLoginModel : PageModel
{
    public IActionResult OnPost(string provider, string returnUrl = null)
    {
        var redirectUrl = Url.Page("./ExternalLogin", pageHandler: "Callback", values: new { returnUrl });
        return new ChallengeResult(provider, null);
    }


    public async Task<IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
    {
        returnUrl = returnUrl ?? Url.Content("~/");
        if (remoteError != null)
        {
            ErrorMessage = $"Error from external provider: {remoteError}";
            return RedirectToPage("./Login", new { ReturnUrl = returnUrl });
        }

        return Page();
    }

    public async Task<IActionResult> OnPostConfirmAsync()
    {
        var claimsPrincipal = await HttpContext.AuthenticateAsync("External");
        await HttpContext.SignInAsync("MainCookie", claimsPrincipal.Principal);
        await HttpContext.SignOutAsync("External");

        return RedirectToPage("/Profile");
    }

}

只需将options.DefaultChallengeScheme=“Auth0”更改为options.DefaultChallengeScheme=“MainCookie”

public class ExternalLoginModel : PageModel
{
    public IActionResult OnPost(string provider, string returnUrl = null)
    {
        var redirectUrl = Url.Page("./ExternalLogin", pageHandler: "Callback", values: new { returnUrl });
        return new ChallengeResult(provider, null);
    }


    public async Task<IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
    {
        returnUrl = returnUrl ?? Url.Content("~/");
        if (remoteError != null)
        {
            ErrorMessage = $"Error from external provider: {remoteError}";
            return RedirectToPage("./Login", new { ReturnUrl = returnUrl });
        }

        return Page();
    }

    public async Task<IActionResult> OnPostConfirmAsync()
    {
        var claimsPrincipal = await HttpContext.AuthenticateAsync("External");
        await HttpContext.SignInAsync("MainCookie", claimsPrincipal.Principal);
        await HttpContext.SignOutAsync("External");

        return RedirectToPage("/Profile");
    }

}
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/2.0 GET https://localhost:44375/profile  
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executing endpoint 'Page: /Profile'
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Route matched with {page = "/Profile", action = "", controller = ""}. Executing page /Profile
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed.
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes ().
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:Information: AuthenticationScheme: Auth0 was challenged.
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executed page /Profile in 11.2594ms
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executed endpoint 'Page: /Profile'
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 28.548ms 302 
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/2.0 POST https://localhost:44375/callback application/x-www-form-urlencoded 375
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: External signed in.
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 113.1223ms 302