Аутентификация Facebook с ASP.NET Core 2.1: OAuth "Платформа Facebook" "invalid_code" "Этот код авторизации был использован." - PullRequest
0 голосов
/ 01 июля 2018

Я читал похожие проблемы с другими фреймворками на stackoverflow, и ни одна из них не касалась решения этой проблемы с помощью ASP.NET Core 2.1. Я предполагаю где-то Мне нужно будет изменить токен доступа, сгенерированный библиотекой, однако я не вижу легкой возможности для этого.

Ошибка после перехода к контроллеру / действию, помеченному [Авторизовать], приводит к следующему исключению:

Exception: OAuth token endpoint failure: Status: BadRequest;Headers: Cache-    Control: no-store
Connection: keep-alive
Date: Sun, 01 Jul 2018 20:26:11 GMT
Pragma: no-cache
WWW-Authenticate: OAuth "Facebook Platform" "invalid_code" "This authorization code has been used."
Strict-Transport-Security: max-age=15552000;  x-fb-trace-id: FUP+X7GzCHR
x-fb-rev: 4066065
facebook-api-version: v2.6
Access-Control-Allow-Origin: *
X-FB-Debug: 97aI6xVBbJLooeNj3qmNCw9NFifMBvYire/pA0R6dCH5BqWcJ9Vc9rJK+KWvwiNiTXV4PX5ASLbEkbCGgqtCmg==
;Body: {"error":{"message":"This authorization code has been used.","type":"OAuthException","code":100,"fbtrace_id":"FUP+X7GzCHR"}};
Unknown location
Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler+<HandleRequestAsync>d__12.MoveNext()

Мой Startup.cs выглядит следующим образом:

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<FacebookIdentityContext>();
    //services.AddDataProtection().PersistKeysToAzureBlobStorage(new Uri(Configuration["Blob:Uri"])).ProtectKeysWithDpapi();
    services.AddCors(options =>
    {

        options.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
                                            .AllowAnyMethod()
                                            .AllowAnyHeader());
    });

    services.AddIdentity<FacebookUser, IdentityRole<int>>().AddEntityFrameworkStores<FacebookIdentityContext>().AddDefaultTokenProviders();
    services.AddAuthentication().AddFacebook(fb =>
    {
        fb.AppId = Configuration["Facebook:AppId"];
        fb.AppSecret = Configuration["Facebook:AppSecret"];
        fb.CallbackPath += "/";
    });
    services.AddMvc().AddControllersAsServices();

    Container container = new Container();
    container.Configure(config =>
    {
        CosmosDataToken graphToken = new CosmosDataToken(new Uri(Configuration["GraphDB:Uri"]), Configuration["GraphDB:Key"], Configuration["GraphDB:Database"], Configuration["GraphDB:DocumentCollection"]);
        config.For<CosmosDataToken>().Add(graphToken).Named("Graph");
        config.For<IBrandDataAdapter>().Use<BrandDataAdapter>().Ctor<CosmosDataToken>().Named("Graph");
        config.For<IBrandBusinessLogic>().Use<BrandBusinessLogic>();
        config.Populate(services);
        config.For<IContainer>().Use(container);
    });
    return container.GetInstance<IServiceProvider>();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{ 
    if (env.IsDevelopment())
    {
        app.UseBrowserLink();
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }
    app.UseAuthentication();
    app.UseStaticFiles();
    app.UseCors("AllowAll");

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });

}

}

AccounController.cs:

[Route("[controller]/[action]")]
public class AccountController : Controller
{
    [HttpGet]
    public IActionResult SignIn()
    {
        var redirectUrl = Url.Action(nameof(HomeController.Index), "Home");
        return Challenge(
            new AuthenticationProperties { RedirectUri = redirectUrl },
            FacebookDefaults.AuthenticationScheme);
    }
    [HttpGet]

    public IActionResult Login(string returnUrl)
    {
        return Challenge(
            new AuthenticationProperties { RedirectUri = returnUrl }, FacebookDefaults.AuthenticationScheme);
    }
}

По запросу: трассировка необработанного стека (9 июля 2018 г.)

System.Exception: An error was encountered while handling the remote login. ---> System.Exception: OAuth token endpoint failure: Status: BadRequest;Headers:     Cache-Control: no-store

