From a11683cc0a1fa1072852ab6a3e8ce971e01fed55 Mon Sep 17 00:00:00 2001 From: David Vo Date: Sat, 12 Oct 2019 17:26:21 +1100 Subject: [PATCH 1/2] Use passport for authentication --- package-lock.json | 740 +++++------------------------- package.json | 9 +- src/api/token/token.controller.ts | 22 +- src/core/auth/auth.guard.ts | 40 -- src/core/auth/auth.module.ts | 20 +- src/core/auth/auth.service.ts | 22 +- src/core/auth/index.ts | 4 +- src/core/auth/jwt.strategy.ts | 19 + src/core/auth/local.strategy.ts | 18 + 9 files changed, 201 insertions(+), 693 deletions(-) delete mode 100644 src/core/auth/auth.guard.ts create mode 100644 src/core/auth/jwt.strategy.ts create mode 100644 src/core/auth/local.strategy.ts diff --git a/package-lock.json b/package-lock.json index 1943aff..78bb677 100644 --- a/package-lock.json +++ b/package-lock.json @@ -77,6 +77,43 @@ "uuid": "3.3.3" } }, + "@nestjs/jwt": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-6.1.1.tgz", + "integrity": "sha512-XZEYC+p69N+Accktjho0B98TkwAKCZNt91+t08eukw7Gwk6FvfJB+aBzHCmQEaWUiAOpAo4eObgac86P12XOkw==", + "requires": { + "@types/jsonwebtoken": "7.2.8", + "jsonwebtoken": "8.4.0" + }, + "dependencies": { + "jsonwebtoken": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.4.0.tgz", + "integrity": "sha512-coyXjRTCy0pw5WYBpMvWOMN+Kjaik2MwTUIq9cna/W7NpO9E+iYbumZONAz3hcr+tXFJECoQVrtmIoC3Oz0gvg==", + "requires": { + "jws": "^3.1.5", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "@nestjs/passport": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-6.1.0.tgz", + "integrity": "sha512-V4KdtFFLsdZQ/HlIECpiK6byzGz57Y12TAc+Iatykk8jWuVFE1jq8RJbpTfB0zG0PTfcGm9crQ6Ut2Rwdmis4Q==" + }, "@nestjs/platform-express": { "version": "6.8.3", "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-6.8.3.tgz", @@ -294,13 +331,6 @@ "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", "requires": { "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "12.7.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz", - "integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ==" - } } }, "@types/body-parser": { @@ -310,13 +340,6 @@ "requires": { "@types/connect": "*", "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "12.7.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz", - "integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ==" - } } }, "@types/connect": { @@ -325,13 +348,6 @@ "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==", "requires": { "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "12.7.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz", - "integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ==" - } } }, "@types/cookies": { @@ -343,13 +359,6 @@ "@types/express": "*", "@types/keygrip": "*", "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "12.7.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz", - "integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ==" - } } }, "@types/cors": { @@ -382,13 +391,6 @@ "requires": { "@types/node": "*", "@types/range-parser": "*" - }, - "dependencies": { - "@types/node": { - "version": "12.7.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz", - "integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ==" - } } }, "@types/fs-capacitor": { @@ -397,13 +399,6 @@ "integrity": "sha512-FKVPOCFbhCvZxpVAMhdBdTfVfXUpsh15wFHgqOKxh9N9vzWZVuWCSijZ5T4U34XYNnuj2oduh6xcs1i+LPI+BQ==", "requires": { "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "12.7.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz", - "integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ==" - } } }, "@types/glob": { @@ -414,13 +409,6 @@ "@types/events": "*", "@types/minimatch": "*", "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "12.7.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz", - "integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ==" - } } }, "@types/graphql": { @@ -448,7 +436,6 @@ "version": "7.2.8", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-7.2.8.tgz", "integrity": "sha512-XENN3YzEB8D6TiUww0O8SRznzy1v+77lH7UmuN54xq/IHIsyWjWOzZuFFTtoiRuaE782uAoRwBe/wwow+vQXZw==", - "dev": true, "requires": { "@types/node": "*" } @@ -469,13 +456,6 @@ "@types/keygrip": "*", "@types/koa-compose": "*", "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "12.7.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz", - "integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ==" - } } }, "@types/koa-compose": { @@ -512,6 +492,47 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.21.tgz", "integrity": "sha512-nuFlRdBiqbF+PJIEVxm2jLFcQWN7q7iWEJGsBV4n7v1dbI9qXB8im2pMMKMCUZe092sQb5SQft2DHfuQGK5hqQ==" }, + "@types/passport": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.1.tgz", + "integrity": "sha512-oK87JjN8i8kmqb0RN0sCUB/ZjrWf3b8U45eAzZVy1ssYYgBrMOuALmvoqp7MglsilXAjxum+LS29VQqeQx6ddA==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, + "@types/passport-jwt": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-3.0.2.tgz", + "integrity": "sha512-eUbpjmmLUbRKulDeR1y1G3t7uVfXRhTP3/TrtVS4F7s8AzvDPXr9DdHNWwQfx/KD2Mfos5UokqnpCjtp5Z/slg==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/jsonwebtoken": "*", + "@types/passport-strategy": "*" + } + }, + "@types/passport-local": { + "version": "1.0.33", + "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.33.tgz", + "integrity": "sha512-+rn6ZIxje0jZ2+DAiWFI8vGG7ZFKB0hXx2cUdMmudSWsigSq6ES7Emso46r4HJk0qCgrZVfI8sJiM7HIYf4SbA==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-strategy": "*" + } + }, + "@types/passport-strategy": { + "version": "0.2.35", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.35.tgz", + "integrity": "sha512-o5D19Jy2XPFoX2rKApykY15et3Apgax00RRLf0RUotPDUsYrQa7x4howLYr9El2mlUApHmCMv5CZ1IXqKFQ2+g==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/passport": "*" + } + }, "@types/range-parser": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", @@ -564,13 +585,6 @@ "integrity": "sha512-yBTM0P05Tx9iXGq00BbJPo37ox68R5vaGTXivs6RGh/BQ6QP5zqZDGWdAO6JbRE/iR1l80xeGAwCQS2nMV9S/w==", "requires": { "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "12.7.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz", - "integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ==" - } } }, "@wry/equality": { @@ -1276,7 +1290,6 @@ "requires": { "anymatch": "^3.1.0", "braces": "^3.0.2", - "fsevents": "^2.0.6", "glob-parent": "^5.0.0", "is-binary-path": "^2.1.0", "is-glob": "^4.0.1", @@ -2283,12 +2296,6 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "fsevents": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.0.tgz", - "integrity": "sha512-+iXhW3LuDQsno8dOIrCIT/CBjeBWuP7PXe8w9shnj9Lebny/Gx1ZjVBYwexLz36Ri2jKuXMNpV6CYNh8lHHgrQ==", - "optional": true - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -3553,7 +3560,6 @@ "anymatch": "^2.0.0", "async-each": "^1.0.1", "braces": "^2.3.2", - "fsevents": "^1.2.7", "glob-parent": "^3.1.0", "inherits": "^2.0.3", "is-binary-path": "^1.0.0", @@ -3587,554 +3593,6 @@ } } }, - "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true - } - } - }, "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", @@ -4485,6 +3943,37 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, + "passport": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.0.tgz", + "integrity": "sha1-xQlWkTR71a07XhgCOMORTRbwWBE=", + "requires": { + "passport-strategy": "1.x.x", + "pause": "0.0.1" + } + }, + "passport-jwt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.0.tgz", + "integrity": "sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==", + "requires": { + "jsonwebtoken": "^8.2.0", + "passport-strategy": "^1.0.0" + } + }, + "passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", + "requires": { + "passport-strategy": "1.x.x" + } + }, + "passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" + }, "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", @@ -4523,6 +4012,11 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" + }, "pg": { "version": "7.12.1", "resolved": "https://registry.npmjs.org/pg/-/pg-7.12.1.tgz", @@ -5658,12 +5152,6 @@ "tslib": "^1.10.0" }, "dependencies": { - "@types/node": { - "version": "12.7.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz", - "integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ==", - "optional": true - }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", diff --git a/package.json b/package.json index f8b4efd..8e395e5 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,8 @@ "dependencies": { "@nestjs/common": "^6.5.3", "@nestjs/core": "^6.5.3", + "@nestjs/jwt": "^6.1.1", + "@nestjs/passport": "^6.1.0", "@nestjs/platform-express": "^6.5.3", "@nestjs/platform-socket.io": "^6.5.3", "@nestjs/swagger": "^3.1.0", @@ -33,10 +35,12 @@ "class-transformer-validator": "^0.8.0", "class-validator": "^0.10.1", "express": "^4.17.1", - "jsonwebtoken": "^8.5.1", "lodash": "^4.17.15", "mysql": "^2.17.1", "nest-raven": "^5.0.0", + "passport": "^0.4.0", + "passport-jwt": "^4.0.0", + "passport-local": "^1.0.0", "pg": "^7.12.1", "reflect-metadata": "^0.1.12", "rxjs": "^6.5.2", @@ -44,9 +48,10 @@ }, "devDependencies": { "@types/express": "^4.17.1", - "@types/jsonwebtoken": "^7.2.8", "@types/lodash": "^4.14.137", "@types/node": "^10.14.15", + "@types/passport-jwt": "^3.0.2", + "@types/passport-local": "^1.0.33", "@types/socket.io": "^1.4.40", "nodemon": "^1.19.1", "ts-node": "^4.1.0", diff --git a/src/api/token/token.controller.ts b/src/api/token/token.controller.ts index 9e356b0..39acd93 100644 --- a/src/api/token/token.controller.ts +++ b/src/api/token/token.controller.ts @@ -1,11 +1,11 @@ +import { Controller, Post, UseGuards } from "@nestjs/common"; +import { AuthGuard } from "@nestjs/passport"; import { - Body, - Controller, - Post, - UnauthorizedException, - ValidationPipe, -} from "@nestjs/common"; -import { ApiOperation, ApiResponse, ApiUseTags } from "@nestjs/swagger"; + ApiImplicitBody, + ApiOperation, + ApiResponse, + ApiUseTags, +} from "@nestjs/swagger"; import { AuthService } from "../../core"; @@ -17,6 +17,7 @@ import { TokenResource } from "./token.resource"; export class TokenController { constructor(private readonly authService: AuthService) {} + @UseGuards(AuthGuard("local")) @Post() @ApiOperation({ title: "Retrieve a token", @@ -27,11 +28,8 @@ export class TokenController { status: 200, type: TokenResource, }) - public auth(@Body(new ValidationPipe()) creds: CredsDto): TokenResource { - if (!this.authService.verifyCreds(creds.user, creds.pass)) { - throw new UnauthorizedException("Incorrect login details"); - } - + @ApiImplicitBody({ name: "CredsDto", type: CredsDto }) + public auth(): TokenResource { return { token: this.authService.getToken() }; } } diff --git a/src/core/auth/auth.guard.ts b/src/core/auth/auth.guard.ts deleted file mode 100644 index 4be2d6d..0000000 --- a/src/core/auth/auth.guard.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { - CanActivate, - ExecutionContext, - Injectable, - UnauthorizedException, -} from "@nestjs/common"; -import { Request } from "express"; - -import { AuthService } from "./auth.service"; - -@Injectable() -export class AuthGuard implements CanActivate { - constructor(protected readonly authService: AuthService) {} - - public canActivate(context: ExecutionContext): boolean { - const request = context.switchToHttp().getRequest(); - const result = this.authService.verifyToken(this.getToken(request)); - if (!result) { - throw new UnauthorizedException("Authorization token is invalid"); - } - - return true; - } - - public getToken(req: Request): string { - const bearerAuth = req.get("Authorization"); - - if (!bearerAuth) { - throw new UnauthorizedException("Authorization header is missing"); - } - - if (!bearerAuth.startsWith("Bearer ")) { - throw new UnauthorizedException( - "Bearer prefix is missing from Authorization header.", - ); - } - - return bearerAuth.slice(7); - } -} diff --git a/src/core/auth/auth.module.ts b/src/core/auth/auth.module.ts index f1fc39c..6ba85a1 100644 --- a/src/core/auth/auth.module.ts +++ b/src/core/auth/auth.module.ts @@ -1,9 +1,23 @@ import { Module } from "@nestjs/common"; -import { AuthGuard } from "./auth.guard"; +import { JwtModule } from "@nestjs/jwt"; +import { PassportModule } from "@nestjs/passport"; + import { AuthService } from "./auth.service"; +import { JwtStrategy } from "./jwt.strategy"; +import { LocalStrategy } from "./local.strategy"; + +// tslint:disable-next-line: no-var-requires +const config = require("../../../config.json"); @Module({ - exports: [AuthService, AuthGuard], - providers: [AuthService, AuthGuard], + imports: [ + PassportModule, + JwtModule.register({ + secret: config.jwt.secret, + signOptions: { expiresIn: config.jwt.duration }, + }) + ], + exports: [AuthService], + providers: [AuthService, LocalStrategy, JwtStrategy], }) export class AuthModule {} diff --git a/src/core/auth/auth.service.ts b/src/core/auth/auth.service.ts index 51189dd..faff11c 100644 --- a/src/core/auth/auth.service.ts +++ b/src/core/auth/auth.service.ts @@ -1,13 +1,19 @@ import { Injectable } from "@nestjs/common"; -import { sign, verify } from "jsonwebtoken"; - -// tslint:disable-next-line: no-var-requires -const config = require("../../../config.json"); +import { JwtService } from "@nestjs/jwt"; @Injectable() export class AuthService { + private readonly user: string; + private readonly pass: string; + + constructor(private readonly jwtService: JwtService) { + const config = require("../../../config.json"); + this.user = config.api.user; + this.pass = config.api.pass; + } + public verifyCreds(username: string, password: string): boolean { - if (username != config.api.user || password != config.api.pass) { + if (username != this.user || password != this.pass) { return false; } @@ -16,7 +22,7 @@ export class AuthService { public verifyToken(token: string): boolean { try { - verify(token, config.jwt.secret); + this.jwtService.verify(token); return true; } catch (err) { return false; @@ -24,8 +30,6 @@ export class AuthService { } public getToken(): string { - return sign({ user: config.api.user }, config.jwt.secret, { - expiresIn: config.jwt.duration, - }); + return this.jwtService.sign({ user: this.user }); } } diff --git a/src/core/auth/index.ts b/src/core/auth/index.ts index 67721e1..ccfdff8 100644 --- a/src/core/auth/index.ts +++ b/src/core/auth/index.ts @@ -1,2 +1,4 @@ +import { AuthGuard as PassportAuthGuard } from "@nestjs/passport"; export { AuthService } from "./auth.service"; -export { AuthGuard } from "./auth.guard"; + +export const AuthGuard = PassportAuthGuard("jwt"); diff --git a/src/core/auth/jwt.strategy.ts b/src/core/auth/jwt.strategy.ts new file mode 100644 index 0000000..dcc2ea8 --- /dev/null +++ b/src/core/auth/jwt.strategy.ts @@ -0,0 +1,19 @@ +import { Injectable } from "@nestjs/common"; +import { PassportStrategy } from "@nestjs/passport"; +import { ExtractJwt, Strategy } from "passport-jwt"; + +@Injectable() +export class JwtStrategy extends PassportStrategy(Strategy) { + constructor() { + const config = require("../../../config.json"); + super({ + jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), + ignoreExpiration: false, + secretOrKey: config.jwt.secret, + }); + } + + protected validate(payload: any) { + return { user: payload.user }; + } +} diff --git a/src/core/auth/local.strategy.ts b/src/core/auth/local.strategy.ts new file mode 100644 index 0000000..3b4f340 --- /dev/null +++ b/src/core/auth/local.strategy.ts @@ -0,0 +1,18 @@ +import { Injectable, UnauthorizedException } from "@nestjs/common"; +import { PassportStrategy } from "@nestjs/passport"; +import { Strategy } from "passport-local"; +import { AuthService } from "./auth.service"; + +@Injectable() +export class LocalStrategy extends PassportStrategy(Strategy) { + constructor(private readonly authService: AuthService) { + super({ usernameField: "user", passwordField: "pass" }); + } + + protected validate(username: string, password: string) { + if (!this.authService.verifyCreds(username, password)) { + throw new UnauthorizedException(); + } + return { user: username }; + } +} From 80443762d64e889177be3b66634749ff8d6cdcf4 Mon Sep 17 00:00:00 2001 From: David Vo Date: Sat, 12 Oct 2019 18:16:58 +1100 Subject: [PATCH 2/2] Add JWT audience --- config.example.json | 1 + src/core/auth/auth.module.ts | 7 +++++-- src/core/auth/jwt.strategy.ts | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/config.example.json b/config.example.json index 399045c..6cd0dba 100644 --- a/config.example.json +++ b/config.example.json @@ -4,6 +4,7 @@ "pass": "password" }, "jwt": { + "audience": "https://api.syncs.org.au", "secret": "supersecret", "duration": "6h" }, diff --git a/src/core/auth/auth.module.ts b/src/core/auth/auth.module.ts index 6ba85a1..75b1c7a 100644 --- a/src/core/auth/auth.module.ts +++ b/src/core/auth/auth.module.ts @@ -14,8 +14,11 @@ const config = require("../../../config.json"); PassportModule, JwtModule.register({ secret: config.jwt.secret, - signOptions: { expiresIn: config.jwt.duration }, - }) + signOptions: { + audience: config.jwt.audience, + expiresIn: config.jwt.duration, + }, + }), ], exports: [AuthService], providers: [AuthService, LocalStrategy, JwtStrategy], diff --git a/src/core/auth/jwt.strategy.ts b/src/core/auth/jwt.strategy.ts index dcc2ea8..d72c667 100644 --- a/src/core/auth/jwt.strategy.ts +++ b/src/core/auth/jwt.strategy.ts @@ -10,6 +10,7 @@ export class JwtStrategy extends PassportStrategy(Strategy) { jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), ignoreExpiration: false, secretOrKey: config.jwt.secret, + audience: config.jwt.audience, }); }