Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Client/src/screens/profile/AuthScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ const AuthScreen: React.FC<AuthScreenProps> = ({ navigation }) => {
setErrors({});

try {
const { idToken: authCode } = await googleAuthService.signIn();
const authData = await authService.googleLogin(authCode);
const { idToken } = await googleAuthService.signIn();
const authData = await authService.googleLogin(idToken);

await authStorage.setToken(authData.token);
await authStorage.setUserId(authData.user.id.toString());
Expand Down
4 changes: 2 additions & 2 deletions Client/src/services/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ class AuthService {
});
}

async googleLogin(authCode: string): Promise<AuthData> {
async googleLogin(idToken: string): Promise<AuthData> {
return this.makeRequest<AuthData>('/auth/google', {
method: 'POST',
body: JSON.stringify({ code: authCode }),
body: JSON.stringify({ idToken }),
});
}
}
Expand Down
26 changes: 14 additions & 12 deletions Client/src/services/googleAuth.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import * as AuthSession from 'expo-auth-session';
import * as WebBrowser from 'expo-web-browser';
import { Platform } from 'react-native';

WebBrowser.maybeCompleteAuthSession();

const GOOGLE_WEB_CLIENT_ID = process.env.EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID;
const GOOGLE_ANDROID_CLIENT_ID = process.env.EXPO_PUBLIC_GOOGLE_ANDROID_CLIENT_ID;

// Use your server as the redirect URI
const API_URL = process.env.EXPO_PUBLIC_API_DOMAIN_URL || 'https://server.splitlyr.clestiq.com';
const redirectUri = `${API_URL}/v1/auth/google/callback`;
// Use Expo's auth proxy for mobile apps
const redirectUri = AuthSession.makeRedirectUri({
scheme: 'splitlyr',
});

