@gfritz Thanks for your reply, it helped me a lot in creating authorization through Firebase Phone Auth. But I’m stuck at the verify stage. The authenticate function works correctly. Could you help with writing the verify function? After the code, I’ll provide the context that goes into it.
"use strict";
const { ForbiddenError } = require('@strapi/utils').errors;
const jwt = require('jsonwebtoken');
module.exports = {
/**
* An asynchronous register function that runs before
* your application is initialized.
*
* This gives you an opportunity to extend code.
*/
register({ strapi }) {
strapi.container.get('auth').register('content-api', {
name: 'firebase-jwt-verifier',
async authenticate(ctx) {
const { authorization } = ctx.request.header;
// Check for the presence of a JWT token in the header
if (authorization) {
const parts = authorization.split(/\s+/);
if (parts[0].toLowerCase() === 'bearer' && parts.length === 2) {
const token = parts[1];
try {
// Verify and decode the Firebase JWT token
const decodedToken = await strapi.firebase.auth().verifyIdToken(token);
// Check if the phone number in the JWT token matches the incoming request
if (decodedToken.phone_number === ctx.request.body.phoneNumber) {
// Get the user or create a new user based on the phone number
let user = await strapi.db.query('plugin::users-permissions.user').findOne({
where: { phoneNumber: ctx.request.body.phoneNumber }
});
if (!user) {
// If the user does not exist, create a new user
user = await strapi.db.query('plugin::users-permissions.user').create({ phoneNumber: ctx.request.body.phoneNumber });
}
// Set the user in the context state
ctx.state.user = user;
// Generate Strapi JWT token
const jwtToken = await strapi.service('plugin::users-permissions.jwt').issue({ id: user.id });
ctx.state.user.jwt = jwtToken
// Return successful authentication and user information
return { authenticated: true, credentials: user };
}
} catch (error) {
// Handle error when verifying or decoding the JWT token
console.error('Error while verifying Firebase JWT token:', error);
}
}
}
// If authentication fails, return authentication error
return { authenticated: false };
},
async verify(ctx) {
try {
// Check for jwt token in ctx.state.auth
if (ctx.credentials && ctx.credentials.jwt) {
const tokenPayload = await strapi.service('plugin::users-permissions.jwt').verify(ctx.credentials.jwt);
return tokenPayload;
}
} catch (error) {
console.error('Error while verifying JWT token:', error);
}
throw new ForbiddenError('Invalid JWT token');
}
});
},
/**
* An asynchronous bootstrap function that runs before
* your application gets started.
*
* This gives you an opportunity to set up your data model,
* run jobs, or perform some special logic.
*/
bootstrap({ strapi }) {
const admin = require("firebase-admin");
const serviceAccount = require("../private/firebase/serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
strapi.firebase = admin;
},
};
Ctx in verify:
{
strategy: {
name: 'firebase-jwt-verifier',
authenticate: [AsyncFunction: authenticate],
verify: [AsyncFunction: verify]
},
credentials: {
id: 1,
username: 'ivstepin',
email: '...',
provider: 'local',
password: '...',
resetPasswordToken: null,
confirmationToken: null,
confirmed: true,
blocked: false,
createdAt: '2023-06-04T03:18:58.578Z',
updatedAt: '2023-06-06T20:00:36.307Z',
phoneNumber: '...',
jwt: 'eyJhbGciO ... ePFc'
},
ability: null
}