Compare commits

...

13 Commits

Author SHA1 Message Date
Kayne Ruse 353be4662b Bumped version number 2021-12-19 16:07:44 +00:00
Kayne Ruse cc655cd988 Merge remote-tracking branch 'refs/remotes/origin/main' 2021-12-19 16:06:30 +00:00
Kayne Ruse ec3b14e32b Removed excess logging 2021-12-19 16:06:23 +00:00
Kayne Ruse b188c46efd Merge pull request #9 from MatthewEvans91/remove-address-line
omit physical address line from validation email where no physical address provided
2021-12-20 03:04:03 +11:00
Matthew Evans ece3b0253f omit physical address line from validation email where no physical address provided 2021-12-18 18:47:44 -07:00
Kayne Ruse 062bc43f5a BUGFIX: sending account index via post validation hook 2021-12-11 11:54:13 +00:00
Kayne Ruse cc6b7bd7b4 Fixed an import/require problem 2021-12-11 10:11:56 +00:00
Kayne Ruse 9bdf3925a3 Implemented a post-validation hook 2021-12-11 09:59:57 +00:00
Kayne Ruse a299bab794 Preparing for Egg Trainer merge 2021-11-18 14:59:30 +00:00
Kayne Ruse 8460d03181 Updated package-lock.json 2021-11-17 06:14:08 +00:00
Kayne Ruse ae88f3002a Bumped node to version 16 LTS 2021-11-17 04:43:03 +00:00
Kayne Ruse f4745084c0 Updated package-lock.json 2021-11-15 22:39:48 +00:00
Kayne Ruse 02387914a8 Updated documentation 2021-08-21 22:45:15 +01:00
9 changed files with 163 additions and 142 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
docker_image: krgamestudios/auth-server
- name: Login to DockerHub
uses: docker/login-action@v1
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
+2 -2
View File
@@ -1,9 +1,9 @@
FROM node:15
FROM node:16
WORKDIR "/app"
COPY package*.json ./
COPY . /app
RUN npm install --production
COPY . /app
EXPOSE 3200
USER node
ENTRYPOINT ["bash", "-c"]
+50 -10
View File
@@ -20,9 +20,17 @@ Content-Type: application/json
}
//DOCS: Used for validating the email address above
###
//DOCS: Used for validating the email address specified above
GET /auth/validation?username=example&token=12345678
//DOCS: If the environment variable HOOK_POST_VALIDATION is set to a URL, then the server will send a GET message to that URL with the newly created account's index
GET https://{HOOK_POST_VALIDATION}?accountIndex={index}
###
//DOCS: Login after validation
POST /auth/login
@@ -33,14 +41,17 @@ Content-Type: application/json
"password": "helloworld"
}
//Result (access token's value is your authorization key below)
//DOCS: Result (access token's value is your authorization key below)
{
"accessToken": "abcde",
"refreshToken": "fghij"
}
//DOCS: Replace an expired authToken pair with these values
###
//DOCS: Replace an expired authToken pair with new values
POST /auth/token
Content-Type: application/json
@@ -48,6 +59,15 @@ Content-Type: application/json
"token": "refreshToken"
}
//DOCS: Result
{
"accessToken": "abcde",
"refreshToken": "fghij"
}
###
//DOCS: After this is called, the refresh route will no longer work
DELETE /auth/logout
@@ -58,22 +78,30 @@ Authorization: Bearer accessToken
}
###
//DOCS: Retreives the private account data, results vary
GET /auth/account
Authorization: Bearer accessToken
//Result
{
"accessToken": "abcde",
"refreshToken": "fghij"
}
###
//DOCS: Update account data, input varies, but is always JSON
//DOCS: Update account data
PATCH /auth/account
Content-Type: application/json
Authorization: Bearer accessToken
{
"password": "helloworld",
"contact": true
}
###
//DOCS: Sets the timer, account will be deleted after 2 days
DELETE /auth/account
@@ -85,6 +113,9 @@ Content-Type: application/json
}
###
//DOCS: Send the link to recover a forgotten password
POST /auth/recover
Content-Type: application/json
@@ -94,17 +125,26 @@ Content-Type: application/json
}
###
//DOCS: Redirect the link to recover a password to the front-end
GET /auth/reset?token=<token>
//Result
//DOCS: Result
301 -> ${WEB_RESET_ADDRESS}?email=<email>&token=<token>
###
//DOCS: Resets a password for the given email, correct token is required
PATCH /auth/reset?email=<email>&token=<token>
{
"password": "password"
}
###
```
+5 -3
View File
@@ -30,6 +30,7 @@ const question = (prompt, def = null) => {
//project configuration
const appName = await question('App Name', 'auth');
const appWebAddress = await question('Web Addr', `${appName}.example.com`);
const postValidationHook = await question('Post Validation Hook', '');
const resetAddress = await question('Reset Addr', `example.com/reset`);
const appPort = await question('App Port', '3200');
@@ -70,6 +71,7 @@ services:
environment:
- WEB_PROTOCOL=https
- WEB_ADDRESS=${appWebAddress}
- HOOK_POST_VALIDATION=${postValidationHook}
- WEB_RESET_ADDRESS=${resetAddress}
- WEB_PORT=${appPort}
- DB_HOSTNAME=database
@@ -85,7 +87,7 @@ services:
- ADMIN_DEFAULT_PASSWORD=${appDefaultPass}
- SECRET_ACCESS=${appSecretAccess}
- SECRET_REFRESH=${appSecretRefresh}
networks:
networks:
- app-network
depends_on:
- database
@@ -96,7 +98,7 @@ services:
MYSQL_USER: ${appDBUser}
MYSQL_PASSWORD: ${appDBPass}
MYSQL_ROOT_PASSWORD: ${dbRootPass}
networks:
networks:
- app-network
volumes:
- ./mysql:/var/lib/mysql
@@ -128,7 +130,7 @@ networks:
`;
const dockerfile = `
FROM node:15
FROM node:16
WORKDIR "/app"
COPY package*.json ./
RUN npm install --production
+81 -112
View File
@@ -1,11 +1,12 @@
{
"name": "auth-server",
"version": "1.4.3",
"version": "1.4.9",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "1.4.3",
"name": "auth-server",
"version": "1.4.9",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
@@ -15,6 +16,7 @@
"jsonwebtoken": "^8.5.1",
"mariadb": "^2.5.4",
"node-cron": "^2.0.3",
"node-fetch": "^2.6.6",
"nodemailer": "^6.6.3",
"sequelize": "^6.6.5"
},
@@ -72,68 +74,18 @@
}
},
"node_modules/ansi-align": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
"integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
"integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
"dev": true,
"dependencies": {
"string-width": "^3.0.0"
}
},
"node_modules/ansi-align/node_modules/ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/ansi-align/node_modules/emoji-regex": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
"dev": true
},
"node_modules/ansi-align/node_modules/is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true,
"engines": {
"node": ">=4"
}
},
"node_modules/ansi-align/node_modules/string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"dev": true,
"dependencies": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/ansi-align/node_modules/strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"dev": true,
"dependencies": {
"ansi-regex": "^4.1.0"
},
"engines": {
"node": ">=6"
"string-width": "^4.1.0"
}
},
"node_modules/ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": {
"node": ">=8"
@@ -1329,6 +1281,17 @@
"node": ">=6.0.0"
}
},
"node_modules/node-fetch": {
"version": "2.6.6",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz",
"integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
}
},
"node_modules/nodemailer": {
"version": "6.6.3",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.3.tgz",
@@ -1959,6 +1922,11 @@
"nodetouch": "bin/nodetouch.js"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
},
"node_modules/type-fest": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
@@ -2079,9 +2047,9 @@
}
},
"node_modules/validator": {
"version": "13.6.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.6.0.tgz",
"integrity": "sha512-gVgKbdbHgtxpRyR8K0O6oFZPhhB5tT1jeEHZR0Znr9Svg03U0+r9DXWMrnRAB+HtCStDQKlaIZm42tVsVjqtjg==",
"version": "13.7.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz",
"integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==",
"engines": {
"node": ">= 0.10"
}
@@ -2094,6 +2062,20 @@
"node": ">= 0.8"
}
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/widest-line": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
@@ -2189,58 +2171,18 @@
}
},
"ansi-align": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
"integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
"integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
"dev": true,
"requires": {
"string-width": "^3.0.0"
},
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
},
"emoji-regex": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
"dev": true
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"dev": true,
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
}
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"dev": true,
"requires": {
"ansi-regex": "^4.1.0"
}
}
"string-width": "^4.1.0"
}
},
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true
},
"ansi-styles": {
@@ -3181,6 +3123,14 @@
"tz-offset": "0.0.1"
}
},
"node-fetch": {
"version": "2.6.6",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz",
"integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==",
"requires": {
"whatwg-url": "^5.0.0"
}
},
"nodemailer": {
"version": "6.6.3",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.3.tgz",
@@ -3650,6 +3600,11 @@
"nopt": "~1.0.10"
}
},
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
},
"type-fest": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
@@ -3743,15 +3698,29 @@
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
},
"validator": {
"version": "13.6.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.6.0.tgz",
"integrity": "sha512-gVgKbdbHgtxpRyR8K0O6oFZPhhB5tT1jeEHZR0Znr9Svg03U0+r9DXWMrnRAB+HtCStDQKlaIZm42tVsVjqtjg=="
"version": "13.7.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz",
"integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw=="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
},
"whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"widest-line": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
+2 -1
View File
@@ -1,6 +1,6 @@
{
"name": "auth-server",
"version": "1.4.3",
"version": "1.4.9",
"description": "An API centric auth server. Uses Sequelize and mariaDB by default.",
"main": "server/server.js",
"scripts": {
@@ -26,6 +26,7 @@
"jsonwebtoken": "^8.5.1",
"mariadb": "^2.5.4",
"node-cron": "^2.0.3",
"node-fetch": "^2.6.6",
"nodemailer": "^6.6.3",
"sequelize": "^6.6.5"
},
+6 -9
View File
@@ -52,9 +52,6 @@ const validateDetails = async (body) => {
return 'Invalid username';
}
//check for existing (banned)
//TODO: re-add banned email checks
//check for existing email
const emailRecord = await accounts.findOne({
where: {
@@ -107,12 +104,12 @@ const registerPendingSignup = async (body, hash, token) => {
const sendValidationEmail = async (email, username, token) => {
const addr = `${process.env.WEB_PROTOCOL}://${process.env.WEB_ADDRESS}/auth/validation?username=${username}&token=${token}`;
const msg = `Hello ${username}!
Please visit the following link to validate your account: ${addr}
You can contact us directly at our physical mailing address here: ${process.env.MAIL_PHYSICAL}
`;
const msg =
`Hello ${username}!\n\n` +
`Please visit the following link to validate your account: ${addr}\n` +
(process.env.MAIL_PHYSICAL
? `\nYou can contact us directly at our physical mailing address here: ${process.env.MAIL_PHYSICAL}\n`
: ``);
let transporter, info;
+14 -2
View File
@@ -1,4 +1,5 @@
const { pendingSignups, accounts } = require('../database/models');
const fetch = require('node-fetch');
//auth/validation
const route = async (req, res) => {
@@ -19,7 +20,7 @@ const route = async (req, res) => {
}
//move data to the accounts table
accounts.create({
const account = await accounts.create({
email: info.email,
username: info.username,
hash: info.hash,
@@ -29,12 +30,23 @@ const route = async (req, res) => {
//delete the pending signup
pendingSignups.destroy({
where: {
username: req.query.username || ''
username: info.username || ''
}
});
//finally
res.status(200).send('Validation succeeded!');
//post-validation hook
if (process.env.HOOK_POST_VALIDATION) {
const probe = await fetch(`https://${process.env.HOOK_POST_VALIDATION}?accountIndex=${account.index}`);
if (!probe.ok) {
console.error('Could not probe the post validation hook');
}
//discard the result
}
};
module.exports = route;
+2 -2
View File
@@ -12,8 +12,8 @@ module.exports = (index, email, username, type, admin, mod) => {
mod,
};
const accessToken = jwt.sign(content, process.env.SECRET_ACCESS, { expiresIn: '10m' });
const refreshToken = jwt.sign(content, process.env.SECRET_REFRESH, { expiresIn: '30d' });
const accessToken = jwt.sign(content, process.env.SECRET_ACCESS, { expiresIn: '10m', issuer: 'auth' });
const refreshToken = jwt.sign(content, process.env.SECRET_REFRESH, { expiresIn: '30d', issuer: 'auth' });
tokens.create({ token: refreshToken, email: email });