const isDebugMode = window.location.search.includes('debug=true'); let debugLogContainer = null; let debugLogCounter = 0; const cookieDomain = '.' + getMainDomain(window.location.href); firebaseDebugLog(true, 'cookieDomain-' + cookieDomain); let refreshInterval; let logoutInProgress = false; let pendingCred = null; document.addEventListener('DOMContentLoaded', function () { // Create debug overlay if debug mode is enabled if (isDebugMode) { createDebugOverlay(); } //Safe to expose as they are identification values not auth keys const firebaseConfig = { apiKey: "AIzaSyA6qrL3tY40YlRkSK4XTS7zijAJ4n15MNU", authDomain: "sso.consequence.net", projectId: "consequence-25a8e", storageBucket: "consequence-25a8e.appspot.com", messagingSenderId: "993189234631", appId: "1:993189234631:web:4d0a240cc0ab799b65fbe2", measurementId: "G-V7CZFS1TQG" }; firebase.initializeApp(firebaseConfig); // Check for native Facebook OAuth callback first (Option 5) handleFacebookOAuthCallback().then(handled => { if (handled) { firebaseDebugLog(true, 'Facebook OAuth callback handled, skipping Firebase redirect check'); return; } // If not a Facebook OAuth callback, check for Firebase redirect result return firebase.auth().getRedirectResult(); }).then(async (result) => { if (!result) return; // Already handled by Facebook OAuth callback if (!result || !result.user) return; const user = result.user; const idToken = await user.getIdToken(); const response = await login(user, idToken); if (response && response.success) { window.location.reload(); } else { console.log("WP login failed after redirect"); } }) .catch((e) => { console.log("getRedirectResult error:", e.code, e.message, e); }); var googleLoginBtn = document.getElementById('googleLoginBtn'); var facebookLoginBtn = document.getElementById('facebook-login'); var twitterLoginBtn = document.getElementById('twitter-login'); var appleLoginBtn = document.getElementById('apple-login'); var logoutBtn = document.getElementById('logoutBtn'); if (googleLoginBtn) { googleLoginBtn.addEventListener('click', function () { var provider = new firebase.auth.GoogleAuthProvider(); provider.setCustomParameters({ prompt: 'select_account' }); handleSignInWithProvider(provider, 'google'); }); } // Facebook Authentication if (facebookLoginBtn) { facebookLoginBtn.addEventListener('click', function () { var provider = new firebase.auth.FacebookAuthProvider(); // provider.setCustomParameters({ // auth_type: 'reauthenticate' // }); handleSignInWithProvider(provider, 'facebook'); }); } // Twitter Authentication if (twitterLoginBtn) { twitterLoginBtn.addEventListener('click', function () { var provider = new firebase.auth.TwitterAuthProvider(); provider.setCustomParameters({ 'force_login': 'true' // Forces the user to reauthenticate }); handleSignInWithProvider(provider, 'twitter'); }); } // Apple Authentication if (appleLoginBtn) { appleLoginBtn.addEventListener('click', function () { var provider = new firebase.auth.OAuthProvider('apple.com'); handleSignInWithProvider(provider, 'apple'); }); } if (logoutBtn) { logoutBtn.addEventListener('click', function () { logout(); }); } firebase.auth().onAuthStateChanged((user) => { firebaseDebugLog(true, '---Start onAuthStateChanged---'); if (logoutInProgress == true) return; // Don't logout if Facebook OAuth is in progress (Option 5 only) if (localStorage.getItem('fb_oauth_processing') === 'true') { firebaseDebugLog(true, 'Facebook OAuth in progress, skipping auth state check'); firebaseDebugLog(true, '---End onAuthStateChanged---'); return; } if (user) { syncGeoToLambda(user.email); firebaseDebugLog(true, 'User signed in:' + user); // regenerateIdToken(user); // Start the refresh process if (checkCookieExists()) { firebaseDebugLog(true, 'CookieExists'); startTokenRefresh(user); } else { firebaseDebugLog(true, 'No CookieExists'); firebaseDebugLog(true, 'No sessioncookie found, logout'); localStorage.setItem('localLogout', 2); //1=local, 2=auto logout(); } } else { firebaseDebugLog(true, 'No user signed in'); clearInterval(refreshInterval); // Clear the interval on sign-out firebaseDebugLog(true, 'On authstatechange check cookie'); // checkSessionCookie(); } firebaseDebugLog(true, '---End onAuthStateChanged---'); }); async function handleSignInWithProvider(provider, pname) { firebaseDebugLog(true, '---Start handleSignInWithProvider'); const loader = document.getElementById('loginSpinner'); try { localStorage.setItem('loggedInLocally', 'true'); logoutInProgress = true; // Option 5: Use native Facebook OAuth for mobile devices ONLY // This includes: mobile regular browsers AND mobile in-app browsers // Desktop in-app browsers will use standard popup flow // This bypasses Firebase's /__/auth/ handler which is blocked by nginx if (pname === 'facebook' && isMobileDevice()) { firebaseDebugLog(true, 'Using custom Facebook OAuth (Option 5) for mobile device'); await handleFacebookNativeAuth(); return; } if (isInAppBrowser()) { await firebase.auth().signInWithRedirect(provider); return; } const result = await firebase.auth().signInWithPopup(provider); loader.style.display = 'flex'; document.getElementById('socialLogin').style.display = 'none'; document.querySelector('.sfba-close').style.display = 'none'; const user = result.user; firebaseDebugLog(true, 'handleSignInWithProvider-' + user); const idToken = await user.getIdToken(); firebaseDebugLog(true, 'ID Token:-' + idToken); const response = await login(user, idToken); if (!response || !response.success) { // Handle unsuccessful login localStorage.removeItem('loggedInLocally'); document.getElementById('socialLogin').style.display = 'block'; document.querySelector('.sfba-close').style.display = 'block'; loader.style.display = 'none'; throw new Error('Failed to authenticate.'); } logoutInProgress = false; window.location.reload(); // Reload the page on successful login } catch (error) { logoutInProgress = false; firebaseDebugLog(true, 'Error during Firebase authentication:' + error.message); localStorage.removeItem('loggedInLocally'); // Ensure localStorage is cleaned up handleLoginError(error); } firebaseDebugLog(true, '---End handleSignInWithProvider'); } function login(user, idToken) { firebaseDebugLog(true, '---Start Login'); return new Promise((resolve, reject) => { jQuery.ajax({ url: firebaseAuthAjax.ajax_url, method: 'POST', data: { action: 'firebase_login', nonce: firebaseAuthAjax.nonce, email: user.email, display_name: user.displayName, provider_id: user.providerData[0].uid, provider_name: user.providerData[0].providerId, idToken: idToken, firebase_uid: user.uid }, success: function (response) { firebaseDebugLog(true, 'login success response:-' + response); setCookie('ssosession', idToken, 24, cookieDomain); syncGeoToLambda(user.email); resolve(response); firebaseDebugLog(true, '---End Login'); }, error: function (error) { firebaseDebugLog(true, 'Error logging in:-' + error); reject(error); } }); }); } async function handleLoginError(error) { if (error.code === 'auth/account-exists-with-different-credential') { jQuery('.temp-preferences').show(); jQuery('.temp-preferences .sfba-before-login').show(); jQuery(".socialLogin").hide(); var email = error.email; // Store credential in memory - cannot reliably serialize Firebase credentials to JSON pendingCred = error.credential; try { var methods = await firebase.auth().fetchSignInMethodsForEmail(email); if (methods.length > 0) { localStorage.setItem('existingProvider', methods[0]); jQuery(".sfba-mask").removeClass("sfba-active"); jQuery(".sfba-link-mask").addClass('sfba-active'); handleLinkModel(methods[0]); } } catch (fetchError) { firebaseDebugLog(true, 'Error fetching sign-in methods: ' + fetchError.message); } } else if (error.code === 'auth/popup-blocked' || error.code === 'auth/popup-closed-by-user') { firebaseDebugLog(true, 'Popup blocked or closed by user'); // Note: Cannot redirect here as we don't have provider context } else { firebaseDebugLog(true, error.message); jQuery('.temp-preferences').hide(); jQuery('.temp-preferences .sfba-before-login').hide(); jQuery(".socialLogin").show(); localStorage.removeItem('Firebaseuserstorage'); } } function handleLinkModel(provider) { // Hide all link buttons first, then show only the relevant one jQuery(".sfba-social-btn-link").hide(); if (provider == 'google.com') { jQuery("#socialLoginLink .link-message .provider-name").html("Google"); jQuery(".sfba-social-btn-link.sfba-login-with-google-btn").show(); } else if (provider == 'facebook.com') { jQuery("#socialLoginLink .link-message .provider-name").html("Facebook"); jQuery(".sfba-social-btn-link.sfba-login-with-facebook-btn").show(); } else if (provider == 'apple.com') { jQuery("#socialLoginLink .link-message .provider-name").html("Apple"); jQuery(".sfba-social-btn-link.sfba-login-with-apple-btn").show(); } else { firebaseDebugLog(true, 'Provider doesnt exist: ' + provider); } } function getAuthProvider(providerId) { switch (providerId) { case firebase.auth.GoogleAuthProvider.PROVIDER_ID: return new firebase.auth.GoogleAuthProvider(); case firebase.auth.FacebookAuthProvider.PROVIDER_ID: return new firebase.auth.FacebookAuthProvider(); case 'apple.com': return new firebase.auth.OAuthProvider('apple.com'); default: throw new Error('No provider found for the given provider ID.'); } } // Modal for SSO Social media buttons and Add ARtist/Tags jQuery(".sfba-show").on("click", function () { var errorElement = document.getElementById("errorMessage"); if (errorElement) { errorElement.innerHTML = ''; } jQuery(".sfba-mask").addClass("sfba-active"); }); // Close popup jQuery(".sfba-close").on("click", function () { jQuery(".sfba-mask").removeClass("sfba-active"); }); // Close popup jQuery(".sfba-link-close").on("click", function () { jQuery(".sfba-link-mask").removeClass("sfba-active"); }); jQuery(".sfba-show-pref").on("click", function () { jQuery(".sfba-mask-pref").addClass("sfba-active"); }); jQuery(".sfba-close-pref").on("click", function () { jQuery(".sfba-mask-pref").removeClass("sfba-active"); }); jQuery('.tab-nav span').on('click', function () { if (jQuery(this).text() == 'My Tags') { jQuery('#all-preferences .tab-nav ul li').removeClass('active'); jQuery('#all-preferences .tab-nav ul li:nth-child(2)').addClass('active'); jQuery('#all-preferences #all-artists').removeClass('active'); jQuery('#all-preferences #all-tags').addClass('active'); } else { jQuery('#all-preferences .tab-nav ul li').addClass('active'); jQuery('#all-preferences .tab-nav ul li:nth-child(2)').removeClass('active'); jQuery('#all-preferences #all-artists').addClass('active'); jQuery('#all-preferences #all-tags').removeClass('active'); } jQuery([jQuery(this).parent()[0], jQuery(jQuery(this).data('href'))[0]]).addClass('active').siblings('.active').removeClass('active'); }); // Delete Artists/Tags jQuery('body').on('click', '.preference-delete, .preference-add.deleteid', function () { var preftype = jQuery(this).data("preftype"); var currentemailaddress = jQuery("#current-email-address").val(); if (jQuery(this).hasClass('deleteid')) { jQuery(this).removeClass('deleteid'); jQuery(this).addClass('addid'); jQuery(this).find('span.pref-add').html('').html('✛'); jQuery(this).find('span.pref-add').css('color', '#009b1a'); var delId = jQuery(this).data("addid"); if (preftype == "artist") { jQuery(".my-artist-list li").each(function () { if (jQuery(this).find("a").attr("data-delid") == delId) { jQuery(this).remove(); } }); } else { jQuery(".my-tags-list li").each(function () { if (jQuery(this).find("a").attr("data-delid") == delId) { jQuery(this).remove(); } }); } } else { var delId = jQuery(this).data("delid"); jQuery(this).parent().remove(); if (preftype == "artist") { jQuery(".preferences-list ul.artist-list li").each(function () { if (jQuery(this).find("a").attr("data-addid") == delId) { jQuery(this).find('span.pref-add').html('').html('✛'); jQuery(this).find('span.pref-add').css('color', '#009b1a'); } }); } else { jQuery(".preferences-list ul.post_tag-list li").each(function () { if (jQuery(this).find("a").attr("data-addid") == delId) { jQuery(this).find('span.pref-add').html('').html('✛'); jQuery(this).find('span.pref-add').css('color', '#009b1a'); } }); } } jQuery.ajax({ type: 'POST', url: firebaseAuthAjax.ajax_url, cache: true, data: { action: 'delete_preferences_action', currentemailaddress: currentemailaddress, delId: delId, preftype: preftype, }, success: function (response) { if (preftype == "artist") { if (jQuery('ul.my-artist-list').find('li').length === 0) { jQuery('.preferences-list.my-artists-ul').html('

Please click the "plus" icon to the right to add Artists to your profile

'); } } else { if (jQuery('ul.my-tags-list').find('li').length === 0) { jQuery('.preferences-list.my-tags-ul').html('

Please click the "plus" icon to the right to add Tags to your profile

'); } } } }); }); let currentAjaxRequest = null; jQuery('.search-preferences').keyup(function (event) { if ((event.key === 'Enter' && jQuery(this).val().length > 2) || jQuery(this).val().length > 2) { jQuery('.search-pref-btn').click(); } if (event.key === 'Backspace') { jQuery('.search-pref-btn').click(); } }); jQuery('.search-pref-btn').on('click', function () { jQuery('.filterButton').removeClass('active'); searchTerm = jQuery(this).prev().val(); var ptype = jQuery(this).data('type'); var preftype = ''; var prefidstring = ''; var textpref = ''; var arrayinside = false; if (ptype === 'artist') { preftype = "artist"; prefidstring = jQuery("#artist_id").val(); textpref = "Artist"; } else if (ptype === 'post_tag') { preftype = "tags"; prefidstring = jQuery("#tag_id").val(); textpref = "Tags"; } if (searchTerm != "") { // Make AJAX request if (currentAjaxRequest) { currentAjaxRequest.abort(); } currentAjaxRequest = jQuery.ajax({ type: 'POST', url: firebaseAuthAjax.ajax_url, dataType: 'json', data: { action: 'preferences_search_action', nonce: firebaseAuthAjax.nonce, search_term: searchTerm, ptype: ptype }, success: function (response) { currentAjaxRequest = null; jQuery('.' + ptype + '-list li').css("display", "none"); jQuery('.' + ptype + '-list li.nonpop-search-data').remove(); var jsonString = JSON.stringify(response); var dataArray = JSON.parse(jsonString); setTimeout(function () { if (Array.isArray(dataArray) && dataArray.length > 0) { jQuery('.post_tag-list p').remove(); jQuery('.artist-list p').remove(); $.each(dataArray, function (index, item) { if (prefidstring !== '' && prefidstring.includes(item.term_id)) { arrayinside = true; } if (arrayinside) { jQuery('.' + ptype + '-list').append('
  • ' + item.name + '
  • '); } else { jQuery('.' + ptype + '-list').append('
  • ' + item.name + '
  • '); } jQuery('.' + ptype + '-list li.nonpop-search-data').css("display", "block"); }); } else { if (jQuery('.not-found').length === 0) { jQuery('.' + ptype + '-list').append('

    No ' + textpref + ' found

    '); } } }, 500); } }); } else { jQuery('.filterButton:first-child').addClass('active'); jQuery('.' + ptype + '-list li').css("display", "block"); jQuery('.' + ptype + '-list li.nonpop-search-data').remove(); } }); jQuery('.filterButton').on('click', function () { jQuery('.post_tag-list p').remove(); jQuery('.artist-list p').remove(); jQuery('.filterButton').removeClass("active"); var filter = jQuery(this).data('filter'); jQuery(this).addClass("active"); jQuery(this).parent().prev().find('.search-preferences').val(filter); var preid = jQuery(this).parent().parent().attr('id'); if (preid === 'all-artists') { var ptype = 'artist'; } else { var ptype = 'post_tag'; } if (ptype == "artist") { var customclass = '.artist-list li'; } else if (ptype == "post_tag") { var customclass = '.post_tag-list li'; } if (filter == "ALL") { jQuery('.' + ptype + '-list li').css("display", "block"); jQuery('.' + ptype + '-list li.nonpop-search-data').remove(); } else { jQuery(customclass).each(function () { var firstLetter = jQuery(this).text().charAt(0).toUpperCase(); if (firstLetter === filter) { jQuery(this).show(); } else { jQuery(this).hide(); } }); jQuery('.' + ptype + '-list li.nonpop-search-data').remove(); } }); // Add Artists/Tags jQuery('body').on('click', '.preference-add.addid', function () { var preftype = jQuery(this).data("preftype"); var currentemailaddress = jQuery("#current-email-address").val(); var newValueartist = '', newValuetags = '', artistadd = '', tagsadd = ''; if (preftype == 'artist') { newValueartist = jQuery(this).data('addid'); artistname = jQuery(this).data('title'); artistadd = '
  • ' + artistname + '
  • '; } else { newValuetags = jQuery(this).data('addid'); tagsname = jQuery(this).data('title'); tagsadd = '
  • ' + tagsname + '
  • '; } jQuery(this).find('span.pref-add').html('').html('✕'); jQuery(this).find('span.pref-add').css('color', '#ff0000'); jQuery(this).removeClass('addid'); jQuery(this).addClass('deleteid'); jQuery.ajax({ type: 'POST', url: firebaseAuthAjax.ajax_url, cache: true, data: { action: 'add_preferences_action', currentemailaddress: currentemailaddress, preftype: preftype, newValueartist: newValueartist, newValuetags: newValuetags, }, success: function (response) { if (artistadd != '') { if (jQuery(".my-artists-ul").find('p').length) { jQuery(".my-artists-ul").html(''); jQuery(".my-artists-ul").append('
    '); jQuery(".my-artists-ul p").css("display", "none"); } else { // jQuery(".my-artists-ul ul").append(artistadd); appendLi('.my-artist-list', artistadd, artistname); } } if (tagsadd != '') { if (jQuery(".my-tags-ul").find('p').length) { jQuery(".my-tags-ul").html(''); jQuery(".my-tags-ul").append('
    '); jQuery(".my-tags-ul p").css("display", "none"); } else { // jQuery(".my-tags-ul ul").append(tagsadd); appendLi('.my-tags-list', tagsadd, tagsname); } } } }); }); // Delete Artists/Tags jQuery('body').on('click', '.preference-delete, .preference-add.deleteid', function () { var preftype = jQuery(this).data("preftype"); var currentemailaddress = jQuery("#current-email-address").val(); if (jQuery(this).hasClass('deleteid')) { jQuery(this).removeClass('deleteid'); jQuery(this).addClass('addid'); jQuery(this).find('span.pref-add').html('').html('✛'); jQuery(this).find('span.pref-add').css('color', '#009b1a'); var delId = jQuery(this).data("addid"); if (preftype == "artist") { jQuery(".my-artist-list li").each(function () { if (jQuery(this).find("a").attr("data-delid") == delId) { jQuery(this).remove(); } }); } else { jQuery(".my-tags-list li").each(function () { if (jQuery(this).find("a").attr("data-delid") == delId) { jQuery(this).remove(); } }); } } else { var delId = jQuery(this).data("delid"); if (preftype == "artist") { jQuery(".preferences-list ul.artist-list li").each(function () { if (jQuery(this).find("a").attr("data-addid") == delId) { jQuery(this).find('span.pref-add').html('').html('✛'); jQuery(this).find('span.pref-add').css('color', '#009b1a'); } }); } else { jQuery(".preferences-list ul.post_tag-list li").each(function () { if (jQuery(this).find("a").attr("data-addid") == delId) { jQuery(this).find('span.pref-add').html('').html('✛'); jQuery(this).find('span.pref-add').css('color', '#009b1a'); } }); } } jQuery.ajax({ type: 'POST', url: firebaseAuthAjax.ajax_url, cache: true, data: { action: 'delete_preferences_action', currentemailaddress: currentemailaddress, delId: delId, preftype: preftype, }, success: function (response) { if (preftype == "artist") { if (jQuery('ul.my-artist-list').find('li').length === 0) { jQuery('.preferences-list.my-artists-ul').html('

    Please click the "plus" icon to the right to add Artists to your profile

    '); } } else { if (jQuery('ul.my-tags-list').find('li').length === 0) { jQuery('.preferences-list.my-tags-ul').html('

    Please click the "plus" icon to the right to add Tags to your profile

    '); } } } }); }); function appendLi(selector, litoadd, textname) { var $list = jQuery(selector); var $newItem = jQuery(litoadd); var textnameIsNumeric = !isNaN(textname); var inserted = false; $list.children('li').each(function () { var $currentItem = jQuery(this); var currentTextName = $currentItem.find('span:first').text(); var currentIsNumeric = !isNaN(currentTextName); if (textnameIsNumeric && currentIsNumeric) { if (parseFloat(textname) < parseFloat(currentTextName)) { $currentItem.before($newItem); inserted = true; return false; } } else if (!textnameIsNumeric && !currentIsNumeric) { if (String(textname).toLowerCase() < String(currentTextName).toLowerCase()) { $currentItem.before($newItem); inserted = true; return false; } } else if (textnameIsNumeric && !currentIsNumeric) { $currentItem.before($newItem); inserted = true; return false; } }); if (!inserted) { $list.append($newItem); } } jQuery(".sfba-social-btn-link").on("click", async function () { jQuery(".sfba-link-mask").removeClass('sfba-active'); var existingProvider = localStorage.getItem('existingProvider'); localStorage.removeItem('existingProvider'); var authProvider = getAuthProvider(existingProvider); try { // Step 1: Sign in with the existing (original) provider var result = await firebase.auth().signInWithPopup(authProvider); var user = result.user; var idToken = await user.getIdToken(); // Step 2: Log in / create the WordPress user (reuses the same login() helper) var loginResponse = await login(user, idToken); if (!loginResponse || !loginResponse.success) { localStorage.removeItem('loggedInLocally'); throw new Error('Failed to authenticate with WordPress.'); } // Step 3: Link the pending credential (from the failed sign-in attempt) if (pendingCred) { try { // var linkResult = await user.linkWithCredential(pendingCred); // // Update cookie with fresh token from the now-linked account // var newIdToken = await linkResult.user.getIdToken(true); setCookie('ssosession', idToken, 24, cookieDomain); firebaseDebugLog(true, 'Account linking successful'); } catch (linkError) { firebaseDebugLog(true, 'Error linking account (non-fatal): ' + linkError.message); // Linking failed but user is already logged in — proceed with existing token } pendingCred = null; } window.location.reload(); } catch (error) { firebaseDebugLog(true, 'Error during account link flow: ' + error.message); } }); /** * Handle native Facebook OAuth (Option 5) * Redirects to Facebook OAuth URL */ async function handleFacebookNativeAuth() { firebaseDebugLog(true, '=== NATIVE FACEBOOK OAUTH (Option 5) ==='); // Facebook App ID (from Facebook Developer Console) const facebookAppId = '2018160385090572'; // Build Facebook OAuth URL const redirectUri = encodeURIComponent(window.location.origin + window.location.pathname); const state = Math.random().toString(36).substring(7); // Random state for security localStorage.setItem('fb_oauth_state', state); localStorage.setItem('fb_oauth_redirect', window.location.href); const facebookAuthUrl = `https://www.facebook.com/v12.0/dialog/oauth?` + `client_id=${facebookAppId}` + `&redirect_uri=${redirectUri}` + `&state=${state}` + `&scope=email,public_profile` + `&response_type=token`; firebaseDebugLog(true, 'Redirecting to Facebook OAuth:', facebookAuthUrl); // Redirect to Facebook window.location.href = facebookAuthUrl; } /** * Handle Facebook OAuth callback * Called on page load to check if we're returning from Facebook OAuth */ async function handleFacebookOAuthCallback() { // Check if login just completed (prevent reload loop) if (sessionStorage.getItem('fb_login_complete') === 'true') { firebaseDebugLog(true, 'Facebook login already completed this session, skipping callback'); sessionStorage.removeItem('fb_login_complete'); return false; } firebaseDebugLog(true, 'Checking for Facebook OAuth callback...'); // Check if URL has Facebook OAuth response (access_token in hash) const hash = window.location.hash; if (!hash || hash.indexOf('access_token=') === -1) { firebaseDebugLog(true, 'No access_token in hash, not a Facebook OAuth callback'); return false; } // Prevent multiple executions if (localStorage.getItem('fb_oauth_processing') === 'true') { firebaseDebugLog(true, 'Already processing Facebook OAuth, skipping'); return true; // Return true to prevent other handlers } localStorage.setItem('fb_oauth_processing', 'true'); firebaseDebugLog(true, '=== FACEBOOK OAUTH CALLBACK DETECTED ==='); try { // Parse the hash fragment const params = new URLSearchParams(hash.substring(1)); const accessToken = params.get('access_token'); const state = params.get('state'); firebaseDebugLog(true, 'Parsed access_token length:', accessToken?.length); firebaseDebugLog(true, 'Parsed state:', state); // Verify state to prevent CSRF const savedState = localStorage.getItem('fb_oauth_state'); firebaseDebugLog(true, 'Saved state:', savedState); if (state !== savedState) { firebaseDebugLog(true, 'ERROR: State mismatch, possible CSRF attack'); localStorage.removeItem('fb_oauth_processing'); return false; } // Exchange Facebook access token for Firebase credential firebaseDebugLog(true, 'Creating Facebook credential from access token'); const credential = firebase.auth.FacebookAuthProvider.credential(accessToken); firebaseDebugLog(true, 'Signing into Firebase with Facebook credential'); const result = await firebase.auth().signInWithCredential(credential); firebaseDebugLog(true, 'Firebase signInWithCredential successful'); const user = result.user; firebaseDebugLog(true, 'User:', user.email, 'UID:', user.uid); // Get Firebase ID token const idToken = await user.getIdToken(); firebaseDebugLog(true, 'Got Firebase ID token, length:', idToken.length); // Login to WordPress firebaseDebugLog(true, 'Calling WordPress login'); const loginResponse = await login(user, idToken); if (!loginResponse || !loginResponse.success) { firebaseDebugLog(true, 'ERROR: WordPress login failed'); localStorage.removeItem('fb_oauth_processing'); throw new Error('Failed to authenticate with WordPress.'); } firebaseDebugLog(true, 'WordPress login successful!'); // Clean up localStorage.removeItem('fb_oauth_state'); localStorage.removeItem('fb_oauth_processing'); localStorage.removeItem('fb_oauth_redirect'); // Set flag to prevent re-processing on reload sessionStorage.setItem('fb_login_complete', 'true'); // Clean hash from URL and reload window.location.hash = ''; window.location.reload(); return true; } catch (error) { firebaseDebugLog(true, 'ERROR in Facebook OAuth callback:', error.code, error.message); localStorage.removeItem('fb_oauth_processing'); // Handle account-exists-with-different-credential error (same as standard flow) if (error.code === 'auth/account-exists-with-different-credential') { // Clean the hash from URL first window.location.hash = ''; jQuery('.temp-preferences').show(); jQuery('.temp-preferences .sfba-before-login').show(); jQuery(".socialLogin").hide(); var email = error.email; // Store credential in memory pendingCred = error.credential; try { var methods = await firebase.auth().fetchSignInMethodsForEmail(email); if (methods.length > 0) { localStorage.setItem('existingProvider', methods[0]); jQuery(".sfba-mask").removeClass("sfba-active"); jQuery(".sfba-link-mask").addClass('sfba-active'); handleLinkModel(methods[0]); } } catch (fetchError) { firebaseDebugLog(true, 'Error fetching sign-in methods: ' + fetchError.message); } } return false; } } }); function logout() { firebaseDebugLog(true, '---Start Logout'); logoutInProgress = true; if (localStorage.getItem('localLogout') === null || localStorage.getItem('localLogout') == 1) { logoutPopup(); } localStorage.removeItem('localLogout'); // Sign out from Firebase firebase.auth().signOut().then(function () { firebaseDebugLog(true, 'User signed out from Firebase.'); // Perform an AJAX request to log the user out from WordPress jQuery.ajax({ url: firebaseAuthAjax.ajax_url, type: 'POST', data: { action: 'firebase_logout' // nonce: firebaseAuthAjax.nonce }, success: function (response) { if (response.success) { localStorage.removeItem('loggedInLocally'); logoutInProgress = false; document.cookie = 'ssosession=; path=/; domain=' + cookieDomain + '; expires=Thu, 01 Jan 1970 00:00:00 UTC;'; window.location.reload(); // Reload the page after successful logout } else { firebaseDebugLog(true, 'Logout failed: ', response.data.message); } firebaseDebugLog(true, '---End Logout'); }, error: function (xhr, status, error) { firebaseDebugLog(true, 'Error logging out: ', xhr.responseText); } }); }).catch(function (error) { firebaseDebugLog(true, 'Firebase logout failed: ', error.message); }); } function loginPopup() { const popupOverlay = document.createElement('div'); popupOverlay.className = 'popup-overlay'; popupOverlay.innerHTML = ``; // Append overlay to the body document.body.appendChild(popupOverlay); // Display the popup popupOverlay.style.display = 'block'; } function logoutPopup() { const popupOverlay = document.createElement('div'); popupOverlay.className = 'popup-overlay'; popupOverlay.innerHTML = ``; // Append overlay to the body document.body.appendChild(popupOverlay); // Display the popup popupOverlay.style.display = 'block'; } function checkCookieExists() { const sessionCookie = getCookie('ssosession'); if (sessionCookie) { return sessionCookie; } return null; } function getCookie(name) { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop().split(';').shift(); } function startTokenRefresh(user) { firebaseDebugLog('refreshInterval-' + new Date().toLocaleString() + '---' + refreshInterval); // Clear any existing intervals clearInterval(refreshInterval); // Refresh the token every 50 minutes (3000 seconds) refreshInterval = setInterval(() => { regenerateIdToken(user); }, 50 * 60 * 1000); // 50 minutes in milliseconds } function regenerateIdToken(user) { user.getIdToken(true) .then((idToken) => { firebaseDebugLog('New ID Token:' + idToken); setCookie('ssosession', idToken, 24, cookieDomain); }) .catch((error) => { firebaseDebugLog('Error getting ID token:', error); }); } function setCookie(name, value, hours, domain) { const expires = new Date(Date.now() + hours * 60 * 60 * 1000).toUTCString(); const cookieValue = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/; domain=${domain}; secure=false; SameSite=Lax`; firebaseDebugLog('cookieValue' + cookieValue); document.cookie = cookieValue; } function getMainDomain(url) { const urlObject = new URL(url); const hostParts = urlObject.hostname.split('.'); // If the host has two or more parts, join the last two parts as the main domain if (hostParts.length >= 2) { const mainDomain = hostParts.slice(-2).join('.'); return mainDomain; } // Fallback for a single part (e.g., localhost) return urlObject.hostname; } function createDebugOverlay() { // Create overlay container debugLogContainer = document.createElement('div'); debugLogContainer.id = 'firebase-debug-overlay'; debugLogContainer.style.cssText = ` position: fixed; top: 0; left: 0; width: 300px; height: 70vh; max-height: 70vh; background: rgba(0, 0, 0, 0.9); color: #0f0; font-family: monospace; font-size: 11px; padding: 10px; overflow-y: auto; z-index: 999999; border-right: 2px solid #0f0; border-bottom: 2px solid #0f0; `; // Add title bar with download button const titleBar = document.createElement('div'); titleBar.style.cssText = 'display: flex; justify-content: space-between; align-items: center; margin-bottom: 5px;'; const title = document.createElement('div'); title.textContent = '🔥 Firebase Debug Log'; title.style.cssText = 'font-weight: bold; color: #ff0;'; const downloadBtn = document.createElement('button'); downloadBtn.textContent = '📥 Download'; downloadBtn.style.cssText = ` background: #0f0; color: #000; border: none; padding: 3px 8px; font-size: 10px; font-weight: bold; cursor: pointer; border-radius: 3px; `; downloadBtn.addEventListener('click', function (e) { e.stopPropagation(); downloadDebugLog(); }); titleBar.appendChild(title); titleBar.appendChild(downloadBtn); debugLogContainer.appendChild(titleBar); // Add close instruction const closeMsg = document.createElement('div'); closeMsg.textContent = '(Tap log area to close)'; closeMsg.style.cssText = 'font-size: 9px; color: #888; margin-bottom: 5px;'; debugLogContainer.appendChild(closeMsg); // Make it closable (but not the download button) debugLogContainer.addEventListener('click', function (e) { if (e.target !== downloadBtn) { debugLogContainer.style.display = 'none'; } }); document.body.appendChild(debugLogContainer); console.log('Debug overlay created'); } function firebaseDebugLog(stat = false, ...messages) { if (isDebugMode && stat) { console.log('Firebase:-', ...messages); // Also write to overlay if it exists if (debugLogContainer) { try { debugLogCounter++; const logEntry = document.createElement('div'); logEntry.style.cssText = 'margin: 2px 0; padding: 2px; border-bottom: 1px solid #333;'; const timestamp = new Date().toLocaleTimeString(); const messageText = messages.map(m => typeof m === 'object' ? JSON.stringify(m) : String(m) ).join(' '); logEntry.innerHTML = `[${debugLogCounter}] ${timestamp}
    ${messageText}`; debugLogContainer.appendChild(logEntry); // Auto-scroll to bottom debugLogContainer.scrollTop = debugLogContainer.scrollHeight; } catch (e) { console.error('Failed to write to debug log:', e); } } } } // Wrapper function for backward compatibility function debugLog(stat = false, ...messages) { firebaseDebugLog(stat, ...messages); } function downloadDebugLog() { if (!debugLogContainer) { console.error('Debug log container not found'); return; } // Collect all log entries const logEntries = debugLogContainer.querySelectorAll('div'); let logText = 'Firebase Authentication Debug Log\n'; logText += '=================================\n'; logText += 'Generated: ' + new Date().toLocaleString() + '\n'; logText += 'URL: ' + window.location.href + '\n'; logText += 'User Agent: ' + navigator.userAgent + '\n'; logText += '=================================\n\n'; // Extract text from each log entry logEntries.forEach((entry, index) => { // Skip the title and close message if (index > 1) { const text = entry.innerText || entry.textContent; if (text && text.trim()) { logText += text + '\n'; } } }); // Create blob and download const blob = new Blob([logText], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'firebase-debug-log-' + Date.now() + '.txt'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); console.log('Debug log downloaded'); } function isInAppBrowser() { const ua = navigator.userAgent || ""; return /FBAN|FBAV|Instagram|Line|Twitter|Snapchat|MicroMessenger/i.test(ua); } function isMobileDevice() { const ua = navigator.userAgent || ""; // Check for mobile devices (iPhone, iPad, Android, etc.) return /iPhone|iPad|iPod|Android|webOS|BlackBerry|IEMobile|Opera Mini/i.test(ua); } function getCurrentGeoData() { return { country: typeof COS_COUNTRY !== 'undefined' ? COS_COUNTRY : '', state: typeof COS_STATE !== 'undefined' ? COS_STATE : '', city: typeof COS_CITY !== 'undefined' ? COS_CITY : '', latitude: typeof COS_LATITUDE !== 'undefined' ? COS_LATITUDE : '', longitude: typeof COS_LONGITUDE !== 'undefined' ? COS_LONGITUDE : '', }; } function hasGeoChanged(currentGeo, lastSyncedGeo) { return ( currentGeo.country !== (lastSyncedGeo.country || '') || currentGeo.state !== (lastSyncedGeo.state || '') || currentGeo.city !== (lastSyncedGeo.city || '') || String(currentGeo.latitude) !== String(lastSyncedGeo.latitude || '') || String(currentGeo.longitude) !== String(lastSyncedGeo.longitude || '') ); } async function syncGeoToLambda(userEmail) { if (!userEmail) return; const currentGeo = getCurrentGeoData(); const lastSyncedGeo = JSON.parse(localStorage.getItem('COS_GEO_DATA') || '{}'); if (currentGeo && !hasGeoChanged(currentGeo, lastSyncedGeo)) { return; } try { const response = await fetch('/wp-admin/admin-ajax.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ action: 'save_geo_to_dynamodb', geo: JSON.stringify(currentGeo), userEmail: userEmail }) }); localStorage.setItem('COS_GEO_DATA', JSON.stringify(currentGeo)); const result = await response.json(); // console.log('Geo synced:', result); } catch (err) { console.error('Geo sync failed:', err); } } ; /*! This file is auto-generated */ (()=>{"use strict";var t={d:(e,n)=>{for(var r in n)t.o(n,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:n[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{actions:()=>P,addAction:()=>A,addFilter:()=>m,applyFilters:()=>w,applyFiltersAsync:()=>I,createHooks:()=>h,currentAction:()=>x,currentFilter:()=>T,defaultHooks:()=>f,didAction:()=>j,didFilter:()=>z,doAction:()=>g,doActionAsync:()=>k,doingAction:()=>O,doingFilter:()=>S,filters:()=>Z,hasAction:()=>_,hasFilter:()=>v,removeAction:()=>p,removeAllActions:()=>F,removeAllFilters:()=>b,removeFilter:()=>y});const n=function(t){return"string"!=typeof t||""===t?(console.error("The namespace must be a non-empty string."),!1):!!/^[a-zA-Z][a-zA-Z0-9_.\-\/]*$/.test(t)||(console.error("The namespace can only contain numbers, letters, dashes, periods, underscores and slashes."),!1)};const r=function(t){return"string"!=typeof t||""===t?(console.error("The hook name must be a non-empty string."),!1):/^__/.test(t)?(console.error("The hook name cannot begin with `__`."),!1):!!/^[a-zA-Z][a-zA-Z0-9_.-]*$/.test(t)||(console.error("The hook name can only contain numbers, letters, dashes, periods and underscores."),!1)};const o=function(t,e){return function(o,i,s,c=10){const l=t[e];if(!r(o))return;if(!n(i))return;if("function"!=typeof s)return void console.error("The hook callback must be a function.");if("number"!=typeof c)return void console.error("If specified, the hook priority must be a number.");const a={callback:s,priority:c,namespace:i};if(l[o]){const t=l[o].handlers;let e;for(e=t.length;e>0&&!(c>=t[e-1].priority);e--);e===t.length?t[e]=a:t.splice(e,0,a),l.__current.forEach((t=>{t.name===o&&t.currentIndex>=e&&t.currentIndex++}))}else l[o]={handlers:[a],runs:0};"hookAdded"!==o&&t.doAction("hookAdded",o,i,s,c)}};const i=function(t,e,o=!1){return function(i,s){const c=t[e];if(!r(i))return;if(!o&&!n(s))return;if(!c[i])return 0;let l=0;if(o)l=c[i].handlers.length,c[i]={runs:c[i].runs,handlers:[]};else{const t=c[i].handlers;for(let e=t.length-1;e>=0;e--)t[e].namespace===s&&(t.splice(e,1),l++,c.__current.forEach((t=>{t.name===i&&t.currentIndex>=e&&t.currentIndex--})))}return"hookRemoved"!==i&&t.doAction("hookRemoved",i,s),l}};const s=function(t,e){return function(n,r){const o=t[e];return void 0!==r?n in o&&o[n].handlers.some((t=>t.namespace===r)):n in o}};const c=function(t,e,n,r){return function(o,...i){const s=t[e];s[o]||(s[o]={handlers:[],runs:0}),s[o].runs++;const c=s[o].handlers;if(!c||!c.length)return n?i[0]:void 0;const l={name:o,currentIndex:0};return(r?async function(){try{s.__current.add(l);let t=n?i[0]:void 0;for(;l.currentIndex0:Array.from(r.__current).some((t=>t.name===n))}};const u=function(t,e){return function(n){const o=t[e];if(r(n))return o[n]&&o[n].runs?o[n].runs:0}};class d{constructor(){this.actions=Object.create(null),this.actions.__current=new Set,this.filters=Object.create(null),this.filters.__current=new Set,this.addAction=o(this,"actions"),this.addFilter=o(this,"filters"),this.removeAction=i(this,"actions"),this.removeFilter=i(this,"filters"),this.hasAction=s(this,"actions"),this.hasFilter=s(this,"filters"),this.removeAllActions=i(this,"actions",!0),this.removeAllFilters=i(this,"filters",!0),this.doAction=c(this,"actions",!1,!1),this.doActionAsync=c(this,"actions",!1,!0),this.applyFilters=c(this,"filters",!0,!1),this.applyFiltersAsync=c(this,"filters",!0,!0),this.currentAction=l(this,"actions"),this.currentFilter=l(this,"filters"),this.doingAction=a(this,"actions"),this.doingFilter=a(this,"filters"),this.didAction=u(this,"actions"),this.didFilter=u(this,"filters")}}const h=function(){return new d},f=h(),{addAction:A,addFilter:m,removeAction:p,removeFilter:y,hasAction:_,hasFilter:v,removeAllActions:F,removeAllFilters:b,doAction:g,doActionAsync:k,applyFilters:w,applyFiltersAsync:I,currentAction:x,currentFilter:T,doingAction:O,doingFilter:S,didAction:j,didFilter:z,actions:P,filters:Z}=f;(window.wp=window.wp||{}).hooks=e})();;