Authentication Backend workflows - dfernandezm/moneycol GitHub Wiki
These workflows have been implemented in GraphQL server for v1. They wrap Firebase Auth client and admin library for the login with password functionality.
GraphQL mutations
There 3 public mutations implemented in GraphQL
loginWithEmail(username, password)
verifyToken(token: string, refresh: boolean)
logout(token: string)
Examples
mutation login($email: String!, $password: String!) {
loginWithEmail(email: $email, password: $password) {
email
token
userId
}
}
---
{
"email": "[email protected]",
"password": "xxxx"
}
mutation verifyToken($token: String!) {
verifyToken(token: $token, refresh: true) {
userId
email
token
}
}
---
{
"token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImZjMmM4YmIyNmE3OGM0M2JkODYzNzA1YjNkNzky..."
}
mutation logout($token: String!) {
logout(token: $token) {
result
}
}
---
{
"token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImZjMmM4YmIyNmE3OGM0M2JkODYzNzA1YjNkNzky..."
}
Login a user with email and password
This corresponds to the loginWithEmail
mutation.
- Frontend collects email/pass and sends request to GQL
- Server logs the user in using firebase auth
- on success
- stores/overrides a session in Firestore
- current valid token is stored
- the refresh token for this user is stored
- lastLogin
- userId
- returns back email, token, userId (authResult)
- frontend stores the token in local storage
- frontend sends the token with every GQL request
- stores/overrides a session in Firestore
- On error
- authentication error is thrown (401), user should relogin
Token verification
Verify mutation with refresh (validateToken).
- The frontend presents an stored token to renew a long lived session and avoid re-login
- First check if the presented token has been programmatically revoked (logged out)
- This means the user explicitly logged out, so this token cannot be reused. It is being presented from an old session or it has been leaked
- if token revoked, an error in sent asking to login again
- if not revoked, continue
- Try to validate the token
- if non-expired token: it is verified using Firebase Auth
- on success
- if refresh has been requested
- it finds the refreshToken from the user session in Firestore
- uses Firebase Auth API to exchange refreshToken with idToken
- stores the new data in the user session
- returns success back
- onError: user must re-login
- if refresh has not been requested
- overrides the session of this user in Firestore with data from the decoded token (it’s the same) and last Login
- if expired token:
- should check the expiration date in the token against the last login in user session stored in Firebase (not implemented in v1)
- if no user session is stored in Firestore
- fail with 401, user should re-login
- if user session is present in Firestore
- find the refresh token from it, exchange it with an idToken using Firebase Auth REST API
- store the data back in Firestore
- return success
- if no user session is stored in Firestore
- should check the expiration date in the token against the last login in user session stored in Firebase (not implemented in v1)
- if non-expired token: it is verified using Firebase Auth
Logout
Logout mutation.
- The frontend sends a logout request providing a token
- The token must be valid, otherwise the logout is rejected (401)
- User Id and email is decoded from the token
- The refreshToken (fetched from Firestore session) is revoked using Firebase Auth API (no more ID tokens can be issued with it)
- The current idToken is locked out by storing it in Firestore collection ‘logged_out_tokens'
- The user session is deleted from Firestore
- signOut is called on Firebase Auth
References
- Issues #185 and related
- Links
- Reauthentication: https://stackoverflow.com/questions/38233687/how-to-use-the-firebase-refreshtoken-to-reauthenticate
- Usage of async/await: https://stackoverflow.com/questions/56583184/what-is-the-best-way-to-use-async-await-inside-onauthstatechanged-of-firebase/56583572
- Exchange refresh tokens with ID tokens: https://stackoverflow.com/questions/38233687/how-to-use-the-firebase-refreshtoken-to-reauthenticate, https://firebase.google.com/docs/reference/rest/auth/
- Manage user sessions: https://firebase.google.com/docs/auth/admin/manage-sessions
- Revoking refresh tokens: https://medium.com/@hiranya911/firebase-revoking-auth-tokens-with-admin-sdk-ac62c73bfdb0