使用本地提供商的OAuth身份验证

时间:2019-03-20 17:00:58

标签: asp.net-core oauth-2.0 asp.net-identity identityserver4 razor-pages

在ASP.NET Core 2.2应用程序中,我正在定义OAuth提供程序。提供者可以登录用户并获取authorize_code,将authorize_code交换为token,并获取用户详细信息,身份服务器的cookie存储在用户代理中。 但是,在重定向到“授权”页面(在我的情况下是/ user)之后,我被重定向回了身份提供者,但是cookie已经分配给了应用程序,因此应用程序获取了authorize_code,将其交换为令牌并获取用户详细信息,然后重定向到Authorize页面和整个过程一次又一次地开始,最终用户代理取消了重定向,所以我陷入了递归之中,也不知道为什么。

这里是使用的配置

services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = "app";
        options.DefaultScheme = "app";
    })
    .AddCookie()
    .AddOAuth("app", options =>
    {
        options.ClientId = "appclient";
        options.ClientSecret = "3f97501d279b44f3bd69e8eec64cf336";

        options.CallbackPath = new PathString("/app-signin");

        options.Scope.Add("app_identity");
        options.Scope.Add("profile");
        options.Scope.Add("email");

        options.AuthorizationEndpoint = "http://dev/services/identity/connect/authorize";
        options.TokenEndpoint = "http://dev/services/identity/connect/token";
        options.UserInformationEndpoint = "http://dev/services/identity/api/user-profile";

        options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
        options.ClaimActions.MapJsonKey(ClaimTypes.GivenName, "firstName");
        options.ClaimActions.MapJsonKey(ClaimTypes.Surname, "lastName");
        options.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");

        options.Events = new OAuthEvents
        {
            OnCreatingTicket = async context =>
            {
                var request = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);
                request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);

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

                var user = JObject.Parse(await response.Content.ReadAsStringAsync());
                context.RunClaimActions(user);
            }
        };
    });

services.Configure<CookiePolicyOptions>(options =>
{
    options.CheckConsentNeeded = context => true;
    options.MinimumSameSitePolicy = SameSiteMode.None;
});

services
    .AddMvc()
    .AddRazorPagesOptions(options => options.Conventions.AuthorizePage("/User"))
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

应用程序在以下内容中登录输出

    info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
    Request starting HTTP/1.1 GET http://localhost:5001/User
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
    Executing endpoint 'Page: /User'
info: Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker[3]
    Route matched with {page = "/User"}. Executing page /User
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
    Authorization failed.
info: Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker[3]
    Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
    Executing ChallengeResult with authentication schemes ().
info: Microsoft.AspNetCore.Authentication.OAuth.OAuthHandler`1[[Microsoft.AspNetCore.Authentication.OAuth.OAuthOptions, Microsoft.AspNetCore.Authentication.OAuth, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]][12]
    AuthenticationScheme: app was challenged.
info: Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker[4]
    Executed page /User in 64.6437ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
    Executed endpoint 'Page: /User'
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
    Request finished in 129.4168ms 302
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
    Request starting HTTP/1.1 GET http://localhost:5001/app-signin?code=311966dfed306bdf5228501edcf7b493e208a0cf720d3ef39f281aabfa04bfb8&scope=wph_identity%20profile%20email&state=CfDJ8Ncai4ZNyK9Bno-T0jQD3hVJUzq-6K_bCKipeVryVM_FhwOvgc_d5ueapYYg7XRTSuFeLbrnZB4K8Zpni8KAk6cg1wWGwDoGXJrb3jp9zwhGQS24bPZUrsVFVxdt9v0loPkJjX6p226E3TisaJkaAxa_bzxyO_JKWtoHKsBLOmbuLh92rvxzde6S9BrElgvOuAYqsJ87UidQbCm8RrqZh78aC1vo5XcdIYEZs6eQjGFt
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[10]
    AuthenticationScheme: Cookies signed in.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
    Request finished in 321.3221ms 302
...

输出仅重复4次以上。 我相信它只是一些配置错误,但我无法弄清楚配置错误。

1 个答案:

答案 0 :(得分:0)

由SameSite Cookie限制引起。 添加.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, opt => opt.Cookie.SameSite = SameSiteMode.None)很有帮助。