Skip to content

Commit

Permalink
🔐 authentication (#2533)
Browse files Browse the repository at this point in the history
* Basic smtp setup

* 🚧 WIP

* 🔐 complete authentication flow with passport

Co-authored-by: Omar Ajoue <krynble@gmail.com>
  • Loading branch information
BHesseldieck and krynble committed Dec 29, 2021
1 parent 34cba4b commit faae122
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 8 deletions.
6 changes: 0 additions & 6 deletions packages/cli/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -595,12 +595,6 @@ const config = convict({
},
},
templates: {
instanceSetup: {
doc: 'HTML template for when the instance has been set up (use full path)',
format: String,
default: '',
env: 'N8N_UM_EMAIL_TEMPLATES_SETUP',
},
invite: {
doc: 'HTML template for inviting new people (use full path)',
format: String,
Expand Down
3 changes: 3 additions & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
"@types/node": "14.17.27",
"@types/open": "^6.1.0",
"@types/parseurl": "^1.3.1",
"@types/passport-jwt": "^3.0.6",
"@types/request-promise-native": "~1.0.15",
"@types/validator": "^13.7.0",
"concurrently": "^5.1.0",
Expand Down Expand Up @@ -118,6 +119,8 @@
"nodemailer": "^6.7.1",
"oauth-1.0a": "^2.2.6",
"open": "^7.0.0",
"passport": "^0.5.0",
"passport-jwt": "^4.0.0",
"pg": "^8.3.0",
"prom-client": "^13.1.0",
"request-promise-native": "^1.0.7",
Expand Down
2 changes: 2 additions & 0 deletions packages/cli/src/Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,8 @@ class App {
const additionalData = await WorkflowExecuteAdditionalData.getBase();
if (this.isUserManagementEnabled) {
// TODO UM: test this.
// TODO: test this.
// @ts-ignore
additionalData.userId = req.body.userId;
}
const nodeTypes = NodeTypes();
Expand Down
49 changes: 49 additions & 0 deletions packages/cli/src/UserManagement/auth/jwt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// @ts-nocheck

import { ExtractJwt, Strategy } from 'passport-jwt';
import * as jwt from 'jsonwebtoken';

import { Db } from '../..';
import config = require('../../../config');

const options = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: 'abc', //config.get('jwt_key'),
};

export function useJwt(passport) {
// The JWT payload is passed into the verify callback
passport.use(
new Strategy(options, async function (jwt_payload, done) {
// We will assign the `sub` property on the JWT to the database ID of user
const user = await Db.collections.User.findOne({
id: jwt_payload.id,
email: jwt_payload.email,
});
if (!user) {
return done(null, false, { message: 'User not found' });
}
return done(null, user);
}),
);
}

export function issueJWT(user) {
const { id, email } = user;
const expiresIn = 14 * 86400000; // 14 days

const payload = {
id,
email,
};

const signedToken = jwt.sign(payload, options.secretOrKey, {
expiresIn: expiresIn / 1000 /* in seconds */,
});

return {
token: 'Bearer ' + signedToken,
expiresIn,
validTill: Date.now() + expiresIn,
};
}
40 changes: 40 additions & 0 deletions packages/cli/src/UserManagement/auth/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// @ts-nocheck

import * as express from 'express';
import * as passport from 'passport';
import { Db, ResponseHelper } from '../..';
import { User } from '../databases/entities/User';
import { issueJWT, useJwt } from './jwt';

useJwt(passport);

export function authenticationRoutes(): void {
// ----------------------------------------
// authentication middleware
// ----------------------------------------
this.app.use(passport.initialize());
this.app.use((req: express.Request, res: express.Response, next: express.NextFunction) => {
// just temp for development
if (req.url.includes('login')) {
return next();
}
// get access to this from Server.ts
// if (authIgnoreRegex.exec(req.url)) {
// return next();
// }
return passport.authenticate('jwt', { session: false })(req, res, next);
});

// ----------------------------------------
// login a user
// ----------------------------------------

this.app.get(
`/${this.restEndpoint}/login`,
ResponseHelper.send(async (req: express.Request, res: express.Response) => {
const user = await Db.collections.User!.findOne({ firstName: 'Ben' });

return issueJWT(user);
}),
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<h1>Hi there!</h1>
<p>Welcome to n8n, {{firstName}} {{lastName}}</p>
<p>Your instance is set up!</p>
<p>Use your email to login: {{email}} and the chosen password.</p>
<p>Have fun automating!</p>
8 changes: 6 additions & 2 deletions packages/cli/src/UserManagement/routes.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
/* eslint-disable import/no-cycle */
// @ts-nocheck

import * as express from 'express';
import { IDataObject } from 'n8n-workflow';
import { Db, GenericHelpers, ResponseHelper } from '..';
import { User } from '../databases/entities/User';
import { getInstance } from './email';
import { isEmailSetup } from './UserManagementHelper';

import { authenticationRoutes } from './auth/routes';

export function addRoutes(): void {
authenticationRoutes.apply(this);

// ----------------------------------------
// Create instance owner
// ----------------------------------------
Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/WorkflowRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ export class WorkflowRunner {
workflowTimeout <= 0 ? undefined : Date.now() + workflowTimeout * 1000,
);
if (data.userId) {
// @ts-ignore
additionalData.userId = data.userId;
}

Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/WorkflowRunnerProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ export class WorkflowRunnerProcess {
workflowTimeout <= 0 ? undefined : Date.now() + workflowTimeout * 1000,
);
if (this.data.userId) {
// @ts-ignore
additionalData.userId = this.data.userId;
}
additionalData.hooks = this.getProcessForwardHooks();
Expand Down

0 comments on commit faae122

Please sign in to comment.