Created
July 21, 2017 11:43
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} | |
}`); | |
if (userQueryResult.error) { | |
reject(userQueryResult.error); | |
} else { | |
resolve(userQueryResult.viewer.User); | |
} | |
} catch (error) { | |
reject(`Could not retrieve GraphCool user`); | |
} | |
}); | |
}; | |
export default loginHandler; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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