mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-12 05:17:28 -08:00
Merge pull request #3019 from n8n-io/n8n-3171-add-authentication-handler
⚡ Add authentication handler - public api
This commit is contained in:
commit
53d88b33ce
|
@ -9,6 +9,9 @@ import path = require('path');
|
|||
|
||||
import express = require('express');
|
||||
|
||||
import { OpenAPIV3 } from 'express-openapi-validator/dist/framework/types';
|
||||
import { Db } from '../..';
|
||||
|
||||
export interface N8nApp {
|
||||
app: Application;
|
||||
}
|
||||
|
@ -23,6 +26,29 @@ export const getRoutes = (): express.Router => {
|
|||
operationHandlers: path.join(__dirname),
|
||||
validateRequests: true, // (default)
|
||||
validateApiSpec: true,
|
||||
validateSecurity: {
|
||||
handlers: {
|
||||
ApiKeyAuth: async (req, scopes, schema: OpenAPIV3.ApiKeySecurityScheme) => {
|
||||
|
||||
const apiKey = req.headers[schema.name.toLowerCase()];
|
||||
|
||||
const user = await Db.collections.User!.find({
|
||||
where: {
|
||||
apiKey,
|
||||
},
|
||||
relations: ['globalRole'],
|
||||
});
|
||||
|
||||
if (!user.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
req.user = user[0];
|
||||
|
||||
return true;
|
||||
},
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
//add error handler
|
||||
|
|
|
@ -7,7 +7,6 @@ export = {
|
|||
res.json({ success: true});
|
||||
},
|
||||
deleteUser: async (req: UserRequest.Delete, res: express.Response) => {
|
||||
console.log('aja')
|
||||
res.json({ success: true });
|
||||
},
|
||||
getUser: async (req: UserRequest.Get, res: express.Response) => {
|
||||
|
|
|
@ -57,7 +57,7 @@ import * as clientOAuth1 from 'oauth-1.0a';
|
|||
import { RequestOptions } from 'oauth-1.0a';
|
||||
import * as csrf from 'csrf';
|
||||
import * as requestPromise from 'request-promise-native';
|
||||
import { createHmac } from 'crypto';
|
||||
import { createHmac, randomBytes } from 'crypto';
|
||||
// IMPORTANT! Do not switch to anther bcrypt library unless really necessary and
|
||||
// tested with all possible systems like Windows, Alpine on ARM, FreeBSD, ...
|
||||
import { compare } from 'bcryptjs';
|
||||
|
@ -564,6 +564,24 @@ class App {
|
|||
// Public API
|
||||
// ----------------------------------------
|
||||
|
||||
|
||||
//test routes to create/regenerate/delete token
|
||||
//NOTE: Only works with admin role
|
||||
//This should be within the user's management user scope
|
||||
this.app.post('/token', async (req: express.Request, res: express.Response) => {
|
||||
const ramdonToken = randomBytes(20).toString('hex');
|
||||
//@ts-ignore
|
||||
await Db.collections.User!.update({ globalRole: 1 }, { apiKey: ramdonToken });
|
||||
return ResponseHelper.sendSuccessResponse(res, { token: ramdonToken }, true, 200);
|
||||
});
|
||||
|
||||
this.app.delete('/token', async (req: express.Request, res: express.Response) => {
|
||||
//@ts-ignore
|
||||
await Db.collections.User!.update({ globalRole: 1 }, { apiKey: null });
|
||||
return ResponseHelper.sendSuccessResponse(res, {}, true, 204);
|
||||
});
|
||||
|
||||
|
||||
this.app.use(`/${this.publicApiEndpoint}`, publicApiv1Routes.getRoutes());
|
||||
|
||||
// Parse cookies for easier access
|
||||
|
|
|
@ -6,7 +6,7 @@ import { Response } from 'express';
|
|||
import { createHash } from 'crypto';
|
||||
import { Db } from '../..';
|
||||
import { AUTH_COOKIE_NAME } from '../../constants';
|
||||
import { JwtToken, JwtPayload } from '../Interfaces';
|
||||
import { JwtPayload, JwtToken } from '../Interfaces';
|
||||
import { User } from '../../databases/entities/User';
|
||||
import config = require('../../../config');
|
||||
|
||||
|
|
|
@ -124,6 +124,9 @@ export class User {
|
|||
this.updatedAt = new Date();
|
||||
}
|
||||
|
||||
@Column({ type: String, nullable: true })
|
||||
apiKey?: string | null;
|
||||
|
||||
/**
|
||||
* Whether the user is pending setup completion.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import {MigrationInterface, QueryRunner} from 'typeorm';
|
||||
import * as config from '../../../../config';
|
||||
|
||||
export class AddAPIKeyColumn1647888658687 implements MigrationInterface {
|
||||
name = 'AddAPIKeyColumn1647888658687';
|
||||
|
||||
async up(queryRunner: QueryRunner): Promise<void> {
|
||||
const tablePrefix = config.get('database.tablePrefix');
|
||||
await queryRunner.query(`ALTER TABLE "${tablePrefix}user" ADD apiKey varchar`);
|
||||
}
|
||||
|
||||
async down(queryRunner: QueryRunner): Promise<void> {
|
||||
const tablePrefix = config.get('database.tablePrefix');
|
||||
await queryRunner.query(`ALTER TABLE "${tablePrefix}user" RENAME TO "temporary_user"`);
|
||||
await queryRunner.query(`CREATE TABLE "${tablePrefix}user" ("id" varchar PRIMARY KEY NOT NULL, "email" varchar(255), "firstName" varchar(32), "lastName" varchar(32), "password" varchar, "resetPasswordToken" varchar, "resetPasswordTokenExpiration" integer DEFAULT (NULL), "personalizationAnswers" text, "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "updatedAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "globalRoleId" integer NOT NULL, CONSTRAINT "FK_f0609be844f9200ff4365b1bb3d" FOREIGN KEY ("globalRoleId") REFERENCES "role" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
|
||||
await queryRunner.query(`INSERT INTO "${tablePrefix}user"("id", "email", "firstName", "lastName", "password", "resetPasswordToken", "resetPasswordTokenExpiration", "personalizationAnswers", "createdAt", "updatedAt", "globalRoleId") SELECT "id", "email", "firstName", "lastName", "password", "resetPasswordToken", "resetPasswordTokenExpiration", "personalizationAnswers", "createdAt", "updatedAt", "globalRoleId" FROM "temporary_user"`);
|
||||
await queryRunner.query(`DROP TABLE "temporary_user"`);
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ import { AddWaitColumn1621707690587 } from './1621707690587-AddWaitColumn';
|
|||
import { UpdateWorkflowCredentials1630330987096 } from './1630330987096-UpdateWorkflowCredentials';
|
||||
import { AddExecutionEntityIndexes1644421939510 } from './1644421939510-AddExecutionEntityIndexes';
|
||||
import { CreateUserManagement1646992772331 } from './1646992772331-CreateUserManagement';
|
||||
import { AddAPIKeyColumn1647888658687 } from './1647888658687-AddAPIKeyColumn';
|
||||
|
||||
const sqliteMigrations = [
|
||||
InitialMigration1588102412422,
|
||||
|
@ -24,6 +25,7 @@ const sqliteMigrations = [
|
|||
UpdateWorkflowCredentials1630330987096,
|
||||
AddExecutionEntityIndexes1644421939510,
|
||||
CreateUserManagement1646992772331,
|
||||
AddAPIKeyColumn1647888658687,
|
||||
];
|
||||
|
||||
export { sqliteMigrations };
|
||||
|
|
Loading…
Reference in a new issue