İçeriğe geç
KURUMSAL Kurumsal teknoloji · İşletmenize özel mühendislik Kurumsal Yazılım · Yönetilen Sunucular · Kurumsal E-posta · LiteSpeed + CloudLinux · Imunify360 Güvenlik · cPanel Yönetim · Uygun pakette 3 Gbps'ye kadar ağ profili
AIOR

XenForo Facebook Login Sonrası URL'de #_=_ Görünmesi — Çözüm

  • Konu başlatıcısı Konu başlatıcısı Aior
  • Başlangıç tarihi Başlangıç tarihi

Aior

Administrator

Yetkili üye
Katıldı
2 Nis 2023
Mesajlar
929
Tepki puanı
2
Puan
18
Yaş
41
Konum
Turkey
Web sitesi
aior.com
Konu sahibi

Bir üye giriş formundaki Facebook düğmesiyle oturum açtığında XenForo onu foruma geri gönderir, fakat adres çubuğundaki URL'nin sonunda #_=_ eki kalır: https://forum.example.com/#_=_ ya da https://forum.example.com/threads/bir-konu.123/#_=_ gibi. Sayfa normal çalışır, bozulan bir şey yoktur; ancak adres bir hata varmış izlenimi verir, üyelerin kopyalayıp paylaştığı bağlantılara karışır ve adresin tamamını okuyan her betik bu eki de görür. Bu yazıda ekin nereden geldiğini, Facebook uygulamasının doğru XenForo adresine yönlendirdiğinden nasıl emin olacağınızı, eki güncellemelerde kaybolmayan bir şablon değişikliğiyle (template modification) nasıl temizleyeceğinizi, düzeltmeyi nasıl test edeceğinizi ve Facebook girişinden sonra sık görülen diğer hataları ele alıyoruz.

Bu konuyu baştan yazdık. Önceki sürüm, XenForo 2.2 ve sonraki sürümlerin bu eki kendiliğinden temizlediğini ve Facebook'un eki XSS ile CSRF saldırılarını önlemek için eklediğini söylüyordu. İki iddiayı da doğrulayamadık; düzeltilmiş hâllerini aşağıda bulacaksınız.

Hızlı çözüm: kontrol listesi​

  1. Facebook uygulamasının Valid OAuth Redirect URIs alanında, Board URL değerinizin sonuna /connected_account.php eklenmiş adres bulunsun; örneğin https://forum.example.com/connected_account.php.
  2. XenForo'da PAGE_CONTAINER şablonuna, aşağıdaki kodu meta charset etiketinin hemen ardına ekleyen bir şablon değişikliği tanımlayın.
  3. Yeni bir sekmede https://forum.example.com/#_=_ adresini açın. Adres çubuğunda anında https://forum.example.com/ görünmeli.
  4. Gizli pencerede, telefonda ve Facebook'un uygulama içi tarayıcısında gerçek bir Facebook girişi yapın; ardından gönderilere giden bağlantıların (#post-123) sayfayı hâlâ doğru yere kaydırdığını kontrol edin.

#_=_ nedir, nereden gelir?​

URL'de # işaretinden sonra gelen kısma parça tanımlayıcı (fragment) denir; günlük kullanımda çoğunlukla "fragment" ya da "hash" diye anılır. Tarayıcı bu kısmı yalnızca kendi tarafında kullanır, sunucuya göndermez: HTTP semantiğini tanımlayan RFC 9110 belgesine göre hedef adres (target URI) fragment'ı içermez, çünkü fragment istemci tarafındaki işlemlere ayrılmıştır. #_=_ ekindeki fragment bir alt çizgi, bir eşittir işareti ve yine bir alt çizgiden oluşur; hiçbir anlam taşımayan, yer tutucu bir anahtar=değer çiftidir. Üye herhangi bir bağlantıya tıkladığı anda ek de kaybolur, çünkü normal bir bağlantı eski fragment'ı yeni sayfaya taşımaz.

Facebook'un bu konudaki tek açıklaması iki cümlelik bir nottur. 2 Eylül 2011 tarihli geliştirici blog yazısında ("Platform Updates: Operation Developer Love"), "Change in Session Redirect Behavior" başlığı altında, bu alan boş bırakıldığında ("when this field is left blank") redirect_uri adresine #_=_ fragment'ını eklemeye başladıklarını yazdılar ve geliştiricilerden uygulamalarının bu davranışa uyum sağladığından emin olmalarını istediler. Bu cümle genellikle şöyle okunur ve geliştiricilerin gözlediği davranış da budur: Facebook tarayıcıyı geri gönderdiği adreste kendi fragment'ı yoksa sonuna #_=_ ekler. XenForo'nun dönüş adresinde fragment bulunmadığı için ek XenForo forumlarında da görülür. Notta bundan öte bir gerekçe verilmiyor.

En olası gerekçe, HTTP yönlendirmelerinde fragment'ın devralınmasıdır (fragment inheritance). RFC 9110'un 10.2.2. bölümüne göre bir 3xx yönlendirmesinin Location başlığında fragment yoksa tarayıcı, yeni adres eski adresin fragment'ını devralmış gibi davranmak zorundadır. Aynı belgenin 17.11. bölümü bunun bir sitenin fragment'ını başka bir siteye sızdırabileceği konusunda uyarır ve fragment'ta kişisel bilgi tutan sitelere, başka sitelere yaptıkları yönlendirmelere kendi (gerekirse boş) fragment'larını eklemelerini önerir; böylece devralma engellenir. Facebook'un giriş penceresi bazı akışlarda veriyi fragment içinde döndürür: Meta'nın elle giriş akışı (manual login flow) belgesine göre response_type=token kullanıldığında erişim belirteci (access token) fragment'ta gelir. Her seferinde zararsız bir fragment göndermek, facebook.com adresindeki hiçbir fragment'ın kullanıcıyla birlikte sizin sitenize taşınmamasını sağlamanın ucuz bir yoludur. Bu yorum standartla örtüşüyor; ancak Facebook böyle bir gerekçe yayımlamadığı için bunu resmî açıklama olarak değil, en makul açıklama olarak değerlendirin.