// Log the redirect URI for debugging (remove in production)
if (__DEV__) {
Expand All @@ -22,7 +25,7 @@ export interface GoogleAuthResponse {
export const googleAuthService = {
async signIn(): Promise<GoogleAuthResponse> {
try {
const clientId = GOOGLE_WEB_CLIENT_ID;
const clientId = Platform.OS === 'android' ? GOOGLE_ANDROID_CLIENT_ID : GOOGLE_WEB_CLIENT_ID;

const discovery = {
authorizationEndpoint: 'https://accounts.google.com/o/oauth2/v2/auth',
Expand All @@ -33,23 +36,22 @@ export const googleAuthService = {
clientId: clientId!,
redirectUri,
scopes: ['openid', 'profile', 'email'],
responseType: AuthSession.ResponseType.Code,
usePKCE: true,
responseType: AuthSession.ResponseType.Token,
usePKCE: false,
});

const result = await request.promptAsync(discovery);

if (result.type === 'success') {
const { code } = result.params;
const { id_token, access_token } = result.params;

if (!code) {
throw new Error('No authorization code received from Google');
if (!id_token) {
throw new Error('No ID token received from Google');
}

// Exchange code for tokens on the server
return {
idToken: code,
accessToken: code,
idToken: id_token,
accessToken: access_token,
};
} else if (result.type === 'error') {
throw new Error(result.error?.message || 'Google sign-in failed');
Expand Down
56 changes: 56 additions & 0 deletions GOOGLE_OAUTH_SETUP.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
Google OAuth Setup Instructions (Client-Side Flow)
===================================================

The Google OAuth login uses client-side ID token flow (simpler and works with mobile apps).

1. Google Cloud Console Configuration:
- Go to https://console.cloud.google.com/
- Select your project
- Enable Google+ API
- Go to Credentials > OAuth 2.0 Client IDs

2. Configure OAuth Consent Screen:
- Add app name: Splitlyr
- Add support email
- Add authorized domains if needed

3. Add Authorized Redirect URI:

For WEB CLIENT:
1. Run your app first: cd Client && npm start
2. Check the console for the logged redirect URI
3. It will look like: https://auth.expo.io/@vasubhut157/splitlyr
4. Go to Google Cloud Console > Credentials
5. Click on your Web Client ID: 379416821819-gseoc5r2lq5ioavdt2mg6ffbeoi1gqeg.apps.googleusercontent.com
6. Scroll to "Authorized redirect URIs"
7. Click "+ ADD URI"
8. Add the URI from step 3
9. Click "SAVE"

For ANDROID CLIENT (if using Android):
- No redirect URI needed
- Add package name: com.clestiq.splitlyr.app
- Add SHA-1 certificate fingerprint:
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android

4. Testing:
- Run the app: cd Client && npm start
- Tap "Continue with Google"
- Should work! 🎉

IMPORTANT NOTES:
================
1. This uses client-side ID token flow (simpler for mobile apps)
2. The ID token is verified on your backend using google-auth-library
3. No client secret needed for this flow
4. Works with Expo Go and standalone builds

Current Configuration:
- Web Client ID: 379416821819-gseoc5r2lq5ioavdt2mg6ffbeoi1gqeg.apps.googleusercontent.com
- Android Client ID: 379416821819-69q39vsrvfuf26031a3llv2qkikfrd18.apps.googleusercontent.com
- Redirect URI: Logged in console when app runs (add to Web Client)

If you see errors:
- "redirect_uri_mismatch": The URI in Google Console doesn't match the logged URI
- "invalid_token": Token verification failed on backend
- Check that both client IDs are correct in .env files
42 changes: 12 additions & 30 deletions services/controllers/authController.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,43 +136,25 @@ const login = async (req, res) => {

const googleLogin = async (req, res) => {
try {
const { code, idToken } = req.body;
const { idToken } = req.body;

if (!code && !idToken) {
if (!idToken) {
return res.status(400).json({
success: false,
message: 'Authorization code or ID token is required'
message: 'ID token is required'
});
}

let payload;

if (code) {
// Exchange authorization code for tokens
const { tokens } = await googleClient.getToken({
code,
redirect_uri: `${process.env.API_BASE_URL || 'https://server.splitlyr.clestiq.com'}/v1/auth/google/callback`
});

const ticket = await googleClient.verifyIdToken({
idToken: tokens.id_token,
audience: process.env.GOOGLE_CLIENT_ID
});

payload = ticket.getPayload();
} else {
// Direct ID token verification (for Android)
const ticket = await googleClient.verifyIdToken({
idToken,
audience: [
process.env.GOOGLE_CLIENT_ID,
process.env.GOOGLE_ANDROID_CLIENT_ID
].filter(Boolean)
});

payload = ticket.getPayload();
}
// Verify ID token
const ticket = await googleClient.verifyIdToken({
idToken,
audience: [
process.env.GOOGLE_CLIENT_ID,
process.env.GOOGLE_ANDROID_CLIENT_ID
].filter(Boolean)
});

const payload = ticket.getPayload();
const { email, name, picture, sub: googleId } = payload;

if (!email) {
Expand Down
3 changes: 0 additions & 3 deletions services/routes/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,5 @@ const { signup, login, googleLogin } = require('../controllers/authController');
router.post('/register', signup);
router.post('/login', login);
router.post('/google', googleLogin);
router.get('/google/callback', (req, res) => {
res.send('<html><body><h1>Authentication successful!</h1><p>You can close this window and return to the app.</p></body></html>');
});

module.exports = router;
9 changes: 9 additions & 0 deletions terraform/load_balancer.tf
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@ resource "google_compute_region_instance_group_manager" "coinbreakr_group" {
health_check = google_compute_health_check.coinbreakr_health_check.id
initial_delay_sec = 300
}

update_policy {
type = "PROACTIVE"
minimal_action = "REPLACE"
max_surge_fixed = 3
max_unavailable_fixed = 0
replacement_method = "SUBSTITUTE"
instance_redistribution_type = "PROACTIVE"
}
}

# Auto Scaler
Expand Down
Loading