Connection: keep-alive

Date: Tue, 10 Jul 2018 02:07:33 GMT

Pragma: no-cache

WWW-Authenticate: OAuth "Facebook Platform" "invalid_code" "This authorization code has been used."

Strict-Transport-Security: max-age=15552000; preload

x-fb-trace-id: GGIG00tEoLq

x-fb-rev: 4083489

facebook-api-version: v2.6

Access-Control-Allow-Origin: *

X-FB-Debug: oRwbzflr375r3JhjSp0V1K1iP3+vI5m/kHUCsr5CPHwHv68Waz4eydZ8cw5cTCCT2KUo6Z8la42syKtNPuWfxQ==

;Body: {"error":{"message":"This authorization code has been used.","type":"OAuthException","code":100,"fbtrace_id":"GGIG00tEoLq"}};

   --- End of inner exception stack trace ---

   at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.<HandleRequestAsync>d__12.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

 at     System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.<Invoke>d__6.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7.MoveNext()

И журналы IIS:

2018-07-10 02:07:33 ::1 GET /signin-facebook/ code=AQACzBL6QlPjzfEBoB2L9LEbMXgdxw3KNgcBc-8fv2RGHAtfa9bGCqWZ-efFgEPv_mx1Xaphi6z0Ok6cNGDArIWiwdtIw_tB2r6EaQ7TyEsov5fajemTgYZtsgJXEOtpOo0YQmBDROIMtaKEAREsJFeN3eR3QYqEedadgSRikCB-gFVKCSalPXVQubHGzPRQHOl16u-zNNe4sJJlBX8G0LZeJ7tziCnIiexfTB_zBWvFrgjggfUPtlFV2VLWLxH55O3xD1sZxY2xFTy01P4Tb4ENAurvAh2techvnV4uDobSyrSVoylGSKEqTHdalENlqKU&state=CfDJ8Fal1oNbU75Jg6-R34J8E0YhIDy-BtCBqI_xTclwY43ARUtMiTWDmco_N7wJNTbUoHedtAe0yVBR2r9sV_sOTayIgaJEkRuqWyuO0i5Yh6vB7pbUX4krFRcwIzDbVSBGxPwBzQSOqtLPoY8KlKjmN70sooi_fQqq3OIcFynOe8UVd-mMtodbu3fdOz0kVpdO-khCscC-R4p78IJiWzqAN_Xsd_MR4ihTKbWSBfGRVreU 44392 - ::1 Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/64.0.3282.140+Safari/537.36+Edge/17.17134 - 500 0 0 245

ИЗМЕНИТЬ 12 июля 2018 года: Полный пример с той же ошибкой можно найти по адресу: https://github.com/jlind0/TestFacebookAuth

1 Ответ

0 голосов
/ 12 июля 2018

Я выяснил вашу проблему. Что-то не так с вашим AccountController. Когда вы звоните Challenge, пользователь перенаправляется на Facebook и возвращается после успешного входа в систему. Когда пользователь возвращается, его учетные данные добавляются с IdentityConstants.ExternalScheme. Здесь вам также нужно позвонить SignIn с IdentityConstants.ApplicationScheme. Таким образом, вам нужен метод обратного вызова для обработки этого.

Это то, что вам нужно иметь в вашем AccountController

[HttpGet]
public IActionResult SignIn()
{
    var redirectUrl = Url.Action(nameof(HomeController.Index), "Home");
    return Login(redirectUrl);
}

[HttpGet]
public IActionResult Login(string returnUrl)
{
    var redirectUrl = Url.Action(nameof(AccountController.LoginCallback), "Account", new { returnUrl = returnUrl });

    return Challenge(
        new AuthenticationProperties { RedirectUri = redirectUrl, }, FacebookDefaults.AuthenticationScheme);
}

[HttpGet]
public async Task<IActionResult> LoginCallback(string returnUrl)
{
    var authenticateResult = await HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme);

    await HttpContext.SignInAsync(IdentityConstants.ApplicationScheme, new System.Security.Claims.ClaimsPrincipal(authenticateResult.Ticket.Principal.Identity));

    return LocalRedirect(returnUrl);
}

Но я настоятельно рекомендую вам использовать шаблон для менеджера пользователей.

...