mirror of
https://github.com/wassname/talk.git
synced 2026-08-12 12:30:39 +08:00
exposed more controls on jwt and added docs
This commit is contained in:
@@ -35,11 +35,22 @@ const CONFIG = {
|
||||
// cleared when the user is logged out.
|
||||
JWT_CLEAR_COOKIE_LOGOUT: process.env.TALK_JWT_CLEAR_COOKIE_LOGOUT ? process.env.TALK_JWT_CLEAR_COOKIE_LOGOUT !== 'FALSE' : true,
|
||||
|
||||
// JWT_DISABLE_AUDIENCE when TRUE will disable the issuer claim (iss) from tokens.
|
||||
JWT_DISABLE_AUDIENCE: process.env.TALK_JWT_DISABLE_AUDIENCE === 'TRUE',
|
||||
|
||||
// JWT_AUDIENCE is the value for the audience claim for the tokens that will be
|
||||
// verified when decoding. If `JWT_AUDIENCE` is not in the environment, then it
|
||||
// will default to `talk`.
|
||||
JWT_AUDIENCE: process.env.TALK_JWT_AUDIENCE || 'talk',
|
||||
|
||||
// JWT_DISABLE_ISSUER when TRUE will disable the issuer claim (iss) from tokens.
|
||||
JWT_DISABLE_ISSUER: process.env.TALK_JWT_DISABLE_ISSUER === 'TRUE',
|
||||
|
||||
// JWT_USER_ID_CLAIM is the claim which stores the user's id. This may be a deep
|
||||
// object delimited using dot notation. Example `user.id` would store it like:
|
||||
// {user: {id}} on the claims object. (Default `sub`)
|
||||
JWT_USER_ID_CLAIM: process.env.TALK_JWT_USER_ID_CLAIM || 'sub',
|
||||
|
||||
// JWT_ISSUER is the value for the issuer for the tokens that will be verified
|
||||
// when decoding. If `JWT_ISSUER` is not in the environment, then it will try
|
||||
// `TALK_ROOT_URL`, otherwise, it will be undefined.
|
||||
@@ -144,6 +155,16 @@ if (CONFIG.JWT_SECRETS) {
|
||||
}
|
||||
}
|
||||
|
||||
// Disable the audience claim if requested.
|
||||
if (CONFIG.JWT_DISABLE_AUDIENCE) {
|
||||
CONFIG.JWT_AUDIENCE = undefined;
|
||||
}
|
||||
|
||||
// Disable the issuer claim if requested.
|
||||
if (CONFIG.JWT_DISABLE_ISSUER) {
|
||||
CONFIG.JWT_ISSUER = undefined;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// External database url's
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -77,15 +77,28 @@ The following are configuration shared with every type of secret used.
|
||||
tokens. (Default `process.env.TALK_ROOT_URL`)
|
||||
- `TALK_JWT_AUDIENCE` (_optional_) - the audience (`aud`) claim for login JWT
|
||||
tokens. (Default `talk`)
|
||||
|
||||
**You must also specify secrets as either the `TALK_JWT_SECRET` or the `TALK_JWT_SECRETS`
|
||||
variable. Refer to the [Secrets Documentation]({{ "/docs/running/secrets/" | absolute_url }})
|
||||
on the contents of those variables.**
|
||||
|
||||
#### Advanced
|
||||
|
||||
These are advanced settings for fine tuning the auth integration, and
|
||||
is not needed in most situations.
|
||||
|
||||
- `TALK_JWT_COOKIE_NAME` (_optional_) - the name of the cookie to extract the
|
||||
JWT from (Default `authorization`)
|
||||
- `TALK_JWT_CLEAR_COOKIE_LOGOUT` (_optional_) - when `FALSE`, Talk will not
|
||||
clear the cookie with name `TALK_JWT_COOKIE_NAME` when logging out (Default
|
||||
`TRUE`)
|
||||
|
||||
**You must also specify secrets as either the `TALK_JWT_SECRET` or the `TALK_JWT_SECRETS`
|
||||
variable. Refer to the [Secrets Documentation]({{ "/docs/running/secrets/" | absolute_url }})
|
||||
on the contents of those variables.**
|
||||
- `TALK_JWT_DISABLE_AUDIENCE` (_optional_) - when `TRUE`, Talk will not verify or sign JWT's
|
||||
with an audience (`aud`) claim, even if the `TALK_JWT_AUDIENCE` config is set. (Default `FALSE`)
|
||||
- `TALK_JWT_DISABLE_ISSUER` (_optional_) - when `TRUE`, Talk will not verify or sign JWT's
|
||||
with an issuer (`iss`) claim, even if the `TALK_JWT_ISSUER` config is set. (Default `FALSE`)
|
||||
- `TALK_JWT_USER_ID_CLAIM` (_optional_) - specify the claim using dot notation for where the
|
||||
user id should be stored/read to/from. Example `user.id` would store it like: `{user: {id}}`
|
||||
on the claims object. (Default `sub`)
|
||||
|
||||
### Email
|
||||
|
||||
|
||||
+14
-8
@@ -1,4 +1,5 @@
|
||||
const passport = require('passport');
|
||||
const {set, get} = require('lodash');
|
||||
const UsersService = require('./users');
|
||||
const SettingsService = require('./settings');
|
||||
const TokensService = require('./tokens');
|
||||
@@ -23,21 +24,26 @@ const {
|
||||
RECAPTCHA_SECRET,
|
||||
RECAPTCHA_ENABLED,
|
||||
JWT_COOKIE_NAME,
|
||||
JWT_CLEAR_COOKIE_LOGOUT
|
||||
JWT_CLEAR_COOKIE_LOGOUT,
|
||||
JWT_USER_ID_CLAIM,
|
||||
} = require('../config');
|
||||
|
||||
const {
|
||||
jwt: JWT_SECRET
|
||||
jwt
|
||||
} = require('../secrets');
|
||||
|
||||
// GenerateToken will sign a token to include all the authorization information
|
||||
// needed for the front end.
|
||||
const GenerateToken = (user) => {
|
||||
return JWT_SECRET.sign({}, {
|
||||
const claims = {};
|
||||
|
||||
// Set the user id.
|
||||
set(claims, JWT_USER_ID_CLAIM, user.id);
|
||||
|
||||
return jwt.sign(claims, {
|
||||
jwtid: uuid.v4(),
|
||||
expiresIn: JWT_EXPIRY,
|
||||
issuer: JWT_ISSUER,
|
||||
subject: user.id,
|
||||
audience: JWT_AUDIENCE,
|
||||
algorithm: JWT_ALG
|
||||
});
|
||||
@@ -191,7 +197,7 @@ const CheckBlacklisted = async (jwt) => {
|
||||
|
||||
// Check to see if this is a PAT.
|
||||
if (jwt.pat) {
|
||||
return TokensService.validate(jwt.sub, jwt.jti);
|
||||
return TokensService.validate(get(jwt, JWT_USER_ID_CLAIM), jwt.jti);
|
||||
}
|
||||
|
||||
// It wasn't a PAT! Check to see if it is valid anyways.
|
||||
@@ -216,7 +222,7 @@ let cookieExtractor = function(req) {
|
||||
// Override the JwtVerifier method on the JwtStrategy so we can pack the
|
||||
// original token into the payload.
|
||||
JwtStrategy.JwtVerifier = (token, secretOrKey, options, callback) => {
|
||||
return JWT_SECRET.verify(token, options, (err, jwt) => {
|
||||
return jwt.verify(token, options, (err, jwt) => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
@@ -238,7 +244,7 @@ passport.use(new JwtStrategy({
|
||||
|
||||
// Use the secret passed in which is loaded from the environment. This can be
|
||||
// a certificate (loaded) or a HMAC key.
|
||||
secretOrKey: JWT_SECRET,
|
||||
secretOrKey: jwt,
|
||||
|
||||
// Verify the issuer.
|
||||
issuer: JWT_ISSUER,
|
||||
@@ -265,7 +271,7 @@ passport.use(new JwtStrategy({
|
||||
|
||||
// Try to get the user from the database or crack it from the token and
|
||||
// plugin integrations.
|
||||
user = await UsersService.findOrCreateByIDToken(jwt.sub, {token, jwt});
|
||||
user = await UsersService.findOrCreateByIDToken(get(jwt, JWT_USER_ID_CLAIM), {token, jwt});
|
||||
}
|
||||
|
||||
// Attach the JWT to the request.
|
||||
|
||||
+5
-2
@@ -1,10 +1,12 @@
|
||||
const errors = require('../errors');
|
||||
const UserModel = require('../models/user');
|
||||
const uuid = require('uuid');
|
||||
const {set, get} = require('lodash');
|
||||
|
||||
const {
|
||||
JWT_ISSUER,
|
||||
JWT_AUDIENCE
|
||||
JWT_AUDIENCE,
|
||||
JWT_USER_ID_CLAIM,
|
||||
} = require('../config');
|
||||
|
||||
const {
|
||||
@@ -30,10 +32,11 @@ module.exports = class TokenService {
|
||||
jti: uuid.v4(),
|
||||
iss: JWT_ISSUER,
|
||||
aud: JWT_AUDIENCE,
|
||||
sub: userID,
|
||||
pat: true
|
||||
};
|
||||
|
||||
set(payload, JWT_USER_ID_CLAIM, userID);
|
||||
|
||||
// Sign the payload.
|
||||
const jwt = JWT_SECRET.sign(payload, {});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user