|
"use strict"; |
|
|
|
const jwt = require("jsonwebtoken"); |
|
const { getAuth } = require("firebase-admin/auth"); |
|
const { nanoid } = require("nanoid"); |
|
const ms = require("ms"); |
|
|
|
const DEFAULT_ROLE_NAME = "User"; // update this variable with the name of your role |
|
const PROVIDER_NAME = "firebase"; |
|
|
|
var endpoint = (router, { services, exceptions, env, database: knex, emitter, logger }) => { |
|
router.post("/connect", async (req, res, next) => { |
|
const { InvalidCredentialsException } = exceptions; |
|
const { accountability, schema } = req; |
|
const idToken = req.body?.id_token; |
|
|
|
const { UsersService, RolesService } = services; |
|
|
|
const usersService = new UsersService({ schema }); |
|
const rolesService = new RolesService({ schema }); |
|
|
|
let user, role, decodedToken; |
|
|
|
// verify token |
|
try { |
|
decodedToken = await getAuth() |
|
.verifyIdToken(idToken); |
|
} |
|
catch (error) { |
|
logger.info(error.message); |
|
return next(new InvalidCredentialsException()); |
|
} |
|
|
|
// get user |
|
const { email } = decodedToken; |
|
user = await getUser(email, usersService); |
|
|
|
// set role if user found, or create new user |
|
if (user?.id) { |
|
role = await getRole(user.role, rolesService); |
|
} |
|
else { |
|
role = await getRole(undefined, rolesService); |
|
const userId = await usersService.createOne({ |
|
email, |
|
provider: PROVIDER_NAME, |
|
role: role.id |
|
}); |
|
user = await usersService.readOne(userId); |
|
} |
|
|
|
const tokenPayload = { |
|
id: user.id, |
|
role: user.role, |
|
app_access: role.app_access, |
|
admin_access: role.admin_access, |
|
}; |
|
|
|
// sign jwt for user |
|
const accessToken = jwt.sign(tokenPayload, env.SECRET, { |
|
expiresIn: env.ACCESS_TOKEN_TTL, |
|
issuer: "directus", |
|
}); |
|
|
|
const refreshToken = nanoid(64); |
|
const refreshTokenExpiration = new Date(Date.now() + ms(env.REFRESH_TOKEN_TTL)); |
|
|
|
await knex('directus_sessions').insert({ |
|
token: refreshToken, |
|
user: user.id, |
|
expires: refreshTokenExpiration, |
|
ip: accountability?.ip, |
|
user_agent: accountability?.userAgent, |
|
}); |
|
|
|
await knex('directus_sessions').delete().where('expires', '<', new Date()); |
|
|
|
await knex('directus_users').update({ last_access: new Date() }).where({ id: user.id }); |
|
|
|
res.json({ |
|
data: { |
|
accessToken, |
|
refreshToken, |
|
expires: ms(env.ACCESS_TOKEN_TTL), |
|
} |
|
}); |
|
}); |
|
}; |
|
|
|
const getUser = async (email, service) => { |
|
const user = (await service.readByQuery({ |
|
fields: ["*"], |
|
filter: { |
|
email: { |
|
_eq: email |
|
} |
|
} |
|
}))[0]; |
|
return user; |
|
} |
|
|
|
const getRole = async (roleId, service) => { |
|
let role; |
|
if (roleId) { |
|
role = await service.readOne(roleId); |
|
} |
|
else { |
|
role = (await service.readByQuery({ |
|
fields: ["id", "admin_access", "app_access"], |
|
filter: { |
|
name: { |
|
_eq: DEFAULT_ROLE_NAME |
|
} |
|
} |
|
}))[0]; |
|
} |
|
return role; |
|
} |
|
|
|
module.exports = endpoint; |
How do you use it on the front end? Does it mean one can use directus sdk?