mirror of
https://github.com/strapi/strapi.git
synced 2025-12-27 07:03:38 +00:00
Use passport standard error handling
Signed-off-by: Alexandre Bodin <bodin.alex@gmail.com>
This commit is contained in:
parent
298dcac271
commit
a4f294f1c4
@ -3,7 +3,7 @@ module.exports = ({ env }) => ({
|
||||
port: env.int('PORT', 1337),
|
||||
admin: {
|
||||
jwt: {
|
||||
secret: env('ADMIN_JWT_SECRET', 'cdd07276439366dcc133324e14a1d6cb'),
|
||||
secret: env('ADMIN_JWT_SECRET', 'example-token'),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -12,7 +12,7 @@ module.exports = {
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
return ctx.badRequest(info.error);
|
||||
return ctx.badRequest(info.message);
|
||||
}
|
||||
|
||||
ctx.state.user = user;
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
const passport = require('koa-passport');
|
||||
const { Strategy: LocalStrategy } = require('passport-local');
|
||||
const { Strategy: JwtStrategy, ExtractJwt } = require('passport-jwt');
|
||||
|
||||
const createLocalStrategy = strapi => {
|
||||
return new LocalStrategy(
|
||||
@ -20,38 +19,38 @@ const createLocalStrategy = strapi => {
|
||||
);
|
||||
};
|
||||
|
||||
const createJWTStrategy = strapi => {
|
||||
const { options, secret } = strapi.admin.services.auth.getJWTOptions();
|
||||
|
||||
const opts = {
|
||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
secretOrKey: secret,
|
||||
jsonWebTokenOptions: options,
|
||||
};
|
||||
|
||||
return new JwtStrategy(opts, function({ id }, done) {
|
||||
strapi
|
||||
.query('administrator', 'admin')
|
||||
.findOne({ id })
|
||||
.then(user => {
|
||||
if (user) {
|
||||
return done(null, user);
|
||||
} else {
|
||||
return done(null, false);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
return done(err, false);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = strapi => ({
|
||||
initialize() {
|
||||
passport.use(createLocalStrategy(strapi));
|
||||
passport.use(createJWTStrategy(strapi));
|
||||
|
||||
// strapi.app.use(passport.authenticate('jwt', { session: false }));
|
||||
strapi.app.use(passport.initialize());
|
||||
|
||||
strapi.app.use(async (ctx, next) => {
|
||||
if (
|
||||
ctx.request.header.authorization &&
|
||||
ctx.request.header.authorization.split(' ')[0] === 'Bearer'
|
||||
) {
|
||||
const token = ctx.request.header.authorization.split(' ')[1];
|
||||
|
||||
const { payload, isValid } = strapi.admin.services.auth.decodeToken(token);
|
||||
|
||||
if (isValid) {
|
||||
// request is made by an admin
|
||||
const admin = await strapi
|
||||
.query('administrator', 'admin')
|
||||
.findOne({ id: payload.id }, []);
|
||||
|
||||
if (!admin || admin.blocked === true) {
|
||||
return ctx.forbidden('Invalid credentials');
|
||||
}
|
||||
|
||||
ctx.state.admin = admin;
|
||||
ctx.state.user = admin;
|
||||
return next();
|
||||
}
|
||||
}
|
||||
|
||||
return next();
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -64,8 +64,6 @@
|
||||
"match-sorter": "^4.0.2",
|
||||
"mini-css-extract-plugin": "^0.6.0",
|
||||
"moment": "^2.24.0",
|
||||
"passport": "0.4.1",
|
||||
"passport-jwt": "4.0.0",
|
||||
"passport-local": "1.0.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.9.0",
|
||||
|
||||
@ -8,7 +8,7 @@ const sanitizeUser = user => {
|
||||
return _.omit(user, ['password', 'resetPasswordToken']);
|
||||
};
|
||||
|
||||
const defaultOptions = { expiresIn: '1s' };
|
||||
const defaultOptions = { expiresIn: '30d' };
|
||||
|
||||
const getJWTOptions = () => {
|
||||
const { options, secret } = strapi.config.get('server.admin.jwt', {});
|
||||
@ -61,18 +61,18 @@ const checkCredentials = async ({ email, password }) => {
|
||||
const user = await strapi.query('administrator', 'admin').findOne({ email });
|
||||
|
||||
if (!user) {
|
||||
return [null, false, { error: 'Invalid credentials' }];
|
||||
return [null, false, { message: 'Invalid credentials' }];
|
||||
}
|
||||
|
||||
const isValid = await strapi.admin.services.auth.validatePassword(password, user.password);
|
||||
|
||||
if (!isValid) {
|
||||
return [null, false, { error: 'Invalid credentials' }];
|
||||
return [null, false, { message: 'Invalid credentials' }];
|
||||
}
|
||||
|
||||
// TODO: change to isActive
|
||||
if (user.blocked === true) {
|
||||
return [null, false, { error: 'User not active' }];
|
||||
return [null, false, { message: 'User not active' }];
|
||||
}
|
||||
|
||||
return [null, user];
|
||||
|
||||
@ -61,7 +61,7 @@ const buildMutation = (mutationName, config) => {
|
||||
const buildMutationContext = ({ options, graphqlContext }) => {
|
||||
const { context } = graphqlContext;
|
||||
|
||||
const ctx = context.app.createContext(_.clone(context.req), _.clone(context.res));
|
||||
const ctx = cloneKoaContext(context);
|
||||
|
||||
if (options.input && options.input.where) {
|
||||
ctx.params = convertToParams(options.input.where || {});
|
||||
@ -134,11 +134,19 @@ const validateResolverOption = config => {
|
||||
return true;
|
||||
};
|
||||
|
||||
const cloneKoaContext = ctx => {
|
||||
return Object.assign(ctx.app.createContext(_.clone(ctx.req), _.clone(ctx.res)), {
|
||||
state: {
|
||||
...ctx.state,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const buildQueryContext = ({ options, graphqlContext }) => {
|
||||
const { context } = graphqlContext;
|
||||
const _options = _.cloneDeep(options);
|
||||
|
||||
const ctx = context.app.createContext(_.clone(context.req), _.clone(context.res));
|
||||
const ctx = cloneKoaContext(context);
|
||||
|
||||
// Note: we've to used the Object.defineProperties to reset the prototype. It seems that the cloning the context
|
||||
// cause a lost of the Object prototype.
|
||||
|
||||
@ -3,38 +3,25 @@ const _ = require('lodash');
|
||||
module.exports = async (ctx, next) => {
|
||||
let role;
|
||||
|
||||
if (ctx.state.user) {
|
||||
// request is already authenticated in a different way
|
||||
return next();
|
||||
}
|
||||
|
||||
if (ctx.request && ctx.request.header && ctx.request.header.authorization) {
|
||||
try {
|
||||
const { id, isAdmin = false } = await strapi.plugins[
|
||||
'users-permissions'
|
||||
].services.jwt.getToken(ctx);
|
||||
const { id } = await strapi.plugins['users-permissions'].services.jwt.getToken(ctx);
|
||||
|
||||
if (id === undefined) {
|
||||
throw new Error('Invalid token: Token did not contain required fields');
|
||||
}
|
||||
|
||||
if (isAdmin) {
|
||||
ctx.state.admin = await strapi.query('user', 'admin').findOne({ id }, []);
|
||||
} else {
|
||||
ctx.state.user = await strapi.plugins['users-permissions'].services.user.fetch({ id });
|
||||
}
|
||||
ctx.state.user = await strapi.plugins['users-permissions'].services.user.fetch({ id });
|
||||
|
||||
} catch (err) {
|
||||
return handleErrors(ctx, err, 'unauthorized');
|
||||
}
|
||||
|
||||
if (ctx.state.admin) {
|
||||
if (ctx.state.admin.blocked === true) {
|
||||
return handleErrors(
|
||||
ctx,
|
||||
'Your account has been blocked by the administrator.',
|
||||
'unauthorized'
|
||||
);
|
||||
}
|
||||
|
||||
ctx.state.user = ctx.state.admin;
|
||||
return await next();
|
||||
}
|
||||
|
||||
if (!ctx.state.user) {
|
||||
return handleErrors(ctx, 'User Not Found', 'unauthorized');
|
||||
}
|
||||
|
||||
@ -21,15 +21,15 @@ const register = async () => {
|
||||
|
||||
const login = async () => {
|
||||
const { body } = await rq({
|
||||
url: '/admin/auth/local',
|
||||
url: '/admin/login',
|
||||
method: 'POST',
|
||||
body: {
|
||||
identifier: auth.email,
|
||||
email: auth.email,
|
||||
password: auth.password,
|
||||
},
|
||||
});
|
||||
|
||||
return body;
|
||||
return body.data;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
@ -38,7 +38,7 @@ module.exports = {
|
||||
await register();
|
||||
|
||||
// login
|
||||
const { jwt } = await login();
|
||||
return jwt;
|
||||
const { token } = await login();
|
||||
return token;
|
||||
},
|
||||
};
|
||||
|
||||
@ -11,6 +11,7 @@ const createRequest = (defaults = {}) => {
|
||||
};
|
||||
|
||||
const createAuthRequest = token => {
|
||||
console.log(token);
|
||||
return createRequest({
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
|
||||
14
yarn.lock
14
yarn.lock
@ -10627,7 +10627,7 @@ jsonparse@^1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
|
||||
integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=
|
||||
|
||||
jsonwebtoken@8.5.1, jsonwebtoken@^8.1.0, jsonwebtoken@^8.2.0:
|
||||
jsonwebtoken@8.5.1, jsonwebtoken@^8.1.0:
|
||||
version "8.5.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
|
||||
integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==
|
||||
@ -13263,14 +13263,6 @@ pascalcase@^0.1.1:
|
||||
resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
|
||||
integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=
|
||||
|
||||
passport-jwt@4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/passport-jwt/-/passport-jwt-4.0.0.tgz#7f0be7ba942e28b9f5d22c2ebbb8ce96ef7cf065"
|
||||
integrity sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==
|
||||
dependencies:
|
||||
jsonwebtoken "^8.2.0"
|
||||
passport-strategy "^1.0.0"
|
||||
|
||||
passport-local@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/passport-local/-/passport-local-1.0.0.tgz#1fe63268c92e75606626437e3b906662c15ba6ee"
|
||||
@ -13278,12 +13270,12 @@ passport-local@1.0.0:
|
||||
dependencies:
|
||||
passport-strategy "1.x.x"
|
||||
|
||||
passport-strategy@1.x.x, passport-strategy@^1.0.0:
|
||||
passport-strategy@1.x.x:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
|
||||
integrity sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=
|
||||
|
||||
passport@0.4.1, passport@^0.4.0:
|
||||
passport@^0.4.0:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270"
|
||||
integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user