Bu ekin ne olmadığını da netleştirelim: CSRF koruması değildir. OAuth'ta bu görev state parametresine aittir; Meta'nın Login Security rehberi de bunu açıkça söyler. Ek ne bir belirteç ne de kişisel veri taşır.

Ek neden XenForo sayfalarında kalıyor?​

Akışı XenForo 2.3 kaynak kodu üzerinden izledik:
  1. Üye giriş formundaki Facebook düğmesine tıklar (İngilizce arayüzde bu düğmeler "Log in using" başlığının altında durur). XenForo isteği (sağlayıcıyı ve dönülecek adresi) ziyaretçinin oturumuna (session) kaydeder ve tarayıcıyı Facebook'un giriş penceresine yönlendirir. Gönderdiği redirect_uri, Board URL seçeneğinin sonuna /connected_account.php eklenmiş hâlidir.
  2. Facebook tarayıcıyı connected_account.php?code=…&state=…#_=_ adresine geri gönderir.
  3. connected_account.php gelen kodu erişim belirteciyle takas eder ve /register/connected-accounts/facebook/ adresine 302 yönlendirmesi döndürür. Bu Location başlığında fragment olmadığından tarayıcı #_=_ ekini korur.
  4. Facebook hesabı bir üyeye zaten bağlıysa XenForo üyenin oturumunu açar ve onu girişe başladığı sayfaya yönlendirir; bu yönlendirmede de fragment olmadığı için ek yerinde kalır. Hesap bağlı değilse XenForo yeni hesap açma ya da mevcut hesaba bağlama formunu aynı adreste, yine #_=_ ekiyle gösterir.
Kısacası ek, akış hangi sayfada biterse üyeyle birlikte oraya gider. XenForo 2.3'ün çekirdek JavaScript dosyalarında ve çekirdek şablonlarında bu eki silen bir kod bulamadık (kendi 2.3 forumumuzun sunduğu dosyalara ve 2.3.4 şablon setine baktık). Kendi forumunuzda ekin kendiliğinden kaybolduğunu görmediyseniz düzeltmeye ihtiyacınız olduğunu varsayın. Eki hiç görmüyorsanız bir eklenti, stiliniz ya da bir analitik betiği onu zaten temizliyor olabilir; sayfa kaynağında _=_ araması yaparak bunu öğrenebilirsiniz.

1. adım: Yönlendirme adresini ve Board URL'yi doğrulayın​

