diff --git a/.env.example b/.env.example index b81754b..9bf5dc8 100644 --- a/.env.example +++ b/.env.example @@ -5,8 +5,14 @@ PORT=4000 # through API_KEY authentication calling /auth endpoint. # Will require SECRET_KEY variable definition as well. API_KEY="changeme" +# The text file where is stored the API KEY. +# This is an alternative of API_KEY. +API_KEY_FILE= # The SECRET KEY used by JWT. It should never be shared. SECRET_KEY="changemetoo" +# The text file where is stored the SECRET KEY. +# This is an alternative of SECRET_KEY. +SECRET_KEY_FILE= # The fullpath to the folder containing template files. # Default is relative to ../repository TEMPLATE_REPOSITORY= diff --git a/Dockerfile b/Dockerfile index 8cf309d..8c3752e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,9 @@ ENV NODE_ENV=production ENV TEMPLATE_REPOSITORY=/data/repository ENV PORT=4000 ENV API_KEY= -ENV SECRET= +ENV API_KEY_FILE= +ENV SECRET_KEY= +ENV SECRET_KEY_FILE= ENV LOGGING_TYPE=console ENV LOGGING_LEVEL=http ENV LOGGING_DIRECTORY=/data/logs diff --git a/README.md b/README.md index 9b796c3..8d9caa8 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ If using docker, define variables when creating the container with `-e VARIABLE= # Use By default, the server can be reached on http://localhost:4000/. -The REST API is documented with an embedded Swagger UI on http://localhost:4000/api-docs/ and also available [on SwaggerHub](https://app.swaggerhub.com/apis/LEOSAC/CardPrintingWorker/1.0.0#/). +The REST API is documented with an embedded Swagger UI on http://localhost:4000/swagger/ and also available [on SwaggerHub](https://app.swaggerhub.com/apis/LEOSAC/CardPrintingWorker/1.0.0#/). JSON template samples can be found on [repository](https://github.com/leosac/card-printing-worker/tree/master/repository) folder. Such templates have to follow [js-cardrendering](https://github.com/leosac/js-cardrendering) format and can easily be created with [js-cardeditor](https://github.com/leosac/js-cardeditor). diff --git a/src/services/AuthService.js b/src/services/AuthService.js index fe545d9..c2b9ae0 100644 --- a/src/services/AuthService.js +++ b/src/services/AuthService.js @@ -1,3 +1,4 @@ +const fs = require('fs'); const jwt = require("jsonwebtoken"); class AuthService { @@ -6,30 +7,59 @@ class AuthService { this.logger = container.get('logger'); } + static apikey = undefined; + static secretkey = undefined; + + isJWTSetup() { + const isSetup = !((!process.env.API_KEY && !process.env.API_KEY_FILE) || (!process.env.SECRET_KEY && !process.env.SECRET_KEY_FILE)); + if (isSetup) { + AuthService.cacheSecrets(); + } + return isSetup; + } + + static cacheSecrets() { + if (!AuthService.apikey) { + if (process.env.API_KEY) { + AuthService.apikey = process.env.API_KEY; + } else if (process.env.API_KEY_FILE) { + AuthService.apikey = fs.readFileSync(process.env.API_KEY_FILE, { encoding: 'utf8' }); + } + } + if (!AuthService.secretkey) { + if (process.env.SECRET_KEY) { + AuthService.secretkey = process.env.SECRET_KEY; + } else if (process.env.SECRET_KEY_FILE) { + AuthService.secretkey = fs.readFileSync(process.env.SECRET_KEY_FILE, { encoding: 'utf8' }); + } + } + } + authenticate(application, apikey, context) { - if (!process.env.API_KEY || !process.env.SECRET_KEY) { + if (!this.isJWTSetup()) { + this.logger.error("Authentication is not enabled. SECRET_KEY and API_KEY variables are required."); throw new Error("Authentication is not enabled. SECRET_KEY and API_KEY variables are required."); } - if (apikey !== process.env.API_KEY) { + if (apikey !== AuthService.apikey) { this.logger.error("Authentication failed. Wrong API_KEY."); return undefined; } return jwt.sign( { application: application, context: context }, - process.env.SECRET_KEY, + AuthService.secretkey, { expiresIn: "1h" } ); } authenticateToken(req, res, next) { - if (!process.env.API_KEY || !process.env.SECRET_KEY) { + if (this.isJWTSetup()) { next(); } else { const authHeader = req.headers['authorization'] const token = authHeader && authHeader.split(' ')[1] if (token == null) return res.sendStatus(401) - jwt.verify(token, process.env.SECRET_KEY, (err, client) => { + jwt.verify(token, AuthService.secretkey, (err, client) => { if (err) { this.logger.error(err); return res.sendStatus(403); @@ -41,7 +71,7 @@ class AuthService { } checkGlobalPermission(req, res, next) { - if (!process.env.API_KEY || !process.env.SECRET_KEY) { + if (!this.isJWTSetup()) { next(); } else { // authenticateToken should have been called first @@ -59,7 +89,7 @@ class AuthService { } checkQueuePermission(req, item) { - if (!process.env.API_KEY || !process.env.SECRET_KEY) { + if (!this.isJWTSetup()) { return true; } else { // authenticateToken should have been called first