Update signing.html
Browse files- signing.html +145 -67
signing.html
CHANGED
|
@@ -54,11 +54,17 @@
|
|
| 54 |
color: #d32f2f;
|
| 55 |
margin-top: 1rem;
|
| 56 |
font-size: 0.9rem;
|
|
|
|
| 57 |
}
|
| 58 |
.loading {
|
| 59 |
margin-top: 1rem;
|
| 60 |
opacity: 0.7;
|
| 61 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
</style>
|
| 63 |
</head>
|
| 64 |
<body>
|
|
@@ -68,34 +74,40 @@
|
|
| 68 |
<button id="authButton" onclick="handleAuth()">Sign in with Google</button>
|
| 69 |
<p class="loading" id="loading" style="display: none;">Processing...</p>
|
| 70 |
<p class="error" id="error"></p>
|
|
|
|
| 71 |
</div>
|
| 72 |
-
|
| 73 |
-
<!--
|
| 74 |
<script type="module">
|
| 75 |
import { initializeApp } from 'https://www.gstatic.com/firebasejs/10.7.1/firebase-app.js';
|
| 76 |
-
import {
|
| 77 |
-
|
| 78 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
|
| 80 |
-
// Firebase
|
| 81 |
const firebaseConfig = {
|
| 82 |
apiKey: "AIzaSyAJZ5UwyLo4b4L8_G7Nocw0nj7dhyBZ_yU",
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
};
|
| 91 |
|
| 92 |
-
//
|
| 93 |
const app = initializeApp(firebaseConfig);
|
| 94 |
const auth = getAuth(app);
|
| 95 |
const provider = new GoogleAuthProvider();
|
| 96 |
|
| 97 |
-
|
| 98 |
-
|
|
|
|
| 99 |
// UI elements
|
| 100 |
const titleEl = document.getElementById('title');
|
| 101 |
const messageEl = document.getElementById('message');
|
|
@@ -103,94 +115,160 @@
|
|
| 103 |
const loadingEl = document.getElementById('loading');
|
| 104 |
const errorEl = document.getElementById('error');
|
| 105 |
|
| 106 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
onAuthStateChanged(auth, (user) => {
|
| 108 |
if (user) {
|
|
|
|
| 109 |
showSuccess(user);
|
| 110 |
}
|
| 111 |
});
|
| 112 |
|
| 113 |
-
//
|
| 114 |
window.handleAuth = async function() {
|
| 115 |
-
try
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
const result = signInWithRedirect(auth, provider); // await signInWithPopup(auth, provider);
|
| 121 |
-
const user = result.user;
|
| 122 |
-
const credential = GoogleAuthProvider.credentialFromResult(result);
|
| 123 |
-
const token = await user.getIdToken();
|
| 124 |
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
}
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
}
|
| 148 |
};
|
| 149 |
|
| 150 |
-
|
| 151 |
-
const myButton = document.getElementById('authButton');
|
| 152 |
-
|
| 153 |
-
myButton.addEventListener('click', function() {
|
| 154 |
-
alert('Hello from the button!');
|
| 155 |
-
});
|
| 156 |
-
|
| 157 |
-
*/
|
| 158 |
-
|
| 159 |
function showSuccess(user) {
|
| 160 |
titleEl.textContent = 'Sign-in Complete';
|
| 161 |
messageEl.innerHTML = `Welcome, <strong>${user.displayName || user.email}</strong>! Redirecting to app...`;
|
| 162 |
buttonEl.textContent = 'Open App';
|
| 163 |
-
buttonEl.onclick = () =>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
buttonEl.disabled = false;
|
| 165 |
loadingEl.style.display = 'none';
|
| 166 |
}
|
| 167 |
|
| 168 |
async function redirectToApp(token, user) {
|
| 169 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 170 |
if (!token) {
|
| 171 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 172 |
}
|
| 173 |
|
| 174 |
-
// Prepare user data
|
| 175 |
const userData = {
|
| 176 |
uid: user.uid,
|
| 177 |
email: user.email,
|
| 178 |
displayName: user.displayName,
|
| 179 |
photoURL: user.photoURL,
|
| 180 |
-
token
|
| 181 |
};
|
| 182 |
|
| 183 |
-
// Encode data for URL
|
| 184 |
const encodedData = encodeURIComponent(JSON.stringify(userData));
|
| 185 |
-
|
| 186 |
-
// Try to open the app with deep link
|
| 187 |
window.location.href = `${appScheme}://auth?data=${encodedData}`;
|
| 188 |
-
|
| 189 |
-
// Fallback:
|
| 190 |
setTimeout(() => {
|
| 191 |
messageEl.innerHTML = 'If the app didn\'t open automatically, please open it manually.';
|
| 192 |
}, 2000);
|
| 193 |
}
|
|
|
|
|
|
|
| 194 |
</script>
|
| 195 |
</body>
|
| 196 |
</html>
|
|
|
|
| 54 |
color: #d32f2f;
|
| 55 |
margin-top: 1rem;
|
| 56 |
font-size: 0.9rem;
|
| 57 |
+
word-break: break-word;
|
| 58 |
}
|
| 59 |
.loading {
|
| 60 |
margin-top: 1rem;
|
| 61 |
opacity: 0.7;
|
| 62 |
}
|
| 63 |
+
.note {
|
| 64 |
+
margin-top: 12px;
|
| 65 |
+
font-size: 0.85rem;
|
| 66 |
+
opacity: 0.85;
|
| 67 |
+
}
|
| 68 |
</style>
|
| 69 |
</head>
|
| 70 |
<body>
|
|
|
|
| 74 |
<button id="authButton" onclick="handleAuth()">Sign in with Google</button>
|
| 75 |
<p class="loading" id="loading" style="display: none;">Processing...</p>
|
| 76 |
<p class="error" id="error"></p>
|
| 77 |
+
<p class="note" id="note">Tip: Serve this page over http(s). Add your test domain to Firebase Auth → Authorized domains.</p>
|
| 78 |
</div>
|
| 79 |
+
|
| 80 |
+
<!-- Full script: handles popup (desktop) and redirect (mobile/webview) flows -->
|
| 81 |
<script type="module">
|
| 82 |
import { initializeApp } from 'https://www.gstatic.com/firebasejs/10.7.1/firebase-app.js';
|
| 83 |
+
import {
|
| 84 |
+
getAuth,
|
| 85 |
+
signInWithPopup,
|
| 86 |
+
signInWithRedirect,
|
| 87 |
+
getRedirectResult,
|
| 88 |
+
GoogleAuthProvider,
|
| 89 |
+
onAuthStateChanged
|
| 90 |
+
} from 'https://www.gstatic.com/firebasejs/10.7.1/firebase-auth.js';
|
| 91 |
|
| 92 |
+
// ---------- Firebase config (keep or replace with your own) ----------
|
| 93 |
const firebaseConfig = {
|
| 94 |
apiKey: "AIzaSyAJZ5UwyLo4b4L8_G7Nocw0nj7dhyBZ_yU",
|
| 95 |
+
authDomain: "cartpost-db-06.firebaseapp.com",
|
| 96 |
+
projectId: "cartpost-db-06",
|
| 97 |
+
storageBucket: "cartpost-db-06.firebasestorage.app",
|
| 98 |
+
messagingSenderId: "212802992706",
|
| 99 |
+
appId: "1:212802992706:web:2a32a453c42cbc3bdfcbdb",
|
| 100 |
+
measurementId: "G-JYWF6B9MVZ"
|
|
|
|
| 101 |
};
|
| 102 |
|
| 103 |
+
// ---------- Init ----------
|
| 104 |
const app = initializeApp(firebaseConfig);
|
| 105 |
const auth = getAuth(app);
|
| 106 |
const provider = new GoogleAuthProvider();
|
| 107 |
|
| 108 |
+
// Your app deep-link scheme (used when redirecting to native app)
|
| 109 |
+
const appScheme = "everydaydresscode";
|
| 110 |
+
|
| 111 |
// UI elements
|
| 112 |
const titleEl = document.getElementById('title');
|
| 113 |
const messageEl = document.getElementById('message');
|
|
|
|
| 115 |
const loadingEl = document.getElementById('loading');
|
| 116 |
const errorEl = document.getElementById('error');
|
| 117 |
|
| 118 |
+
// ---------- Helpers ----------
|
| 119 |
+
function isLikelyWebViewOrInApp() {
|
| 120 |
+
const ua = navigator.userAgent || '';
|
| 121 |
+
// common markers for in-app browsers / webviews
|
| 122 |
+
const webviewMarkers = /wv|WebView|FBAN|FBAV|Instagram|KAKAOTALK|Line|MicroMessenger/i;
|
| 123 |
+
// On Android, some webviews don't include "Chrome" in UA
|
| 124 |
+
return webviewMarkers.test(ua) || (/Android/i.test(ua) && !/Chrome/i.test(ua));
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
function resetUI() {
|
| 128 |
+
buttonEl.disabled = false;
|
| 129 |
+
loadingEl.style.display = 'none';
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
function safeSetError(msg) {
|
| 133 |
+
// ensure we never put an object directly into DOM
|
| 134 |
+
errorEl.textContent = String(msg || 'Authentication failed.');
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
// ---------- Handle redirect result (page load after signInWithRedirect) ----------
|
| 138 |
+
getRedirectResult(auth)
|
| 139 |
+
.then(async (result) => {
|
| 140 |
+
if (result && result.user) {
|
| 141 |
+
// Successful redirect result
|
| 142 |
+
const user = result.user;
|
| 143 |
+
try {
|
| 144 |
+
const token = await user.getIdToken();
|
| 145 |
+
showSuccess(user);
|
| 146 |
+
// small delay to let user see success message
|
| 147 |
+
setTimeout(() => redirectToApp(token, user), 1000);
|
| 148 |
+
} catch (tokenErr) {
|
| 149 |
+
console.error('Token error after redirect:', tokenErr);
|
| 150 |
+
safeSetError('Signed in but failed to retrieve token. See console for details.');
|
| 151 |
+
}
|
| 152 |
+
}
|
| 153 |
+
})
|
| 154 |
+
.catch((err) => {
|
| 155 |
+
console.error('getRedirectResult error:', err.code, err.message);
|
| 156 |
+
// Friendly message but keep details in console
|
| 157 |
+
safeSetError('Authentication after redirect failed. See console for details.');
|
| 158 |
+
resetUI();
|
| 159 |
+
});
|
| 160 |
+
|
| 161 |
+
// ---------- Persisted state detection ----------
|
| 162 |
onAuthStateChanged(auth, (user) => {
|
| 163 |
if (user) {
|
| 164 |
+
// Already signed-in (session persisted)
|
| 165 |
showSuccess(user);
|
| 166 |
}
|
| 167 |
});
|
| 168 |
|
| 169 |
+
// ---------- Main auth handler (called on button click) ----------
|
| 170 |
window.handleAuth = async function() {
|
| 171 |
+
// disable UI while we try
|
| 172 |
+
buttonEl.disabled = true;
|
| 173 |
+
loadingEl.style.display = 'block';
|
| 174 |
+
errorEl.textContent = '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 175 |
|
| 176 |
+
try {
|
| 177 |
+
if (isLikelyWebViewOrInApp()) {
|
| 178 |
+
// Use redirect flow in environments where popup is unreliable
|
| 179 |
+
console.log('Detected webview/in-app: using signInWithRedirect.');
|
| 180 |
+
// signInWithRedirect will redirect the browser away; getRedirectResult will handle the result on return.
|
| 181 |
+
await signInWithRedirect(auth, provider);
|
| 182 |
+
// After this line the browser navigates away; no further code executes in most cases.
|
| 183 |
+
} else {
|
| 184 |
+
// Desktop / normal browsers: popup flow
|
| 185 |
+
console.log('Using signInWithPopup for desktop browser.');
|
| 186 |
+
const result = await signInWithPopup(auth, provider);
|
| 187 |
+
if (result && result.user) {
|
| 188 |
+
const user = result.user;
|
| 189 |
+
const token = await user.getIdToken();
|
| 190 |
+
showSuccess(user);
|
| 191 |
+
// Wait briefly so user sees success then redirect to app.
|
| 192 |
+
setTimeout(() => redirectToApp(token, user), 800);
|
| 193 |
+
} else {
|
| 194 |
+
// Defensive fallback, shouldn't normally happen
|
| 195 |
+
console.warn('signInWithPopup returned no user:', result);
|
| 196 |
+
safeSetError('Sign-in did not complete. Check console for details.');
|
| 197 |
+
resetUI();
|
| 198 |
+
}
|
| 199 |
}
|
| 200 |
+
} catch (err) {
|
| 201 |
+
// Common Firebase errors: log full details and show human message
|
| 202 |
+
console.error('Auth error:', err.code, err.message, err);
|
| 203 |
+
let msg = 'Authentication failed. See console for details.';
|
| 204 |
+
if (err && err.code === 'auth/popup-closed-by-user') msg = 'Sign-in cancelled. Please try again.';
|
| 205 |
+
else if (err && err.code === 'auth/popup-blocked') msg = 'Pop-up blocked. Allow pop-ups and try again.';
|
| 206 |
+
else if (err && err.code === 'auth/cancelled-popup-request') msg = 'Popup request cancelled (race). Try again.';
|
| 207 |
+
else if (err && err.code === 'auth/unauthorized-domain') msg = 'Unauthorized domain — add this domain in Firebase Console (Auth → Authorized domains).';
|
| 208 |
+
safeSetError(msg);
|
| 209 |
+
resetUI();
|
| 210 |
}
|
| 211 |
};
|
| 212 |
|
| 213 |
+
// ---------- UI helpers ----------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 214 |
function showSuccess(user) {
|
| 215 |
titleEl.textContent = 'Sign-in Complete';
|
| 216 |
messageEl.innerHTML = `Welcome, <strong>${user.displayName || user.email}</strong>! Redirecting to app...`;
|
| 217 |
buttonEl.textContent = 'Open App';
|
| 218 |
+
buttonEl.onclick = async () => {
|
| 219 |
+
// ensure currentUser exists and get a token before redirecting
|
| 220 |
+
const current = auth.currentUser;
|
| 221 |
+
if (!current) {
|
| 222 |
+
safeSetError('No signed-in user available. Reload and try again.');
|
| 223 |
+
return;
|
| 224 |
+
}
|
| 225 |
+
try {
|
| 226 |
+
const token = await current.getIdToken();
|
| 227 |
+
redirectToApp(token, current);
|
| 228 |
+
} catch (e) {
|
| 229 |
+
console.error('Failed to get token on manual Open App:', e);
|
| 230 |
+
safeSetError('Failed to get token. See console.');
|
| 231 |
+
}
|
| 232 |
+
};
|
| 233 |
buttonEl.disabled = false;
|
| 234 |
loadingEl.style.display = 'none';
|
| 235 |
}
|
| 236 |
|
| 237 |
async function redirectToApp(token, user) {
|
| 238 |
+
if (!user) {
|
| 239 |
+
safeSetError('No signed-in user available to redirect.');
|
| 240 |
+
return;
|
| 241 |
+
}
|
| 242 |
+
// If token not provided, fetch it
|
| 243 |
if (!token) {
|
| 244 |
+
try {
|
| 245 |
+
token = await user.getIdToken();
|
| 246 |
+
} catch (e) {
|
| 247 |
+
console.error('Failed to fetch token before redirect:', e);
|
| 248 |
+
safeSetError('Failed to fetch token. See console.');
|
| 249 |
+
return;
|
| 250 |
+
}
|
| 251 |
}
|
| 252 |
|
|
|
|
| 253 |
const userData = {
|
| 254 |
uid: user.uid,
|
| 255 |
email: user.email,
|
| 256 |
displayName: user.displayName,
|
| 257 |
photoURL: user.photoURL,
|
| 258 |
+
token
|
| 259 |
};
|
| 260 |
|
|
|
|
| 261 |
const encodedData = encodeURIComponent(JSON.stringify(userData));
|
| 262 |
+
// Attempt to open native app via deep link
|
|
|
|
| 263 |
window.location.href = `${appScheme}://auth?data=${encodedData}`;
|
| 264 |
+
|
| 265 |
+
// Fallback: after 2s, give user manual instructions
|
| 266 |
setTimeout(() => {
|
| 267 |
messageEl.innerHTML = 'If the app didn\'t open automatically, please open it manually.';
|
| 268 |
}, 2000);
|
| 269 |
}
|
| 270 |
+
|
| 271 |
+
// ---------- End of script ----------
|
| 272 |
</script>
|
| 273 |
</body>
|
| 274 |
</html>
|