.Net Core Facebook OAuth вызывает ошибку "redirect_uri_mismatch"

Всем привет, использую проект на Razor Page, на сервере сайт работает через Reverse Proxy с помощью Apache2. Когда запускаю сайт на localhost проблема не появляется, авторизация проходит отлично. В запросе с локального хоста передается redirect_url в запросе: https://localhost:5081/signin-facebook но с хостинга, передается вот такой redirect_url: http://mysite.ru/signin-facebook т.е http схема вместо https. В учетке разраба фейсбука, нельзя указывать http протоколы в принимаемых redirect_url, принимаются только https. При попытке авторизации с хостинга, выдает ошибку ниже:

    info: AspNet.Security.OAuth.Facebook.FacebookAuthenticationHandler[12]
          AuthenticationScheme: Facebook was challenged.
    info: AspNet.Security.OAuth.Facebook.FacebookAuthenticationHandler[4]
          Error from RemoteAuthentication: OAuth token endpoint failure: Status: BadRequest;Headers: Vary: Accept-Encoding
          WWW-Authenticate: OAuth "Facebook Platform" "redirect_uri_mismatch"
   --- End of inner exception stack trace ---
   at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context,
 Task task)

Хостинг работает через CDN Cloudflare, если это важно. Виртуал хост апача выглядит вот так:

<VirtualHost *:80>
    ProxyPreserveHost On
    ProxyPass / http://localhost:5080/
    ProxyPassReverse / http://localhost:5080/
    ServerName mysite.ru
</VirtualHost>
<VirtualHost *:443>
    ServerName mysite.ru

    ProxyPass / http://localhost:5081/
    ProxyPassReverse / http://localhost:5081/
                <IfModule mod_headers.c>
                Header always add Strict-Transport-Security "max-age=15768000"
                RequestHeader unset Proxy early
                Header set X-Content-Type-Options nosniff
                Header always set X-Frame-Options SAMEORIGIN
                Header set X-XSS-Protection "1; mode=block"
                </IfModule>
</VirtualHost>

При запуске сайта, выводятся логи:

info: Microsoft.Hosting.Lifetime[0]                                                                                                        [102/102]
      Now listening on: http://localhost:5080
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: https://localhost:5081
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production

Как разрешить ошибку, куда копать? В сторону библиотеки OAuth (Microsoft.AspNetCore.Authentication.OAuth) или в сторону хостинга (апач, реверс прокси и т.п).

Дополнено: Если добавить в Startup.cs код:

    app.Use((context, next) =>
    {
        if (context.Request.Headers["x-forwarded-proto"] == "https")
        {
            context.Request.Scheme = "https";
        }
        return next();
    });

То в запрос к фейсбуку redirect_url меняет схему на https, но мой сайт выдает ошибку 500 при возврате на адрес https://mystite.ru/signin-facebook?code=returnedCodeFromFacebook&state=someState


Ответы (1 шт):

Автор решения: Saltant

Методом проб и ошибок, найдено РЕШЕНИЕ

После редактирования apache2 виртуал хоста на то что ниже, OAuth аутентификация стала проходить как следует.

<VirtualHost *:80>
    ProxyPass / http://localhost:5080/
    ProxyPassReverse / http://localhost:5080/
    ServerName mysite.ru
</VirtualHost>
<VirtualHost *:443>
    ProxyPreserveHost On
    ServerName mysite.ru
    
    SSLProxyEngine on
    SSLProxyCheckPeerCN off

    ProxyPass / https://localhost:5081/
    ProxyPassReverse / https://localhost:5081/
</VirtualHost>

Для того что бы всё заработало, мне пришлось отключить проксирование через сервера cloudflare, иначе почему то с фейсбука редайректило на localhost:5081 вместо доменного имени (игнорировалась директива апача ProxyPreserveHost), кто знает как подружиться в этом плане с cloudflare, расскажите, буду благодарен.

Так же пришлось включить SSLProxyEngine и создать сертификаты (т.к вероятно клоудфлейровские без проксирования не используются), у меня почему то выбивало ошибку рукопожатия с моими созданными сертификатами, по этому в апач добавил директиву SSLProxyCheckPeerCN

Это минимальный набор виртуального хоста в моем случае, для того что бы всё работало (в пример виртуал хоста не стал вписывать ссылки на сертификаты, но они там должны быть).

Интеграция с Cloudflare CDN

Для того, что бы проксирование заработало через cloudflare, нужно слегка подредактировать Virtual Host apache2 и загрузить на хостинг (где сайт расположен) CA сертификат cloudflare (который можно получить в настройках клоудфлейра), так же нужно в виртуал хосте убрать блок с 80 портом и оставить только 443 (SSL) иначе будет ошибка 500, итоговый виртуал хост выглядит вот так:

<VirtualHost *:443>
    ProxyPreserveHost On
    ServerName mysite.ru
    
    SSLProxyEngine on
    SSLProxyCheckPeerCN off
    ProxyPass / https://localhost:5081/
    ProxyPassReverse / https://localhost:5081/
        
    SSLProtocol all -SSLv2
    SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:!RC4+RSA:+HIGH:+MEDIUM:!LOW:!RC4
    SSLCertificateFile /etc/letsencrypt/live/mysite.ru/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/mysite.ru/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/mysite.ru/chain.pem
    SSLCACertificateFile /etc/letsencrypt/live/mysite.ru/origin-pull-ca.pem
    
    SSLHonorCipherOrder On
    SSLUseStapling On
    SSLStaplingResponderTimeout 5
    SSLStaplingReturnResponderErrors Off
    SSLVerifyDepth 1
    
<IfModule mod_headers.c>
    Header always add Strict-Transport-Security "max-age=15768000"
    Header set X-Content-Type-Options nosniff
    Header always set X-Frame-Options SAMEORIGIN
    Header set X-XSS-Protection "1; mode=block"
</IfModule>
    
    ErrorLog /var/log/apache2/mysite-error.log
    CustomLog /var/log/apache2/mysite-access.log common
</VirtualHost>

От использования некоторых заголовков в виртуал хосте думаю можно отказаться, заменив аналогами из кода самого сайта .net core (Razor в моем случае) но я для "уверенности" бахнул и в виртуал хост.

В панели Cloudflare можно включать теперь SSL/TLS Mode в режим Full или Full(Strict) всё будет прекрасно работать, так же можно накрутить всякие другие "улучшайки" у CDN, всё будет работать, включая выданный самим клоудфлейром сертификат на основной домен и все поддомены.

→ Ссылка