mirror of
https://github.com/directus/directus.git
synced 2026-02-01 20:45:02 -05:00
Wrap up oAuth flow
This commit is contained in:
@@ -5,6 +5,7 @@ import Joi from '@hapi/joi';
|
||||
import * as AuthService from '../services/auth';
|
||||
import grant from 'grant';
|
||||
import getGrantConfig from '../utils/get-grant-config';
|
||||
import getEmailFromProfile from '../utils/get-email-from-profile';
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -19,6 +20,12 @@ router.post(
|
||||
await loginSchema.validateAsync(req.body);
|
||||
const { email, password } = req.body;
|
||||
|
||||
/**
|
||||
* @TODO
|
||||
* Make sure to validate the payload. AuthService.authenticate's password is optional which
|
||||
* means there's a possible problem when req.body.password is undefined
|
||||
*/
|
||||
|
||||
const token = await AuthService.authenticate(email, password);
|
||||
|
||||
return res.status(200).json({
|
||||
@@ -31,15 +38,17 @@ router.use('/sso', session({ secret: process.env.SECRET, saveUninitialized: true
|
||||
|
||||
router.use(grant.express()(getGrantConfig()));
|
||||
|
||||
router.get('/sso/:provider/callback', (req, res) => {
|
||||
console.log(req.session.grant);
|
||||
router.get(
|
||||
'/sso/:provider/callback',
|
||||
asyncHandler(async (req, res) => {
|
||||
const email = getEmailFromProfile(req.params.provider, req.session.grant.response.profile);
|
||||
|
||||
/**
|
||||
* @TODO
|
||||
*
|
||||
*/
|
||||
const token = await AuthService.authenticate(email);
|
||||
|
||||
res.send(req.session.grant);
|
||||
});
|
||||
return res.status(200).json({
|
||||
data: { token },
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -2,7 +2,7 @@ import database from '../database';
|
||||
import APIError, { ErrorCode } from '../error';
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
export const authenticate = async (email: string, password: string) => {
|
||||
export const authenticate = async (email: string, password?: string) => {
|
||||
const user = await database
|
||||
.select('id', 'password', 'role')
|
||||
.from('directus_users')
|
||||
@@ -13,8 +13,15 @@ export const authenticate = async (email: string, password: string) => {
|
||||
throw new APIError(ErrorCode.INVALID_USER_CREDENTIALS, 'Invalid user credentials');
|
||||
}
|
||||
|
||||
/** @TODO implement password hash */
|
||||
if (password !== user.password) {
|
||||
/**
|
||||
* @NOTE
|
||||
* This undefined check is on purpose so we can login through SSO without having to rely on
|
||||
* password. However, this check might be a little tricky, as we don't want this login with just
|
||||
* email to leak anywhere else.. We might have to make a dedicated "copy" of this function to
|
||||
* signal the difference
|
||||
*/
|
||||
if (password !== undefined && password !== user.password) {
|
||||
/** @TODO implement password hash checking */
|
||||
throw new APIError(ErrorCode.INVALID_USER_CREDENTIALS, 'Invalid user credentials');
|
||||
}
|
||||
|
||||
|
||||
@@ -1,24 +1,28 @@
|
||||
import { get } from 'lodash';
|
||||
|
||||
// The path in JSON to fetch the email address from the profile.
|
||||
const profileMap = {
|
||||
github: 'email',
|
||||
};
|
||||
// Note: a lot of services use `email` as the path. We fall back to that as default, so no need to
|
||||
// map it here
|
||||
const profileMap = {};
|
||||
|
||||
/**
|
||||
* Extract the email address from a given user profile coming from a providers API
|
||||
*
|
||||
* Falls back to OAUTH_<PROVIDER>_PROFILE_EMAIL if we don't have it preconfigured yet
|
||||
* Falls back to OAUTH_<PROVIDER>_PROFILE_EMAIL if we don't have it preconfigured yet, and defaults
|
||||
* to `email` if nothing is set
|
||||
*
|
||||
* This is used in the SSO flow to extract the users
|
||||
*/
|
||||
export default function getEmailFromProfile(provider: string, profile: Record<string, any>) {
|
||||
const path =
|
||||
profileMap[provider] || process.env[`OAUTH_${provider.toUpperCase()}_PROFILE_EMAIL`];
|
||||
profileMap[provider] ||
|
||||
process.env[`OAUTH_${provider.toUpperCase()}_PROFILE_EMAIL`] ||
|
||||
'email';
|
||||
const email = get(profile, path);
|
||||
|
||||
if (!path) {
|
||||
throw new Error('Path to email in profile object is unknown.');
|
||||
if (!email) {
|
||||
throw new Error("Couldn't extract email address from SSO provider response");
|
||||
}
|
||||
|
||||
return get(profile, path);
|
||||
return email;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user