Skip to content

Commit d94091a

Browse files
committed
Add webviewGoogleSignin
1 parent 8bf3c4f commit d94091a

File tree

2 files changed

+85
-14
lines changed

2 files changed

+85
-14
lines changed

web/lib/firebase/users.ts

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,58 @@ export function writeReferralInfo(
4343
}
4444
}
4545

46-
// export function isAndroidWebView() {
47-
// try {
48-
// // Detect if Android bridge exists
49-
// return typeof (window as any).AndroidBridge?.isNativeApp === 'function';
50-
// } catch {
51-
// return false;
52-
// }
53-
// }
46+
export function isAndroidWebView() {
47+
try {
48+
// Detect if Android bridge exists
49+
return typeof (window as any).AndroidBridge?.isNativeApp === 'function';
50+
} catch {
51+
return false;
52+
}
53+
}
5454

55+
async function generatePKCE() {
56+
const array = new Uint8Array(32);
57+
crypto.getRandomValues(array);
58+
const codeVerifier = btoa(String.fromCharCode(...array))
59+
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
60+
61+
const encoder = new TextEncoder();
62+
const hashBuffer = await crypto.subtle.digest('SHA-256', encoder.encode(codeVerifier));
63+
const hashArray = Array.from(new Uint8Array(hashBuffer));
64+
const codeChallenge = btoa(String.fromCharCode(...hashArray))
65+
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
66+
67+
console.log({codeVerifier, codeChallenge})
68+
return {codeVerifier, codeChallenge};
69+
}
70+
71+
export const GOOGLE_CLIENT_ID = '253367029065-khkj31qt22l0vc3v754h09vhpg6t33ad.apps.googleusercontent.com'
72+
73+
/**
74+
* Authenticates a Firebase client running a webview APK on Android with Google OAuth.
75+
*
76+
* `https://accounts.google.com/o/oauth2/v2/auth?${params}` to get the code (in external browser, as google blocks it in webview)
77+
* Redirects to `com.compassmeet:/auth` (in webview java main activity)
78+
* 'https://oauth2.googleapis.com/token' to get the ID token (in javascript app)
79+
* signInWithCredential(auth, credential) to set up firebase user in client (auth.currentUser)
80+
*
81+
* @public
82+
*/
83+
export async function webviewGoogleSignin() {
84+
const {codeVerifier, codeChallenge} = await generatePKCE();
85+
localStorage.setItem('pkce_verifier', codeVerifier);
86+
87+
const params = new URLSearchParams({
88+
client_id: GOOGLE_CLIENT_ID,
89+
redirect_uri: 'com.compassmeet:/auth', // your deep link
90+
response_type: 'code',
91+
scope: 'openid email profile',
92+
code_challenge: codeChallenge,
93+
code_challenge_method: 'S256',
94+
});
95+
96+
window.open(`https://accounts.google.com/o/oauth2/v2/auth?${params}`, '_system');
97+
}
5598

5699
// export async function googleNativeLogin() {
57100
// console.log('Platform:', Capacitor.getPlatform())
@@ -94,12 +137,11 @@ export function writeReferralInfo(
94137
// export const isRunningInAPK = () => typeof window !== 'undefined' && (window as any).IS_APK === true
95138

96139
export async function firebaseLogin() {
97-
// if (isAndroidWebView()) {
98-
// console.log('Running in APK')
99-
// return await googleNativeLogin()
100-
// return await signInWithRedirect(auth, new GoogleAuthProvider())
101-
// }
102-
// console.log('Running in web')
140+
if (isAndroidWebView()) {
141+
console.log('Running in APK')
142+
return await webviewGoogleSignin()
143+
}
144+
console.log('Running in web')
103145
const provider = new GoogleAuthProvider()
104146
return signInWithPopup(auth, provider).then(async (result) => {
105147
return result

web/pages/_app.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import clsx from 'clsx'
1212
import {initTracking} from 'web/lib/service/analytics'
1313
import WebPush from "web/lib/service/web-push";
1414
import AndroidPush from "web/lib/service/android-push";
15+
import {GOOGLE_CLIENT_ID} from "web/lib/firebase/users";
1516

1617
// See https://nextjs.org/docs/basic-features/font-optimization#google-fonts
1718
// and if you add a font, you must add it to tailwind config as well for it to work.
@@ -63,6 +64,34 @@ function MyApp({Component, pageProps}: AppProps<PageProps>) {
6364
}
6465
}, [])
6566

67+
window.addEventListener('oauthRedirect', async (event: any) => {
68+
console.log('Received oauthRedirect event:', event.detail);
69+
const url = new URL(event.detail);
70+
71+
const code = url.searchParams.get('code');
72+
if (!code) {
73+
console.error('No code found in URL');
74+
return;
75+
}
76+
77+
const codeVerifier = localStorage.getItem('pkce_verifier');
78+
79+
const tokenResponse = await fetch('https://oauth2.googleapis.com/token', {
80+
method: 'POST',
81+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
82+
body: new URLSearchParams({
83+
client_id: GOOGLE_CLIENT_ID,
84+
code,
85+
code_verifier: codeVerifier!,
86+
redirect_uri: 'com.compassmeet:/auth',
87+
grant_type: 'authorization_code',
88+
}),
89+
});
90+
91+
const tokens = await tokenResponse.json();
92+
console.log('Tokens:', tokens);
93+
});
94+
6695
const title = 'Compass'
6796
const description = 'The platform for intentional connections'
6897

0 commit comments

Comments
 (0)