XenForo kılavuzunun Facebook bağlı hesap sayfası (27 Ekim 2026'da kontrol ettik) şunları söylüyor: Valid OAuth redirect URIs alanına forum adresinizin sonuna /connected_account.php eklenmiş hâlini yazın, örneğin https://xenforo.com/community/connected_account.php; bu adresin başı XenForo'daki Board URL ayarıyla birebir aynı olmalı; Board URL HTTPS gerektirir. XenForo 2.3 yönlendirme adresini çalışma anında Board URL seçeneğinden ürettiği için iki değer karakteri karakterine aynı olmalıdır. Meta da yönlendirme adresini listenizle tam eşleşme (exact match) kuralına göre karşılaştırır: state dışındaki bütün parametreler dahil adresin tamamı aynı olmak zorundadır. Bu, Strict Mode'un çalışma biçimidir ve Meta'nın güvenlik rehberine göre Strict Mode bütün uygulamalar için zorunludur.

Board URL, Setup > Options > Basic options sayfasındadır (2.0 ve 2.1'de bu grubun adı Basic board information idi). 2.2.9'dan beri seçeneğin açıklaması, adresin sonunda "/" işareti, sorgu dizesi (query string), fragment ya da index.php gibi bir dosya adı bulunmaması gerektiğini belirtir ve önerilen adresi gösterir.

Board URLValid OAuth Redirect URIs kaydıSonuç
https://forum.example.comhttps://forum.example.com/connected_account.phpDoğru
https://www.example.com/communityhttps://www.example.com/community/connected_account.phpDoğru (alt klasör ve www dahil)
https://www.example.com/communityhttps://example.com/community/connected_account.phpURL Blocked: alan adı farklı (www)
http://forum.example.comhttp://forum.example.com/connected_account.phpReddedilir: Facebook, OAuth yönlendirmelerinde HTTPS ister
https://forum.example.comhttps://forum.example.com/register/connected/facebook (eski rehberlerde geçen bir yol)URL Blocked: yol farklı

Facebook uygulamasında iki ayar daha önemlidir. Client OAuth Login ve Web OAuth Login açık olmalıdır (URL Blocked mesajı da bunları kontrol etmenizi ister); Settings > Basic altındaki App Domains alanını doldurduysanız forumun alan adı da bu listede yer almalıdır. Her değişiklikten sonra XenForo'da Setup > Connected accounts > Test provider ile sağlayıcıyı test edin. Önce yönlendirme adresini ve Board URL'yi düzeltmek, birçok URL Blocked hatasını ve yönlendirme döngüsünü baştan önler; görsel temizlik ancak giriş sorunsuz çalıştıktan sonra anlam kazanır.

2. adım: #_=_ ekini şablon değişikliğiyle temizleyin​

Kodu doğrudan PAGE_CONTAINER şablonuna yapıştırmayın. Doğrudan düzenleme, şablonu yalnızca o stilde (tema) özelleştirir: bir güncelleme ana şablonu değiştirdiğinde sizin kopyanız Outdated templates (güncel olmayan şablonlar) listesinde görünür ve değişikliklerin birleştirilmesi (merge) gerekir, şablon varsayılana döndürülürse değişiklik kaybolur, kendi PAGE_CONTAINER kopyasına sahip bir stil de kodu hiç almaz. Şablon değişikliği ise ayrı saklanır, tek tıkla kapatılabilir ve XenForo onu Find metninin eşleştiği her stildeki şablon kopyasına uygular.

  1. Yönetim panelinde Appearance > Template modifications sayfasını açın (Styles & templates grubundadır). Bunun için "Manage styles, style properties, and templates" yönetici yetkisi gerekir.
  2. Public sekmesi seçiliyken Add template modification düğmesine tıklayın.
  3. Template: PAGE_CONTAINER. Modification key: fb_hash_cleanup (yalnızca harf, rakam ve alt çizgi). Description: Facebook girişinden sonra #_=_ ekini siler.
  4. Search type: Simple replacement. Find alanına meta charset etiketini Template contents kutusundan birebir kopyalayın; varsayılan 2.3 şablonunda bu, aşağıdaki satırdır.
  5. Replace alanına aşağıdaki bloğu yapıştırın. $0 bulunan metni geri koyar; yani meta etiketi yerinde kalır, kod da hemen ardından gelir.
  6. Test düğmesiyle sonucu önizleyin, ardından Automatically apply template modification işaretliyken kaydedin.

Find:
Kod:
<meta charset="utf-8" />

Replace:
Kod:
$0
<script>
(function () {
    if (window.location.hash !== '#_=_') return;
    try {
        window.history.replaceState(window.history.state, '', window.location.pathname + window.location.search);
    } catch (e) {}
})();
</script>

Kod ne yapıyor?
  • Yalnızca fragment tam olarak #_=_ olduğunda devreye girer. #post-123, bir profil sekmesi ya da başka bir sayfa içi bağlantı (anchor) olduğu gibi kalır.
  • history.replaceState, sayfayı yeniden yüklemeden ve yeni bir geçmiş kaydı (history entry) eklemeden mevcut kaydı değiştirir; bu yüzden Geri düğmesi #_=_ ekli adrese dönmez.
  • İkinci argüman boş dizedir; MDN bunu geleneksel ve ileriye dönük güvenli değer olarak tanımlar. Yeni adres yalnızca yol ve sorgu dizesinden oluştuğu için her zaman aynı kökendedir (same-origin).
  • history.state değerini korur; başka bir betiğin kaydetmiş olabileceği durumu silmez.
  • replaceState nadiren de olsa hata fırlatabilir: MDN, belgenin tam etkin olmadığı, adresin geçersiz olduğu ve yöntemin çok sık çağrıldığı durumları sayar. try/catch bu yüzden var; görsel bir düzeltme sayfayı asla bozmamalı.
  • İçinde {$ ya da {{ dizisi bulunmadığı için XenForo'nun şablon derleyicisi kodu olduğu gibi bırakır.

Bu yazının önceki sürümündeki kod, replaceState desteklemeyen tarayıcılarda yedek olarak window.location.hash = '' satırını çalıştırıyordu. Güncel tarayıcıların hepsi replaceState destekler; o yedek yol ise adresin sonunda tek başına bir # bırakır. Bu yüzden onu çıkardık.

Konum önemlidir. Kod, head bölümü ayrıştırılırken çalışır: XenForo'nun ertelenmiş (defer) JavaScript dosyalarından ve XenForo 2.3'ün çerez onayı ayarına bağlı olarak head bölümünün en sonuna eklediği google_analytics şablonundan önce. Kaydettikten sonra herhangi bir sayfanın kaynağını açın, _=_ araması yapın ve kodun bir kez göründüğünü, eklentilerin ya da stilinizin eklediği Google Analytics, Tag Manager veya başka izleme kodlarının üstünde durduğunu doğrulayın. Şablon değişiklikleri listesinde kaydın yanındaki sayaçlar değişikliğin kaç şablona uygulandığını, kaçında Find metninin bulunamadığını ve kaçında hata çıktığını gösterir. "Bulunamadı" sayacının sıfırdan büyük olması çoğunlukla PAGE_CONTAINER şablonunu kendisi özelleştirmiş ve meta charset satırı farklı olan bir stile işaret eder; Find metnini o stilin şablonundan kopyalayarak ikinci bir şablon değişikliği ekleyin.

Alternatif: küçük bir JavaScript dosyası​

Satır içi kod yerine dosya kullanmayı tercih ediyorsanız ya da İçerik Güvenliği Politikanız (Content-Security-Policy, CSP) satır içi betiklere izin vermiyorsa aynı fonksiyonu (script etiketleri olmadan) XenForo kök dizinindeki js/custom/fb-hash-cleanup.js dosyasına koyun ve Replace alanına şunu yazın:
Kod:
$0
<script src="{{ base_url('js/custom/fb-hash-cleanup.js') }}"></script>
Dosyanın head içinde tam o noktada çalışması için async ya da defer eklemeyin. Bu biçimde yüklenen bir dosya, gelene kadar sayfanın ayrıştırılmasını bekletir; dosya çok küçük olduğu ve ilk ziyaretten sonra önbellekten geldiği için gecikme genellikle önemsizdir, ama her yeni ziyaretçi için fazladan bir istek demektir. XenForo'nun xf:js etiketi de js dizinindeki dosyaları yükleyebilir; fakat kendi 2.3 forumumuzda bu yolla eklenen dosyalar defer özniteliğiyle basılıyor, yani sayfa ayrıştırıldıktan sonra, head içindeki satır içi analitik kodlarından sonra çalışıyor. Adres çubuğu için bu yeterlidir, ama analitiğin temiz adresi kaydetmesini istiyorsanız geç kalır. Dosya XenForo paketinin parçası olmadığından kurulum notlarınıza ve yedeklerinize ekleyin; dosyayı değiştirdiğinizde adını değiştirin ya da ?v=2 gibi bir sorgu dizesi ekleyin ki tarayıcılar önbellekteki eski kopyayı kullanmayı bıraksın.

İçerik Güvenliği Politikası (CSP)​

Web sunucunuz, CDN'iniz ya da bir eklenti Content-Security-Policy başlığı gönderiyor olabilir. Şu komutla kontrol edin:
Bash:
curl -sI https://forum.example.com/ | grep -i content-security-policy
Politikanın script-src yönergesi (bu yönerge yoksa default-src) satır içi betiklere izin vermiyorsa kod engellenir ve tarayıcı konsolunda bir CSP ihlali görünür. MDN'ye göre satır içi bir betiğe üç yolla izin verilebilir: 'unsafe-inline', bir nonce ya da betikle eşleşen bir özet (hash). 'unsafe-inline' bütün politikayı zayıflatır, nonce ise sunucunun her yanıtta yeniden üretmesini gerektirir; bu yüzden pratikte iki seçenek kalır: kodun özetini script-src yönergesine ('sha256-…') eklemek ya da script-src yönergesinde 'self' bulunan bir politikanın zaten izin verdiği harici dosyayı kullanmak. MDN'nin belirttiği gibi özet yalnızca script etiketlerinin arasındaki içerikten hesaplanır; boşluklar ve büyük-küçük harf önemlidir, tek bir fazla boşluk bile özeti değiştirir. Chromium tabanlı tarayıcılar beklenen özeti konsoldaki hata mesajında yazar. Content-Security-Policy-Report-Only başlığı ise hiçbir şeyi engellemez, yalnızca ihlalleri raporlar; daha sıkı bir politikayı önce bu modda denemek güvenli bir yoldur.

3. adım: Düzeltmeyi test edin​

  1. Facebook olmadan: https://forum.example.com/#_=_ adresini yeni bir sekmede açın. Açık bir sayfada denemek isterseniz adresin sonuna #_=_ ekleyip Enter'a, ardından F5'e basın: yalnızca fragment değiştiğinde Enter sayfayı yeniden yüklemez ve kod çalışmaz, F5 ise sayfayı yeniden yükler. Temiz adres hemen görünmelidir.
  2. Sayfa içi bağlantılar: bir gönderinin başlığındaki tarih ya da numara bağlantısını (/threads/…/post-123 biçimindedir) yeni sekmede açın. XenForo konu sayfasına #post-123 ekiyle yönlendirir; sayfa yine o gönderiye kaymalıdır.
  3. Geri düğmesi: temizlikten sonra Geri, #_=_ ekli adrese değil, bir önceki sayfaya dönmelidir.
  4. Gizli pencerede (incognito) gerçek giriş: bir kez bir üyeye bağlı Facebook hesabıyla, bir kez de kayıt veya bağlama formunu açan, bağlı olmayan bir hesapla deneyin.
  5. Telefonlar: iOS'ta Safari, Android'de Chrome.
  6. Facebook'un uygulama içi tarayıcısı (in-app browser): forum bağlantısını Messenger'da kendinize gönderin ya da yalnızca sizin görebileceğiniz bir yerde paylaşın, Facebook veya Messenger uygulamasının içinde açın ve giriş yapın. Uygulama içi tarayıcılar çoğu zaman adresin tamamını göstermez; menüden bağlantıyı kopyalayıp okuyabileceğiniz bir yere yapıştırın.
  7. Analitik: GA4'ün Realtime ya da DebugView ekranında girişten sonraki sayfa görüntülemesi temiz adresle görünmeli ve yalnızca bir kez sayılmalıdır.

Facebook girişinden sonra görülen diğer sorunlar​

Tabloda "XenForo:" ile başlayan mesajlar XenForo 2.3'ün İngilizce metinleridir; Türkçe dil paketi kullanıyorsanız çevirilerini görürsünüz.

Belirti veya mesajOlası nedenÇözüm
Facebook: URL BlockedYönlendirme adresi Valid OAuth Redirect URIs listesinde yok ya da Client/Web OAuth Login kapalıBoard URL'yi ve yönlendirme adresini 1. adımdaki gibi ayarlayın, iki OAuth seçeneğini de açın
Facebook: Insecure Login Blocked (ya da URL Blocked)Board URL http:// ile başlıyorForumu HTTPS'e taşıyın ve Board URL'yi güncelleyin
Facebook: App not activeUygulama Geliştirme (Development) modunda; bu modda yalnızca uygulamada rolü olanlar (admin, developer, tester) giriş yapabilirZorunlu alanları doldurup uygulamayı Canlı (Live) moda alın; test için hesabı tester olarak ekleyin
XenForo: There is no valid connected account request available. Please try again.Dönüşte oturum çerezi gönderilmedi: giriş www.example.com'da başlayıp example.com'a döndü (ya da http ile https karıştı), config.php'de yanlış çerez alanı veya yolu, çerezlere SameSite=Strict ekleyen bir sunucu ya da CDN kuralı (bu tür çerezler Facebook'tan dönüşte gönderilmez), süresi dolmuş oturum ya da tarayıcı geçmişinden veya yer iminden sonradan yeniden açılan dönüş adresiTek bir kanonik alan adı seçin, diğerlerini 301 ile ona yönlendirin, Board URL'yi buna göre ayarlayın, çerez ayarlarını varsayılana döndürün, SameSite=Strict kuralını kaldırın ve girişi baştan başlatın
XenForo: An error occurred while connecting with Facebook. Please try again later.Belirteç kaydedilemedi: yanlış App ID ya da App Secret, Facebook'a HTTPS ile ulaşamayan bir sunucu ya da yeniden kullanılan bir yetkilendirme kodu (OAuth 2.0'ı tanımlayan RFC 6749'a göre bu kod kısa ömürlü ve tek kullanımlıktır)Setup > Connected accounts > Test provider ile test edin: test modunda XenForo, Facebook'un döndürdüğü asıl hata metnini gösterir. Bilgileri yeniden girin, sunucudan dışarıya HTTPS bağlantısını test edin ve girişi baştan başlatın
XenForo: Unfortunately, you did not grant permission to access your connected account. This is required to continue.Üye Facebook'un izin penceresini iptal etti ya da izni reddetti (XenForo e-posta iznini ister)Girişi yeniden deneyip izin penceresini onaylayın; sunucuda düzeltilecek bir şey yoktur
XenForo: The email address linked to this Facebook account belongs to another member's account…Aynı e-posta adresiyle kayıtlı bir üye zaten var; XenForo hesapları kendiliğinden bağlamazÜye önce parolasıyla giriş yapar, ardından Facebook'u hesabının Connected accounts sayfasından bağlar
Giriş tamamlanıyor ama üye hâlâ çıkış yapmış görünüyorÇerez alanı veya yolu, karışık alan adları ya da misafir sayfalarını önbellekten sunan bir CDN veya sayfa önbelleğiYukarıdakilerle aynı; ayrıca oturum açmış ziyaretçileri HTML önbelleğinin dışında tutun

Çerez ayarları config.php dosyasındadır: $config['cookie']['prefix'] (varsayılan xf_), $config['cookie']['path'] (varsayılan /) ve $config['cookie']['domain'] (varsayılan olarak boştur; çerez yalnızca onu oluşturan alan adına ait olur). XenForo kılavuzu, yanlış değerlerin yöneticiler dahil herkesin giriş yapamamasına yol açabileceği konusunda uyarır ve bir alan adında tek kurulum varsa bu ayarlara dokunmaya gerek olmadığını belirtir. İki alan adını birlikte çalıştırmak için çerez alanını genişletmek yerine birini web sunucusunda diğerine yönlendirin.

Canlı moda geçerken: Meta, Settings > Basic altında bir gizlilik politikası adresi ister (XenForo kılavuzu kullanım şartları adresini de girmenizi söyler). Meta'nın veri silme SSS'ine göre ayrıca bir veri silme talimatları adresi ya da bir veri silme geri çağırma (callback) adresi vermeniz gerekir. Geri çağırmayı uygulayan bir eklentiniz yoksa en kolay yol, üyelerin hesaplarının ve verilerinin silinmesini nasıl isteyebileceklerini anlatan bir yardım sayfasıdır. Uygulamanın oluşturulması, izinler ve canlıya alma adımları için XenForo için Facebook Login uygulaması oluşturma rehberimize bakabilirsiniz; yönlendirme adresi olarak 1. adımdaki değeri kullanın.

Analitik ve SEO etkisi​

  • Sunucu tarafı: fragment sunucuya hiç ulaşmaz; erişim günlükleri, sunucu tarafı istatistikler ve yeniden yazma (rewrite) kuralları onu görmez. Hiçbir nginx ya da .htaccess kuralının #_=_ ekini silememesinin nedeni de budur.
  • Arama motorları: botlar Facebook ile giriş yapmaz; #_=_ ekli bir bağlantı paylaşılıp taransa bile fragment sayfanın içeriğini değiştirmez ve XenForo'nun kanonik bağlantısı fragment içermez. Google'ın JavaScript SEO rehberi, Googlebot bu tür adresleri güvenilir biçimde çözümleyemediği için farklı içerikleri fragment ile yüklememeyi önerir; #_=_ ise içeriği hiç değiştirmez. Bu yüzden ek, yinelenen içerik (duplicate content) sorunu yaratmaz ve robots.txt kuralı gerektirmez.
  • İstemci tarafı: sayfadaki betikler adresi fragment'ıyla birlikte okur. Google'ın gtag.js belgesine göre GA4'te page_location değerinin varsayılanı fragment'ı içermez; ancak page_location değerini kendi değişkeniyle dolduran Tag Manager kurulumları, başka analitik araçları, ısı haritaları ve oturum kaydı araçları adresin tamamını saklayabilir. Kendi kurulumunuzun ne kaydettiğini DebugView'da kontrol edin.
  • Çift sayım: GA4 varsayılan olarak tarayıcı geçmişi değiştiğinde de sayfa görüntüleme gönderir (geliştirilmiş ölçümdeki "Page changes based on browser history events" ayarı); Google'ın yardım sayfasına göre bu seçenek pushState, popState ve replaceState çağrılarını dinler. Tag Manager'ın History Change tetikleyicisi de fragment değiştiğinde ya da sayfa History API'yi kullandığında çalışır. Temizlik bu dinleyiciler kurulduktan sonra çalışırsa, kurulumunuza bağlı olarak fazladan bir sayfa görüntüleme sayılabilir. Kodu head bölümünün en üstünde, bütün etiketlerden önce çalıştırmak iki sorunu birden önler.

Sık sorulan sorular​

#_=_ bir güvenlik sorunu mu?
Hayır. Belirteç ya da kişisel veri içermeyen, anlamsız bir yer tutucudur. Silmek girişin güvenliğini zayıflatmaz; CSRF koruması state parametresinden gelir.

Facebook'un bu eki eklemesini engelleyebilir miyim?
Pratikte hayır. Facebook eki, yönlendirme adresinde fragment olmadığında ekler; OAuth 2.0'ı tanımlayan RFC 6749 (3.1.2. bölüm) ise yönlendirme adresinde fragment bulunmasına zaten izin vermez. XenForo'nun yönlendirme adresi de sabittir (Board URL + /connected_account.php) ve uygulama ayarlarınızla birebir eşleşmek zorundadır. Eki tarayıcıda temizlemek en sağlam yoldur.

Kod gönderi bağlantılarını ya da profil sekmelerini bozar mı?
Hayır. Fragment'ı yalnızca '#_=_' değeriyle birebir karşılaştırır, başka her değeri yok sayar.

Sunucu tarafında bir yönlendirme kuralı gerekir mi?
Hayır; işe de yaramaz, çünkü sunucu fragment'ı hiç almaz.

Değişikliği ekledim ama #_=_ hâlâ görünüyor. Neye bakmalıyım?
Değişikliğin etkin olduğuna ve "bulunamadı" sayacının sıfır olduğuna, kodun sayfa kaynağında analitik kodlarının üstünde yer aldığına, konsolda CSP hatası olmadığına ve CDN'inizin ya da sayfa önbelleğinizin eski HTML'i sunmadığına bakın (değişiklikten sonra önbelleği temizleyin).

Google ile girişte de gerekli mi?
Bu ek Facebook'a özgüdür. Kod başka her fragment'ı yok saydığı için Google, Microsoft ya da GitHub girişlerinden sonra zararsızdır. XenForo kılavuzu Google için de aynı dönüş adresini verir: Google Cloud Console'da Authorized redirect URIs alanına Board URL + /connected_account.php yazılır. Google tarafındaki diğer adımlar için XenForo için Google Login API entegrasyonu konusuna bakabilirsiniz.

Sonuç ve sonraki adımlar​

Özetle #_=_, Facebook'un yönlendirmeye eklediği ve tarayıcının XenForo'nun kendi yönlendirmeleri boyunca taşıdığı görsel bir ektir. Önce altyapıyı düzeltin (Board URL, yönlendirme adresi, HTTPS, tek kanonik alan adı, varsayılan çerez ayarları), ardından şablon değişikliğini ekleyin, masaüstünde, telefonda ve uygulama içi tarayıcıda test edin ve analitiğin temiz adresleri kaydettiğini doğrulayın. Kurulumu ve bakımı bir ekibe bırakmak isterseniz AIOR'un forum ve topluluk hizmetlerine göz atabilirsiniz.

After a member signs in with the Facebook button on the login form, XenForo sends them back to the forum, but the address bar now ends in #_=_: https://forum.example.com/#_=_ or https://forum.example.com/threads/some-topic.123/#_=_. The page works and nothing is broken, but the address looks like an error, it ends up in links that members copy and share, and any script that reads the full URL sees it. This page explains where the marker comes from, how to make sure the Facebook app points at the right XenForo address, how to remove the marker with a template modification that survives upgrades, how to test the fix, and which related errors appear after a Facebook login.

We have rewritten this post. The earlier version said that XenForo 2.2 and later remove the fragment automatically and that Facebook adds it to stop XSS and CSRF. We could not confirm either claim, so both are corrected below.

Quick fix checklist​

  1. In the Facebook app, make sure Valid OAuth Redirect URIs contains your Board URL followed by /connected_account.php, for example https://forum.example.com/connected_account.php.
  2. In XenForo, add a template modification to PAGE_CONTAINER that inserts the snippet below right after the meta charset tag.
  3. Open https://forum.example.com/#_=_ in a new tab. The address bar should immediately show https://forum.example.com/.
  4. Do a real Facebook login in a private window, on a phone and in Facebook's in-app browser, then check that links to posts (#post-123) still jump to the right place.

What #_=_ is and where it comes from​

The part of a URL after the # sign is the fragment, often called the hash. The browser keeps it to itself and does not send it to the server: RFC 9110 (HTTP Semantics) says the target URI excludes the fragment, which is reserved for client-side processing. In #_=_ the fragment is an underscore, an equals sign and another underscore: a placeholder key=value pair with no meaning. It also disappears as soon as the member clicks any link, because a normal link does not carry the old fragment along.

Facebook's only public note on it is two sentences long. In a developer blog post dated 2 September 2011 ("Platform Updates: Operation Developer Love"), under the heading "Change in Session Redirect Behavior", Facebook wrote that it had started adding the fragment #_=_ to the redirect_uri "when this field is left blank", and asked apps to make sure they could handle it. The usual reading, and the behaviour developers report, is that Facebook appends #_=_ whenever the address it sends the browser back to has no fragment of its own. XenForo's return address has none, which is why the marker shows up on XenForo boards. The note gives no further reason.

The most likely reason is fragment inheritance across HTTP redirects. Section 10.2.2 of RFC 9110 says that when the Location of a 3xx redirect has no fragment, the browser must process the redirect as if the new address inherits the fragment of the original one. Section 17.11 warns that this can disclose one site's fragment to another site, and advises sites that keep personal information in fragments to give redirects to other sites a (possibly empty) fragment of their own, which blocks the inheritance. Facebook's login dialog can return data in fragments: according to Meta's manual login flow documentation, response_type=token puts the access token in the fragment. Always sending a harmless fragment is a cheap way to make sure that nothing from a facebook.com address follows the user to your site. This reading fits the standard, but Facebook has not published this reasoning, so treat it as the most plausible explanation rather than an official one.

What #_=_ is not: it is not CSRF protection. In OAuth that job belongs to the state parameter, as Meta's Login Security guide says. The marker carries no token and no personal data.

Why it stays on XenForo pages​

We traced the flow in the XenForo 2.3 source:
  1. The member clicks the Facebook button under "Log in using" on the login form. XenForo stores the request (provider and return address) in the visitor's session and redirects the browser to Facebook's login dialog. The redirect_uri it sends is the Board URL option followed by /connected_account.php.
  2. Facebook sends the browser back to connected_account.php?code=…&state=…#_=_.
  3. connected_account.php exchanges the code for a token and answers with a 302 redirect to /register/connected-accounts/facebook/. That Location has no fragment, so the browser keeps #_=_.
  4. If the Facebook account is already linked to a member, XenForo logs them in and redirects to the page where they started, again without a fragment, so the marker stays. If it is not linked, XenForo shows the form for registering or linking an existing account at that same address, still with #_=_.
So the marker follows the member to whatever page the flow ends on. We found no code in XenForo 2.3's core JavaScript or core templates that removes it (we checked the files served by our own 2.3 board and the 2.3.4 template set). Unless you have seen the marker disappear on its own on your board, assume you need the fix. If you never see the marker, an add-on, your style or an analytics script may already be cleaning it; search the page source for _=_ to find out.

Step 1: Check the redirect URI and the Board URL​

XenForo's manual page for the Facebook connected account (checked on 27 October 2026) says: enter your board URL followed by /connected_account.php in Valid OAuth redirect URIs, for example https://xenforo.com/community/connected_account.php; the beginning of this URL must match your Board URL setting exactly; and the Board URL requires HTTPS. XenForo 2.3 builds the redirect URI from the Board URL option at run time, so the two values must agree character for character. Meta compares the redirect URI with your list as an exact match, including every parameter except state. That is how Strict Mode works, and Meta's security guide says Strict Mode is required for all apps.

The Board URL is under Setup > Options > Basic options (the group was called Basic board information in 2.0 and 2.1). Since 2.2.9 the option's hint says the URL should not include a trailing "/", a query string, a hash fragment or a file name such as index.php, and it shows a suggested URL.

Board URLEntry in Valid OAuth Redirect URIsResult
https://forum.example.comhttps://forum.example.com/connected_account.phpCorrect
https://www.example.com/communityhttps://www.example.com/community/connected_account.phpCorrect (subfolder and www included)
https://www.example.com/communityhttps://example.com/community/connected_account.phpURL Blocked: the host differs (www)
http://forum.example.comhttp://forum.example.com/connected_account.phpRejected: Facebook requires HTTPS for OAuth redirects
https://forum.example.comhttps://forum.example.com/register/connected/facebook (a path found in older guides)URL Blocked: the path differs

Two more settings in the Facebook app matter. Client OAuth Login and Web OAuth Login must be on (the URL Blocked message itself asks you to check them), and if you filled in App Domains under Settings > Basic, the forum's domain must be on that list. After any change, run Setup > Connected accounts > Test provider in XenForo. Fixing the redirect URI and the Board URL first prevents many URL Blocked errors and redirect loops; the cosmetic fix only makes sense once the login itself works.

Step 2: Remove #_=_ with a template modification​

Do not paste the script straight into PAGE_CONTAINER. A direct edit customises the template in that one style: when an upgrade changes the master template, your copy appears under Outdated templates and has to be merged, the change disappears if the template is reverted, and a style with its own copy of PAGE_CONTAINER never gets it. A template modification is stored separately, can be switched off with one click, and XenForo applies it to every copy of the template in every style where the Find text matches.

  1. In the admin control panel open Appearance > Template modifications (in the Styles & templates group). This needs the admin permission "Manage styles, style properties, and templates".
  2. With the Public tab selected, click Add template modification.
  3. Template: PAGE_CONTAINER. Modification key: fb_hash_cleanup (letters, numbers and underscores only). Description: Remove #_=_ after Facebook login.
  4. Search type: Simple replacement. Find: the meta charset tag copied exactly from the Template contents box. In the default 2.3 template it is the line shown below.
  5. Replace: the block below. $0 puts the found text back, so the meta tag stays where it is and the script follows it.
  6. Click Test to preview the result, then save with Automatically apply template modification ticked.

Find:
Kod:
<meta charset="utf-8" />

Replace:
Kod:
$0
<script>
(function () {
    if (window.location.hash !== '#_=_') return;
    try {
        window.history.replaceState(window.history.state, '', window.location.pathname + window.location.search);
    } catch (e) {}
})();
</script>

What the snippet does:
  • It acts only when the fragment is exactly #_=_. #post-123, a profile tab or any other anchor is left alone.
  • history.replaceState rewrites the current history entry without reloading the page and without adding a new entry, so the Back button does not return to the #_=_ address.
  • The second argument is an empty string, which MDN describes as the traditional and future-proof value, and the new URL is only the path plus the query string, so it is always same-origin.
  • It keeps history.state, so it does not wipe state that another script may have stored.
  • The try/catch is there because replaceState can throw in rare cases (MDN lists a document that is not fully active, an invalid URL and too many calls). A cosmetic fix must never break the page.
  • It contains neither {$ nor {{, so XenForo's template compiler leaves it untouched.

The snippet in the earlier version of this post fell back to window.location.hash = '' in browsers without replaceState. All current browsers support replaceState, and that fallback leaves a bare # at the end of the address, so we dropped it.

Placement matters. The snippet runs while the head is being parsed: before XenForo's deferred JavaScript and before the google_analytics template, which XenForo 2.3 includes at the very end of the head, subject to its cookie consent setting. After saving, open any page, view the source, search for _=_ and confirm that the snippet appears once and sits above any Google Analytics, Tag Manager or other tracking code that add-ons or your style insert. In the template modification list, the counters next to the entry show how many templates it was applied to, how many did not contain the Find text and how many produced errors. A non-zero "not found" count usually means a style with its own customised PAGE_CONTAINER whose meta charset line differs; add a second modification with the Find text copied from that style's template.

Alternative: a small JavaScript file​

If you prefer files to inline code, or your Content Security Policy forbids inline scripts, put the same function (without the script tags) in js/custom/fb-hash-cleanup.js under the XenForo root and use this Replace value instead:
Kod:
$0
<script src="{{ base_url('js/custom/fb-hash-cleanup.js') }}"></script>
Leave out async and defer, so the file runs at that point in the head. A script loaded this way pauses parsing until it arrives; the file is tiny and cached after the first visit, so the delay is usually negligible, but it is still one more request for every new visitor. XenForo's xf:js tag can also load files from the js directory, but on our 2.3 board those files are emitted with the defer attribute: they run only after the page has been parsed, after any inline analytics code in the head. That is fine for the address bar and too late if you want analytics to record the clean URL. The file is not part of the XenForo package, so list it in your deployment notes and backups, and when you edit it, rename it or add a query string such as ?v=2 so browsers stop using the cached copy.

Content Security Policy​

Your web server, CDN or an add-on may send a Content-Security-Policy header. Check with:
Bash:
curl -sI https://forum.example.com/ | grep -i content-security-policy
If the policy's script-src directive (or default-src, when there is no script-src) does not allow inline scripts, the snippet is blocked and the browser console reports a CSP violation. MDN lists three ways to allow an inline script: 'unsafe-inline', a nonce, or a hash that matches the script. 'unsafe-inline' weakens the whole policy and a nonce has to be generated afresh by the server for every response, so in practice you have two options: add the snippet's hash to script-src ('sha256-…'), or use the external file, which a policy with 'self' in script-src already allows. MDN notes that the hash is computed over the script's contents only, without the script tags, and that whitespace and capitalisation count, so a single extra space changes it. Chromium-based browsers print the expected hash in the console error. A Content-Security-Policy-Report-Only header blocks nothing and only reports violations, which makes it a safe way to try a stricter policy first.

Step 3: Test the fix​

  1. Without Facebook: open https://forum.example.com/#_=_ in a new tab. To try it on a page that is already open, add #_=_ to the address, press Enter and then F5: when only the fragment changes, Enter does not reload the page, so the snippet would not run, while F5 does reload it. The clean address should appear straight away.
  2. Anchors: open the link behind a post's date or number in its header (it looks like /threads/…/post-123) in a new tab. XenForo redirects to the thread page with #post-123, and the page should still scroll to that post.
  3. Back button: after the cleanup, Back should go to the previous page, not to the #_=_ version.
  4. Real login in a private (incognito) window: once with a Facebook account already linked to a member, once with an unlinked account that gets the register-or-link form.
  5. Phones: Safari on iOS and Chrome on Android.
  6. Facebook's in-app browser: send the forum link to yourself in Messenger, or post it where only you can see it, open it inside the Facebook or Messenger app and log in. In-app browsers often hide the full address; use their menu to copy the link and paste it somewhere you can read it.
  7. Analytics: in GA4 Realtime or DebugView, the page view after the login should show the clean address and should be counted once.

Related problems after a Facebook login​

Rows that start with "XenForo:" quote XenForo 2.3's English phrases; with a language pack installed you will see the translated text.

Symptom or messageLikely causeFix
Facebook: URL BlockedThe redirect URI is not in Valid OAuth Redirect URIs, or Client/Web OAuth Login is offSet the Board URL and the redirect URI as in Step 1 and switch both OAuth options on
Facebook: Insecure Login Blocked (or URL Blocked)The Board URL starts with http://Move the board to HTTPS and update the Board URL
Facebook: App not activeThe app is in Development mode, where only people with a role on the app (admin, developer, tester) can log inFill in the required fields and switch the app to Live; for tests, add the account as a tester
XenForo: There is no valid connected account request available. Please try again.The session cookie was not sent on the way back: the login started on www.example.com and returned to example.com (or http and https were mixed), a wrong cookie domain or path in config.php, a server or CDN rule that forces SameSite=Strict on cookies (such cookies are not sent when Facebook redirects back), an expired session, or a callback address opened again later from history or a bookmarkPick one canonical host, 301-redirect the others to it, set the Board URL to it, restore the default cookie settings, remove any SameSite=Strict rewrite and start the login again
XenForo: An error occurred while connecting with Facebook. Please try again later.No token was stored: a wrong App ID or App Secret, a server that cannot reach Facebook over HTTPS, or a reused authorization code (OAuth 2.0, RFC 6749, makes codes short-lived and single-use)Run Setup > Connected accounts > Test provider: in test mode XenForo shows Facebook's own error text. Re-enter the credentials, test outbound HTTPS from the server and start again
XenForo: Unfortunately, you did not grant permission to access your connected account. This is required to continue.The member cancelled or declined Facebook's permission dialog (XenForo asks for the email permission)Try again and accept the dialog; nothing to fix on the server
XenForo: The email address linked to this Facebook account belongs to another member's account…A member already registered with the same email address, and XenForo does not link the accounts automaticallyThe member logs in with their password, then links Facebook from the Connected accounts page of their account
Login completes, but the member still looks logged outCookie domain or path, mixed hosts, or a CDN or page cache that serves cached guest pagesAs above, and keep logged-in visitors out of the HTML cache

Cookie settings live in config.php: $config['cookie']['prefix'] (default xf_), $config['cookie']['path'] (default /) and $config['cookie']['domain'] (empty by default, which ties the cookie to the host that set it). XenForo's manual warns that wrong values can leave everyone, administrators included, unable to log in, and that a single installation on a domain has no reason to change them. To make two hosts work, redirect one to the other at the web server instead of widening the cookie domain.

Going Live: Meta asks for a privacy policy URL under Settings > Basic (XenForo's manual also asks for the terms of service URL), and Meta's data deletion FAQ says you must provide either a data deletion instructions URL or a data deletion callback URL. If you have no add-on that implements the callback, a help page explaining how members can ask for their account and data to be deleted is the simple route. For creating the app, its permissions and going Live, see our guide How to Create a Facebook Login App for XenForo; for the redirect URI, use the value from Step 1.

Analytics and SEO​

  • Server side: the fragment never reaches the server, so access logs, server-side statistics and rewrite rules never see it. That is also why no nginx or .htaccess rule can remove #_=_.
  • Search engines: crawlers do not log in with Facebook, and even if a shared link with #_=_ is crawled, the fragment does not change the page and XenForo's canonical link carries no fragment. Google's JavaScript SEO guide advises against using fragments to load different content because Googlebot cannot reliably resolve such URLs; #_=_ does not change the content at all. So the marker causes no duplicate-content problem and needs no robots.txt rule.
  • Client side: scripts in the page read the address together with the fragment. Google's gtag.js documentation says the default page_location in GA4 excludes the fragment, but Tag Manager setups that fill page_location from their own variables, other analytics tools, heatmaps and session recorders may store the full URL. Check in DebugView what your own setup records.
  • Double counting: by default GA4 also sends a page view when the browser history changes (the "Page changes based on browser history events" setting under enhanced measurement), and Google's help page says this option listens for pushState, popState and replaceState. A Tag Manager History Change trigger also fires when the fragment changes or the page uses the History API. If the cleanup runs after those listeners are in place, it can be counted as an extra page view, depending on your setup. Running the snippet at the top of the head, before any tag, avoids both problems.

Frequently asked questions​

Is #_=_ a security problem?
No. It is a meaningless placeholder with no token or personal data. Removing it does not weaken the login; CSRF protection comes from the state parameter.

Can I stop Facebook from adding it?
Not in any practical way. Facebook adds it when the redirect address has no fragment, and OAuth 2.0 (RFC 6749, section 3.1.2) does not allow a fragment in a redirect address anyway. XenForo's redirect URI is also fixed (Board URL plus /connected_account.php) and has to match your app settings exactly. Cleaning it in the browser is the reliable fix.

Will the snippet break links to posts or profile tabs?
No. It compares the fragment with '#_=_' exactly and ignores every other value.

Do I need a server-side redirect?
No, and it would not work: the server never receives the fragment.

I added the modification but still see #_=_. What should I check?
That the modification is enabled and its "not found" counter is zero, that the snippet is in the page source above the analytics code, that the console shows no CSP error, and that your CDN or page cache is not serving old HTML (purge it after the change).

Is this needed for Google login too?
The marker is Facebook's. The snippet ignores every other fragment, so it is harmless after Google, Microsoft or GitHub logins. XenForo's manual gives the same return address for Google: enter your Board URL plus /connected_account.php under Authorized redirect URIs in Google Cloud Console. For the rest of the Google setup, see How to Set Up Google Login API for XenForo.

Conclusion and next steps​

In short, #_=_ is a cosmetic marker that Facebook adds to its redirect and that the browser carries through XenForo's own redirects. Fix the plumbing first (Board URL, redirect URI, HTTPS, one canonical host, default cookie settings), then add the template modification, test it on a desktop, on a phone and in the in-app browser, and confirm that analytics records clean URLs. If you would rather hand the setup and upkeep to a team, AIOR offers forum and community services.
 

Ekler

  • 1687520419705.webp
    1687520419705.webp
    47 KB · Görüntülenme: 3
Son düzenleyen:

Forum istatistikleri

Konular
925
Mesajlar
932
Üyeler
26
En son üye
Jessicawatson

Çevrimiçi üyeler

Şu anda çevrimiçi üye yok.

Öne çıkan içerik

AIOR
AIOR TEKNOLOJİ

Tüm ihtiyaçlarınız için Teklif alın

Hosting · Domain · Sunucu · Tasarım · Yazılım · Mühendislik · Sektörel Çözümler

Teklif al

7/24 Destek · Anında yanıt

Geri
Üst