Skip to content

Instantly share code, notes, and snippets.

@gautamsi
Created November 9, 2021 05:43
Show Gist options
  • Select an option

  • Save gautamsi/d89cf29a5ea2d4c3eb0e19eb248a8d9c to your computer and use it in GitHub Desktop.

Select an option

Save gautamsi/d89cf29a5ea2d4c3eb0e19eb248a8d9c to your computer and use it in GitHub Desktop.
Firebase Auth with Keystone
import { KeystoneContext } from '@keystone-next/keystone/types';
import admin from 'firebase-admin';
const firebase = admin.initializeApp();
export const authMutations = `
authenticateWithFirebase(token: String!): User
signupWithFirebase(
token: String!
name: String!
email: String
password: String!
): User
verifyEmailAddress(token: String!): User
verifyMobile(phone: String!): UserAlreadyExist
`;
export const authTypes = `
type UserAlreadyExist {
success: Boolean!
}
`;
export async function authenticateWithFirebase(
root: any,
{ token }: { token: string },
context: KeystoneContext
) {
const sudo = context.sudo();
const firebaseToken = await firebase.auth()?.verifyIdToken(token);
const { uid, phone_number: phone } = firebaseToken;
const firebaseUser = await sudo.lists.User.findMany({
where: {
firebaseId: { equals: uid },
phone: { equals: phone },
},
});
if (!firebaseUser.length) {
throw new Error('USER_NOT_FOUND');
}
const item = firebaseUser[0];
const newToken = await context?.startSession?.({
itemId: item?.id,
listKey: 'User',
});
if (newToken) {
return await sudo.db.lists.User.findOne({ where: { id: item.id } });
}
return null;
}
export async function signupWithFirebase(
root: any,
{
token,
name,
email,
password,
}: { token: string; name: string; email: string; password: string },
context: KeystoneContext
) {
try {
const firebaseToken = await firebase.auth().verifyIdToken(token);
const sudo = context.sudo();
const { uid, phone_number: phone } = firebaseToken;
const firebaseUser = await sudo.lists.User.findMany({
where: {
firebaseId: { equals: uid },
phone: { equals: phone },
},
});
if (firebaseUser.length) {
throw new Error('USER_ALREADY_EXIST');
}
const newUser = await sudo.lists.User.createOne({
data: {
name,
phone: phone,
firebaseId: uid,
email,
password,
},
});
const item = newUser;
const currentUser = await context?.startSession?.({
itemId: item?.id,
listKey: 'User',
});
if (currentUser) {
return await sudo.db.lists.User.findOne({ where: { id: item.id } });
}
return null;
} catch (error) {
throw new Error('Error creating User.');
}
}
export async function verifyEmailAddress(
root: any,
{ token }: { token: string },
context: KeystoneContext
) {
const user = context?.session?.data;
if (!user?.id) {
return null;
}
try {
const firebaseToken = await firebase.auth().verifyIdToken(token);
const { email_verified } = firebaseToken;
const sudo = context.sudo();
const registeredUser = await sudo.lists.User.updateOne({
where: { id: user.id },
data: {
isVerifiedEmail: email_verified,
},
query: 'id',
});
return { id: registeredUser.id };
} catch (error) {
console.log('error', error);
return null;
}
}
export async function verifyMobile(
root: any,
{ phone }: { phone: string },
context: KeystoneContext
) {
const sudo = context.sudo();
const isValid = await sudo.lists.User.findOne({
where: { phone },
query: 'id',
});
return { success: isValid?.id ? true : false };
}
import { graphQLSchemaExtension } from '@keystone-next/keystone';
import {
authenticateWithFirebase,
authMutations,
authTypes,
signupWithFirebase,
verifyEmailAddress,
verifyMobile,
} from './auth';
const typeDefs = String.raw`
${authTypes}
type Mutation {
${authMutations}
}
`;
export const extendGraphqlSchema = graphQLSchemaExtension({
typeDefs,
resolvers: {
Mutation: {
authenticateWithFirebase,
signupWithFirebase,
verifyEmailAddress,
verifyMobile,
},
},
});
@gautamsi
Copy link
Copy Markdown
Author

gautamsi commented Nov 9, 2021

import extendGraphqlSchema to add to keystone config.

@dragosstancu
Copy link
Copy Markdown

Hi,

Thank you, Sir!

That looks very exciting!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment