87 lines
1.9 KiB
JavaScript
87 lines
1.9 KiB
JavaScript
import crypto from 'crypto';
|
|
import jwt from 'jsonwebtoken';
|
|
|
|
import data from './data';
|
|
import { privateKey, publicKey } from './secret';
|
|
|
|
function getCurrentSeconds() {
|
|
return Math.floor(Date.now() / 1000);
|
|
}
|
|
|
|
function createTokenId() {
|
|
return crypto.randomBytes(16).toString('hex');
|
|
}
|
|
|
|
export function createToken(scopes = {}) {
|
|
return new Promise((resolve, reject) => {
|
|
const payload = {
|
|
jti: createTokenId(),
|
|
iss: 'https://unpkg.com',
|
|
iat: getCurrentSeconds(),
|
|
scopes
|
|
};
|
|
|
|
jwt.sign(payload, privateKey, { algorithm: 'RS256' }, (error, token) => {
|
|
if (error) {
|
|
reject(error);
|
|
} else {
|
|
resolve(token);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
const revokedTokensSet = 'revoked-tokens';
|
|
|
|
export function verifyToken(token) {
|
|
return new Promise((resolve, reject) => {
|
|
const options = { algorithms: ['RS256'] };
|
|
|
|
jwt.verify(token, publicKey, options, (error, payload) => {
|
|
if (error) {
|
|
reject(error);
|
|
} else {
|
|
if (payload.jti) {
|
|
data.sismember(revokedTokensSet, payload.jti, (error, value) => {
|
|
if (error) {
|
|
reject(error);
|
|
} else {
|
|
resolve(value === 0 ? payload : null);
|
|
}
|
|
});
|
|
} else {
|
|
resolve(null);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
export function revokeToken(token) {
|
|
return verifyToken(token).then(payload => {
|
|
if (payload) {
|
|
return new Promise((resolve, reject) => {
|
|
data.sadd(revokedTokensSet, payload.jti, error => {
|
|
if (error) {
|
|
reject(error);
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
export function removeAllRevokedTokens() {
|
|
return new Promise((resolve, reject) => {
|
|
data.del(revokedTokensSet, error => {
|
|
if (error) {
|
|
reject(error);
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
}
|