Skip to content

Instantly share code, notes, and snippets.

@jhalborg
Created July 21, 2017 11:43
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jhalborg/5042201f558034243376cffb55111d85 to your computer and use it in GitHub Desktop.
Save jhalborg/5042201f558034243376cffb55111d85 to your computer and use it in GitHub Desktop.
GraphCool + Firebase Auth function for generating a custom Firebase token with embedded Graphcool token
import * as admin from 'firebase-admin';
import Graphcool, { fromEvent } from 'graphcool-lib';
import { Request, Response } from 'express';
const TAG = 'LoginHandler';
const serviceAccount = require('./path/to/firebaseKey.json');
const pat = '__PAT__'
const projectId = '__PROJECT-ID__';
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: '__DATABASE-URL__'
});
const loginHandler = async (req: Request, res: Response) => {
if (
req.body !== null &&
req.body.data !== null &&
req.body.data.firebaseIdToken != null
) {
req.body.context = { graphcool: { pat, projectId } }; // Adding context manually, should not be needed when out of beta
const graphcool = fromEvent(req.body);
const api = graphcool.api('relay/v1');
const { firebaseIdToken } = req.body.data;
let firebaseUserId: string = '';
let graphcoolUserId: string = '';
console.log(`${TAG} Received firebaseIdToken ${firebaseIdToken}`);
// Verify the token with Firebase SDK
try {
const decodedToken = await admin.auth().verifyIdToken(firebaseIdToken);
firebaseUserId = decodedToken.uid;
} catch (error) {
res.status(401).send(`Could not verify id token with Firebase`);
return;
}
try {
const user = await getGraphcoolUser(firebaseUserId, graphcool);
if (user === null) {
graphcoolUserId = await createGraphcoolUser(firebaseUserId, graphcool);
} else {
graphcoolUserId = user.id;
}
const graphcoolToken = await generateGraphcoolToken(
graphcoolUserId,
graphcool
);
const additionalClaims = {
graphcoolToken: graphcoolToken
};
const customFirebaseToken = await admin
.auth()
.createCustomToken(firebaseUserId, additionalClaims);
res.status(200).send({ data: { customToken: customFirebaseToken } });
} catch (error) {
res.status(503).send(`Error communicating with GraphCool: ${error}`);
return;
}
} else {
res.status(400).send(`No data found for req.body.data.firebaseIdToken`);
}
};
const generateGraphcoolToken = async (
graphcoolUserId: string,
graphcool: Graphcool
) => {
return graphcool.generateAuthToken(graphcoolUserId, 'User');
};
const createGraphcoolUser = async (
firebaseUserId: string,
graphcool: Graphcool
) => {
return new Promise(async (resolve, reject) => {
const api = graphcool.api('relay/v1');
try {
const createUserResult = await api.request(`
mutation CreateUserMutation {
createUser(input :{
clientMutationId:"",
firebaseUserId:"${firebaseUserId}",
}) {
user {
id
}
}
}`);
const graphcoolUserId: string = createUserResult.createUser.user.id;
resolve(graphcoolUserId);
} catch (error) {
reject(`Could not create GraphCool user`);
}
});
};
const getGraphcoolUser = async (firebaseId: string, graphcool: Graphcool) => {
return new Promise(async (resolve, reject) => {
const api = graphcool.api('relay/v1');
try {
const userQueryResult: any = await api.request(`
query {
viewer {
User(firebaseUserId:"${firebaseId}"){
id
email
}
}
}`);
if (userQueryResult.error) {
reject(userQueryResult.error);
} else {
resolve(userQueryResult.viewer.User);
}
} catch (error) {
reject(`Could not retrieve GraphCool user`);
}
});
};
export default loginHandler;
type CustomTokenPayload {
customToken: String!
}
extend type Query {
getCustomToken(firebaseIdToken: String!): CustomTokenPayload
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment