Skip to content

Commit

Permalink
Merge pull request #29 from cabinetoffice/NTRNL-450-add-authenticatio…
Browse files Browse the repository at this point in the history
…n-middleware

Ntrnl 450 add authentication middleware
  • Loading branch information
harley-harris authored Jul 11, 2024
2 parents 40d63b9 + 6d9d13e commit 3fdb6c2
Show file tree
Hide file tree
Showing 11 changed files with 283 additions and 23 deletions.
23 changes: 14 additions & 9 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
PATH_SSL_PRIVATE_KEY=./infrastructure/host/test.key
PATH_SSL_CERTIFICATE=./infrastructure/host/test.cert

PORT=3000
NODE_ENV=development

AUTH_SIGN_IN_URL=https://cola.service.cabinetoffice.gov.uk/v2/<TEST>/login
BASE_URL=http://localhost:3000
CDN_HOST=test
NODE_SSL_ENABLED=false

COOKIE_ID_NAME=app-name
COOKIE_PARSER_SECRET=test
COOKIE_SESSION_SECRET=test
HUMAN=true
LOG_LEVEL=info
HUMAN=true
NODE_ENV=development
NODE_SSL_ENABLED=false
PATH_SSL_PRIVATE_KEY=./infrastructure/host/test.key
PATH_SSL_CERTIFICATE=./infrastructure/host/test.cert
PORT=3000
SESSION_APP_KEY=test
SESSION_ID_NAME=test
USER_POOL_CLIENT_ID=test
USER_POOL_ID=test
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ Directory Path | Description
`./.husky` | Add pre check script, includes `pre-commit` and `pre-push` checks
`./src` | Contains all TypeScript code
`./src/app.ts` | Application entry point
`./src/bin/www.ts` | Server configuration
`./src/config/index.ts` | Contains all the application's configurations
`./src/controller` | Business logic and handlers
`./src/middleware` | Middleware functions (Authentication, validation ...)
Expand All @@ -42,6 +41,31 @@ Directory Path | Description
`./docs` | Contains documentation files
Others files | Other files related to modules dependency, CI/CD, *git, dockerization, lint, test/typescript configs …


### Config variables

