diff --git a/.github/workflows/deploy-to-dev.yml b/.github/workflows/deploy-to-dev.yml index d6365d4..d8e00fb 100644 --- a/.github/workflows/deploy-to-dev.yml +++ b/.github/workflows/deploy-to-dev.yml @@ -23,10 +23,10 @@ jobs: - name: Create .env file run: | - echo "JWT_SECRET=${{ secrets.DEV_JWT_SECRET }}" >> .env - echo "DATABASE_URL=${{ secrets.DEV_DATABASE_URL }}" >> .env - echo "ACCESS_CODE_EXPIRY=1y" >> .env - echo "ENV=development" >> .env + echo "JWT_SECRET=\"${{ secrets.DEV_JWT_SECRET }}\"" >> .env + echo "DATABASE_URL=\"${{ secrets.DEV_DATABASE_URL }}\"" >> .env + echo "ACCESS_CODE_EXPIRY=\"1y\"" >> .env + echo "ENV=\"development\"" >> .env - name: Build project run: npm run build diff --git a/.github/workflows/deploy-to-prod.yml b/.github/workflows/deploy-to-prod.yml index c16fae2..1447075 100644 --- a/.github/workflows/deploy-to-prod.yml +++ b/.github/workflows/deploy-to-prod.yml @@ -23,11 +23,14 @@ jobs: - name: Create .env file run: | - echo "JWT_SECRET=${{ secrets.PRODUCTION_JWT_SECRET }}" >> .env - echo "DATABASE_URL=${{ secrets.PRODUCTION_DATABASE_URL }}" >> .env - echo "FIREBASE_WEB_API_KEY=${{ secrets.FIREBASE_WEB_API_KEY }}" >> .env - echo "ACCESS_CODE_EXPIRY=1y" >> .env - echo "ENV=production" >> .env + echo "JWT_SECRET=\"${{ secrets.PRODUCTION_JWT_SECRET }}\"" >> .env + echo "DATABASE_URL=\"${{ secrets.PRODUCTION_DATABASE_URL }}\"" >> .env + echo "FIREBASE_WEB_API_KEY=\"${{ secrets.FIREBASE_WEB_API_KEY }}\"" >> .env + echo "FIREBASE_PROJECT_ID=\"${{ secrets.FIREBASE_PROJECT_ID }}\"" >> .env + echo "FIREBASE_CLIENT_EMAIL=\"${{ secrets.FIREBASE_CLIENT_EMAIL }}\"" >> .env + echo "FIREBASE_PRIVATE_KEY=\"${{ secrets.FIREBASE_PRIVATE_KEY }}\"" >> .env + echo "ACCESS_CODE_EXPIRY=\"1y\"" >> .env + echo "ENV=\"production\"" >> .env - name: Build project run: npm run build diff --git a/.github/workflows/deploy-to-staging.yml b/.github/workflows/deploy-to-staging.yml index cce61c8..601e18c 100644 --- a/.github/workflows/deploy-to-staging.yml +++ b/.github/workflows/deploy-to-staging.yml @@ -23,11 +23,14 @@ jobs: - name: Create .env file run: | - echo "JWT_SECRET=${{ secrets.STAGING_JWT_SECRET }}" >> .env - echo "DATABASE_URL=${{ secrets.STAGING_DATABASE_URL }}" >> .env - echo "FIREBASE_WEB_API_KEY=${{ secrets.FIREBASE_WEB_API_KEY }}" >> .env - echo "ACCESS_CODE_EXPIRY=1y" >> .env - echo "ENV=staging" >> .env + echo "JWT_SECRET=\"${{ secrets.STAGING_JWT_SECRET }}\"" >> .env + echo "DATABASE_URL=\"${{ secrets.STAGING_DATABASE_URL }}\"" >> .env + echo "FIREBASE_WEB_API_KEY=\"${{ secrets.FIREBASE_WEB_API_KEY }}\"" >> .env + echo "FIREBASE_PROJECT_ID=\"${{ secrets.FIREBASE_PROJECT_ID }}\"" >> .env + echo "FIREBASE_CLIENT_EMAIL=\"${{ secrets.FIREBASE_CLIENT_EMAIL }}\"" >> .env + echo "FIREBASE_PRIVATE_KEY=\"${{ secrets.FIREBASE_PRIVATE_KEY }}\"" >> .env + echo "ACCESS_CODE_EXPIRY=\"1y\"" >> .env + echo "ENV=\"staging\"" >> .env - name: Build project run: npm run build diff --git a/package.json b/package.json index d0aa4ed..1e0d26f 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "bcrypt": "^5.1.1", "class-validator": "^0.14.0", "cookie-parser": "^1.4.6", + "firebase-admin": "^12.1.0", "mongoose": "^8.0.3", "passport": "^0.7.0", "passport-jwt": "^4.0.1", diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 6566d6f..67682b9 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -19,6 +19,6 @@ export class AuthController { @Post('verifyOTP') async verifyOTP(@Body() otpBody, @Res() response) { - this.authService.verifyOTP(otpBody, response); + return response.json(await this.authService.verifyOTP(otpBody)); } } diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index ab3ce60..7350175 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -5,6 +5,8 @@ import * as bcrypt from 'bcrypt'; import { generalError } from 'src/utils/generalError'; import Twilio from 'twilio'; import getCountryCodeAndPhoneNumber from 'src/utils/getCountryCodeAndPhoneNumber'; +import { verifyToken } from 'src/utils/firebase'; + @Injectable() export class AuthService { constructor( @@ -33,73 +35,57 @@ export class AuthService { return accessToken; } - async login(phoneNumber, response) { + async login(phoneNumber: string) { const { phoneNumber: phoneNumberWithoutCountryCode, countryCode } = getCountryCodeAndPhoneNumber(phoneNumber); + const user = await this.userService.findOrCreateUser( phoneNumberWithoutCountryCode, countryCode, ); const token = this.getAuthToken(user); - return response.json({ + + return { token, user, - }); - } - - async verifyFirebaseOtp(sessionInfo, code) { - const apiKey = process.env.FIREBASE_WEB_API_KEY; - const url = `https://identitytoolkit.googleapis.com/v1/accounts:signInWithPhoneNumber?key=${apiKey}`; - const requestBody = { - sessionInfo, - code, }; + } + async verifyFirebaseOtp(payload: string) { try { - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(requestBody), - }); - - const responseData = await response.json(); - return responseData; + const decodedToken = await verifyToken(payload); + return decodedToken.phone_number; } catch (error) { console.error('Error verifying OTP:', error); throw error; } } - async verifyDevModeOtp(otpBody, response) { + async verifyDevModeOtp(payload: string) { try { - const { payload, otp } = otpBody; - - this.login(payload, response); + return payload; } catch (error) { - response.json({ - error: 'Failed to verify OTP. Please try again later.' + error, - }); + console.log('Error verifying OTP:', error); + throw error; } } - async verifyOTP(otpBody, response) { + async verifyOTP(otpBody) { + let phoneNumberWithCountryCode: string; try { + const { payload } = otpBody; + if (process.env.ENV === 'development' || process.env.ENV === 'dev') { - this.verifyDevModeOtp(otpBody, response); - return; + phoneNumberWithCountryCode = await this.verifyDevModeOtp(payload); + } else { + phoneNumberWithCountryCode = await this.verifyFirebaseOtp(payload); } - const { payload, otp } = otpBody; - const { phoneNumber: phoneNumberWithCountryCode } = - await this.verifyFirebaseOtp(payload, otp); - - this.login(phoneNumberWithCountryCode, response); + return await this.login(phoneNumberWithCountryCode); } catch (error) { - response.json({ + return { error: 'Failed to verify OTP. Please try again later.' + error, - }); + }; } } diff --git a/src/utils/firebase.ts b/src/utils/firebase.ts new file mode 100644 index 0000000..75a1ff3 --- /dev/null +++ b/src/utils/firebase.ts @@ -0,0 +1,22 @@ +import firebase from 'firebase-admin'; + +let app: firebase.app.App; + +export const verifyToken = async (token: string) => { + try { + if (!app) { + app = firebase.initializeApp({ + credential: firebase.credential.cert({ + projectId: process.env.FIREBASE_PROJECT_ID, + clientEmail: process.env.FIREBASE_CLIENT_EMAIL, + privateKey: process.env.FIREBASE_PRIVATE_KEY, + }), + }); + } + + const decodedToken = await app.auth().verifyIdToken(token); + return decodedToken; + } catch (error) { + return error; + } +};