From 1b46739a0d665813d746ab6a3d32c2df126229c7 Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Thu, 18 Aug 2022 18:42:18 -0700 Subject: [PATCH] add sign in option for android client on server --- .../app/omnivore/omnivore/LoginViewModel.kt | 31 +++++++++++++++++++ .../app/omnivore/omnivore/RESTNetworker.kt | 17 ++++++++++ packages/api/.env.example | 1 + packages/api/.env.test | 1 + packages/api/src/routers/auth/google_auth.ts | 12 +++++-- .../routers/auth/mobile/mobile_auth_router.ts | 5 +-- .../api/src/routers/auth/mobile/sign_in.ts | 3 +- packages/api/src/util.ts | 3 ++ 8 files changed, 67 insertions(+), 6 deletions(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/LoginViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/LoginViewModel.kt index 653f7e2ab..d5f788438 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/LoginViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/LoginViewModel.kt @@ -76,5 +76,36 @@ class LoginViewModel @Inject constructor( Log.d(ContentValues.TAG, "Google Result?: $googleIdToken") // TODO: submit id token to backend // If token is missing then set the error message + + if (googleIdToken == null) { + return + } + + val login = RetrofitHelper.getInstance().create(AuthProviderLoginSubmit::class.java) + + viewModelScope.launch { + isLoading = true + errorMessage = null + + val result = login.submitAuthProviderLogin( + SignInParams(token = googleIdToken, provider = "GOOGLE") + ) + + isLoading = false + + if (result.body()?.authToken != null) { + datastoreRepo.putString(DatastoreKeys.omnivoreAuthToken, result.body()?.authToken!!) + } else { + errorMessage = "Something went wrong. Please check your email/password and try again" + } + + if (result.body()?.authCookieString != null) { + datastoreRepo.putString( + DatastoreKeys.omnivoreAuthCookieString, result.body()?.authCookieString!! + ) + } + } } + + } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/RESTNetworker.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/RESTNetworker.kt index 62a838665..c3956f73e 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/RESTNetworker.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/RESTNetworker.kt @@ -7,6 +7,17 @@ import retrofit2.http.Body import retrofit2.http.Headers import retrofit2.http.POST +data class AuthPayload( + val authCookieString: String, + val authToken: String +) + +data class SignInParams( + val token: String, + val provider: String, // APPLE or GOOGLE + val source: String = "ANDROID" +) + data class EmailAuthPayload( val authCookieString: String?, val authToken: String?, @@ -24,6 +35,12 @@ interface EmailLoginSubmit { suspend fun submitEmailLogin(@Body credentials: EmailLoginCredentials): Response } +interface AuthProviderLoginSubmit { + @Headers("Content-Type: application/json") + @POST("/api/mobile-auth/sign-in") + suspend fun submitAuthProviderLogin(@Body params: SignInParams): Response +} + object RetrofitHelper { fun getInstance(): Retrofit { return Retrofit.Builder().baseUrl(Constants.demoProdURL) diff --git a/packages/api/.env.example b/packages/api/.env.example index 6e90843b6..78aa2387a 100644 --- a/packages/api/.env.example +++ b/packages/api/.env.example @@ -12,6 +12,7 @@ GATEWAY_URL=http://localhost:4000/api IMAGE_PROXY_URL=http://localhost:8080 IMAGE_PROXY_SECRET_KEY=some-secret GAUTH_IOS_CLIENT_ID= +GAUTH_ANDROID_CLIENT_ID= GAUTH_CLIENT_ID='notset' GAUTH_SECRET='notset' GCP_PROJECT_ID=omnivore-local diff --git a/packages/api/.env.test b/packages/api/.env.test index 16fd0aaf8..bfdce2355 100644 --- a/packages/api/.env.test +++ b/packages/api/.env.test @@ -12,6 +12,7 @@ GATEWAY_URL=http://localhost:4000/api IMAGE_PROXY_URL=http://localhost:8080 IMAGE_PROXY_SECRET_KEY=some-secret GAUTH_IOS_CLIENT_ID= +GAUTH_ANDROID_CLIENT_ID= GAUTH_CLIENT_ID='notset' GAUTH_SECRET='notset' GCP_PROJECT_ID=omnivore-local diff --git a/packages/api/src/routers/auth/google_auth.ts b/packages/api/src/routers/auth/google_auth.ts index e6c78eafb..e9b2b37bd 100644 --- a/packages/api/src/routers/auth/google_auth.ts +++ b/packages/api/src/routers/auth/google_auth.ts @@ -57,16 +57,22 @@ export const validateGoogleUser = async ( } } -const googleMobileClient = new OAuth2Client(env.google.auth.iosClientId) const googleWebClient = new OAuth2Client(env.google.auth.clientId) export async function decodeGoogleToken( - idToken: string + idToken: string, + isAndroid: boolean ): Promise { try { + const clientID = isAndroid + ? env.google.auth.androidClientId + : env.google.auth.iosClientId + + const googleMobileClient = new OAuth2Client(clientID) + const loginTicket = await googleMobileClient.verifyIdToken({ idToken, - audience: env.google.auth.iosClientId, + audience: clientID, }) const email = loginTicket.getPayload()?.email diff --git a/packages/api/src/routers/auth/mobile/mobile_auth_router.ts b/packages/api/src/routers/auth/mobile/mobile_auth_router.ts index 138aae9c8..de1652bf7 100644 --- a/packages/api/src/routers/auth/mobile/mobile_auth_router.ts +++ b/packages/api/src/routers/auth/mobile/mobile_auth_router.ts @@ -16,8 +16,9 @@ export function mobileAuthRouter() { const router = express.Router() router.post('/sign-in', async (req, res) => { - const { token, provider } = req.body - const payload = await createMobileSignInResponse(token, provider) + const { token, provider, source } = req.body + const isAndroid = source === 'ANDROID' + const payload = await createMobileSignInResponse(isAndroid, token, provider) res.status(payload.statusCode).json(payload.json) }) diff --git a/packages/api/src/routers/auth/mobile/sign_in.ts b/packages/api/src/routers/auth/mobile/sign_in.ts index 699c38aa0..8feb36d41 100644 --- a/packages/api/src/routers/auth/mobile/sign_in.ts +++ b/packages/api/src/routers/auth/mobile/sign_in.ts @@ -15,12 +15,13 @@ import { StatusType } from '../../../datalayer/user/model' import { comparePassword } from '../../../utils/auth' export async function createMobileSignInResponse( + isAndroid: boolean, token?: string, provider?: AuthProvider ): Promise { try { if (token && provider === 'GOOGLE') { - const decodedTokenResult = await decodeGoogleToken(token) + const decodedTokenResult = await decodeGoogleToken(token, isAndroid) return createAuthResponsePayload(provider, decodedTokenResult) } diff --git a/packages/api/src/util.ts b/packages/api/src/util.ts index f43a9a8b2..edd3b642d 100755 --- a/packages/api/src/util.ts +++ b/packages/api/src/util.ts @@ -30,6 +30,7 @@ interface BackendEnv { google: { auth: { iosClientId: string + androidClientId: string clientId: string secret: string } @@ -122,6 +123,7 @@ const nullableEnvVars = [ 'PREVIEW_GENERATION_SERVICE_URL', 'GCS_UPLOAD_SA_KEY_FILE_PATH', 'GAUTH_IOS_CLIENT_ID', + 'GAUTH_ANDROID_CLIENT_ID', 'GAUTH_CLIENT_ID', 'GAUTH_SECRET', 'SEGMENT_WRITE_KEY', @@ -195,6 +197,7 @@ export function getEnv(): BackendEnv { const google = { auth: { iosClientId: parse('GAUTH_IOS_CLIENT_ID'), + androidClientId: parse('GAUTH_ANDROID_CLIENT_ID'), clientId: parse('GAUTH_CLIENT_ID'), secret: parse('GAUTH_SECRET'), },