Some config variables relate to authentication, refer to [node-login](https://github.com/cabinetoffice/node-login) for more details about how these variables are used.

| Key | Description | Example Value |
|-----------------------------|---------------------------------------------------------------------|--------------------------------------------------------------------|
| AUTH_SIGN_IN_URL | Authentication sign in URL | `https://cola.service.cabinetoffice.gov.uk/v2/<YOUR_SERVICE>/login`|
| BASE_URL | Base application URL | `http://localhost:3000` (dev mode) |
| CDN_HOST | CDN host | `cdn_domain` |
| COOKIE_ID_NAME | The name of the COLA authentication cookie | `github-requests` |
| COOKIE_PARSER_SECRET | Secret used in validating/calculating the cookie signature | `secret` |
| COOKIE_SESSION_SECRET | Secret key for signing the session cookie | `secret` |
| HUMAN | Formatting messages form (default JSON) | `true` (Enable human formatting for log messages) |
| LOG_LEVEL | Logging levels | `info` |
| NODE_ENV | Node environment | `development` or `production` |
| NODE_SSL_ENABLED | Node SSL | `true` or `false` |
| PATH_SSL_CERTIFICATE | Path to SSL certificate | `./infrastructure/host/test.cert` |
| PATH_SSL_PRIVATE_KEY | Path to SSL private key | `./infrastructure/host/test.key` |
| PORT | Server port number | `3000` |
| SESSION_APP_KEY | Session application key | `git` |
| SESSION_ID_NAME | Session ID name | `connect.sid` |
| USER_POOL_CLIENT_ID | Client ID of an app registered with the user pool in Amazon Cognito | `secret` |
| USER_POOL_ID | ID of the user pool in Amazon Cognito | `secret` |

## ESlint

We use ESlint as both a formatter and code quality assurance. Eslint can also be setup to format on save using a VScode extension:
Expand Down
20 changes: 14 additions & 6 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,19 @@ services:
ports:
- "${PORT}:3000"
environment:
- NODE_ENV=${NODE_ENV}
- PATH_SSL_PRIVATE_KEY=${PATH_SSL_PRIVATE_KEY}
- PATH_SSL_CERTIFICATE=${PATH_SSL_CERTIFICATE}
- CDN_HOST=${CDN_HOST}
- NODE_SSL_ENABLED=${NODE_SSL_ENABLED}
- AUTH_SIGN_IN_URL=${AUTH_SIGN_IN_URL}
- BASE_URL=${BASE_URL}
- CDN_HOST=${CDN_HOST}
- COOKIE_ID_NAME=${COOKIE_ID_NAME}
- COOKIE_PARSER_SECRET=${COOKIE_PARSER_SECRET}
- COOKIE_SESSION_SECRET=${COOKIE_SESSION_SECRET}
- HUMAN=${HUMAN}
- LOG_LEVEL=${LOG_LEVEL}
- LOG_LEVEL=${LOG_LEVEL}
- NODE_ENV=${NODE_ENV}
- NODE_SSL_ENABLED=${NODE_SSL_ENABLED}
- PATH_SSL_CERTIFICATE=${PATH_SSL_CERTIFICATE}
- PATH_SSL_PRIVATE_KEY=${PATH_SSL_PRIVATE_KEY}
- SESSION_APP_KEY=${SESSION_APP_KEY}
- SESSION_ID_NAME=${SESSION_ID_NAME}
- USER_POOL_CLIENT_ID=${USER_POOL_CLIENT_ID}
- USER_POOL_ID=${USER_POOL_ID}
108 changes: 105 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"license": "MIT",
"devDependencies": {
"@types/cookie-parser": "^1.4.4",
"@types/cookie-session": "^2.0.49",
"@types/cors": "^2.8.14",
"@types/express": "^4.17.17",
"@types/jest": "^29.5.4",
Expand All @@ -40,7 +41,9 @@
},
"dependencies": {
"@co-digital/logging": "^1.0.1",
"@co-digital/login": "^1.0.4",
"cookie-parser": "^1.4.6",
"cookie-session": "^2.1.0",
"cors": "^2.8.5",
"crypto": "^1.0.1",
"express": "^4.18.2",
Expand Down
6 changes: 5 additions & 1 deletion src/app.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import express from 'express';
import cookieParser from 'cookie-parser';
import cookieSession from 'cookie-session';
import path from 'path';

import router from './routes/index';
Expand All @@ -11,14 +12,17 @@ import { errorHandler, errorNotFound } from './controller/error.controller';

import { setNonce } from './middleware/nonce.middleware';
import { configureRateLimit } from './config/rate-limit';
import { COOKIE_PARSER_SECRET, COOKIE_SESSION_SECRET } from './config/index';

const app = express();

app.disable('x-powered-by');

app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());

app.use(cookieParser(COOKIE_PARSER_SECRET));
app.use(cookieSession({ secret: COOKIE_SESSION_SECRET }));

app.use(setNonce);
configureHelmet(app);
Expand Down
4 changes: 4 additions & 0 deletions src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ export const PORT = getEnvironmentValue('PORT', '3000');
export const BASE_URL = getEnvironmentValue('BASE_URL', `http://localhost:${PORT}`);
export const CDN_HOST = getEnvironmentValue('CDN_HOST');
export const NODE_SSL_ENABLED = getEnvironmentValue('NODE_SSL_ENABLED', 'false');
export const NODE_ENV = getEnvironmentValue('NODE_ENV');

export const COOKIE_PARSER_SECRET = getEnvironmentValue('COOKIE_PARSER_SECRET');
export const COOKIE_SESSION_SECRET = getEnvironmentValue('COOKIE_SESSION_SECRET');

export const PATH_SSL_PRIVATE_KEY = getEnvironmentValue('PATH_SSL_PRIVATE_KEY', 'false');
export const PATH_SSL_CERTIFICATE = getEnvironmentValue('PATH_SSL_CERTIFICATE', 'false');
Expand Down
25 changes: 25 additions & 0 deletions src/middleware/authentication.middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { NextFunction, Request, Response } from 'express';
import { log } from '../utils/logger';
import * as config from '../config';
import { colaAuthenticationMiddleware } from '@co-digital/login';

export const authentication = (
req: Request,
res: Response,
next: NextFunction
) => {
try {

if (config.NODE_ENV === 'production') {
log.infoRequest(req, 'Authenticating through COLA...');
return colaAuthenticationMiddleware(req, res, next);
}

log.infoRequest(req, 'Skipping authentication...');
next();

} catch (err: any) {
log.errorRequest(req, err.message);
next(err);
}
};
3 changes: 2 additions & 1 deletion src/routes/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { Router } from 'express';

import { get, post } from '../controller/info.controller';
import * as config from '../config';
import { authentication } from '../middleware/authentication.middleware';

const infoRouter = Router();

infoRouter.get(config.INFO_URL, get);
infoRouter.get(config.INFO_URL, authentication, get);
infoRouter.post(config.INFO_URL, post);

export default infoRouter;
13 changes: 11 additions & 2 deletions test/setup.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
export default () => {
process.env.LOG_LEVEL = 'info';
process.env.CDN_HOST = 'test';
process.env.HUMAN = 'true';
process.env.LOG_LEVEL = 'info';
process.env.COOKIE_PARSER_SECRET = 'secret';
process.env.COOKIE_SESSION_SECRET = 'secret';
process.env.COOKIE_ID_NAME = 'secret';
process.env.USER_POOL_ID = 'secret';
process.env.USER_POOL_CLIENT_ID = 'secret';
process.env.COOKIE_ID_NAME = 'test';
process.env.AUTH_SIGN_IN_URL = 'test';
process.env.SESSION_ID_NAME = 'test';
process.env.SESSION_APP_KEY = 'test';
process.env.TEST_KEY = 'test';
process.env.CDN_HOST = 'test';
process.env.UNSANITISED_TEST_KEY = ' test ';
};
Loading

0 comments on commit 3fdb6c2

Please sign in to comment.