剃刀页面授权与外部cookie陷入循环

时间:2019-06-29 01:07:23

标签: c# authentication asp.net-core auth0

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

我设置了一个主cookie,一个外部cookie和我的Auth0点。然后,它会回调到页面(/ Account / ExternalLogin),在我做完他们需要做的一切后,我在其中登录主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");
            });
}

这是AccountController

public class AccountController : Controller
{
    public async Task Login(string returnUrl = "/")
    {
        var redirectUrl = Url.Page("/ExternalLogin", pageHandler: "Callback", values: new { returnUrl });
        await HttpContext.ChallengeAsync("Auth0", new AuthenticationProperties() { RedirectUri = redirectUrl });
    }

    [Authorize]
    public async Task Logout()
    {
        await HttpContext.SignOutAsync("External");
        await HttpContext.SignOutAsync("MainCookie");
        await HttpContext.SignOutAsync("Auth0", new AuthenticationProperties
        {
            RedirectUri = Url.Action("Index", "Home")
        });
    }
}

因此,我们重定向到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");
    }

}

因此,当我转到/ Account / Login时,它将正确地将我发送到Auth0,然后将其发送到ExternalLogin,然后单击按钮并设置主Cookie。然后,这可以让我访问/ Profile。

但是,如果我没有被授权,如果我执行/ Profile,那么我将跳到Auth0,但是在进行身份验证之后,我只会陷入这样的循环中。

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 

1 个答案:

答案 0 :(得分:1)

只需更改选项。将DefaultChallengeScheme =“ Auth0”更改为选项。DefaultChallengeScheme=“ MainCookie”。