Remove auth

This commit is contained in:
Michael Jackson
2019-07-09 10:58:10 -07:00
parent db01dc234b
commit 390498fefd
15 changed files with 0 additions and 466 deletions

View File

@ -1,65 +0,0 @@
import request from 'supertest';
import createServer from '../createServer';
import withRevokedToken from './utils/withRevokedToken';
import withToken from './utils/withToken';
describe('The /_auth endpoint', () => {
let server;
beforeEach(() => {
server = createServer();
});
describe('POST /_auth', () => {
it('creates a new auth token', done => {
request(server)
.post('/_auth')
.end((err, res) => {
expect(res.body).toHaveProperty('token');
done();
});
});
});
describe('GET /_auth', () => {
describe('with no auth', () => {
it('echoes back null', done => {
request(server)
.get('/_auth')
.end((err, res) => {
expect(res.body).toHaveProperty('auth');
expect(res.body.auth).toBe(null);
done();
});
});
});
describe('with a revoked auth token', () => {
it('echoes back null', done => {
withRevokedToken({ some: { scope: true } }, token => {
request(server)
.get('/_auth?token=' + token)
.end((err, res) => {
expect(res.body).toHaveProperty('auth');
expect(res.body.auth).toBe(null);
done();
});
});
});
});
describe('with a valid auth token', () => {
it('echoes back the auth payload', done => {
withToken({ some: { scope: true } }, token => {
request(server)
.get('/_auth?token=' + token)
.end((err, res) => {
expect(res.body).toHaveProperty('auth');
expect(typeof res.body.auth).toBe('object');
done();
});
});
});
});
});
});

View File

@ -1,89 +0,0 @@
import request from 'supertest';
import createServer from '../createServer';
import withAuthHeader from './utils/withAuthHeader';
import withRevokedToken from './utils/withRevokedToken';
import withToken from './utils/withToken';
describe('The /api/auth endpoint', () => {
let server;
beforeEach(() => {
server = createServer();
});
describe('POST /api/auth', () => {
it('creates a new auth token', done => {
request(server)
.post('/api/auth')
.end((err, res) => {
expect(res.body).toHaveProperty('token');
done();
});
});
});
describe('GET /api/auth', () => {
describe('with no auth', () => {
it('echoes back null', done => {
request(server)
.get('/api/auth')
.end((err, res) => {
expect(res.body).toHaveProperty('auth');
expect(res.body.auth).toBe(null);
done();
});
});
});
describe('with a revoked auth token', () => {
it('echoes back null', done => {
withRevokedToken({ some: { scope: true } }, token => {
request(server)
.get('/api/auth?token=' + token)
.end((err, res) => {
expect(res.body).toHaveProperty('auth');
expect(res.body.auth).toBe(null);
done();
});
});
});
});
describe('with a valid auth token', () => {
describe('in the query string', () => {
it('echoes back the auth payload', done => {
const scopes = { some: { scope: true } };
withToken(scopes, token => {
request(server)
.get('/api/auth?token=' + token)
.end((err, res) => {
expect(res.body).toHaveProperty('auth');
expect(res.body.auth).toBeDefined();
expect(res.body.auth.scopes).toMatchObject(scopes);
done();
});
});
});
});
describe('in the Authorization header', () => {
it('echoes back the auth payload', done => {
const scopes = { some: { scope: true } };
withAuthHeader(scopes, header => {
request(server)
.get('/api/auth')
.set({ Authorization: header })
.end((err, res) => {
expect(res.body).toHaveProperty('auth');
expect(res.body.auth).toBeDefined();
expect(res.body.auth.scopes).toMatchObject(scopes);
done();
});
});
});
});
});
});
});

View File

@ -1,3 +0,0 @@
import closeDatabase from './utils/closeDatabase';
afterAll(closeDatabase);

View File

@ -1,5 +0,0 @@
import data from '../../utils/data';
export default function closeDatabase() {
data.quit();
}

View File

@ -1,11 +0,0 @@
import withToken from './withToken';
function encodeBase64(token) {
return Buffer.from(token).toString('base64');
}
export default function withAuthHeader(scopes, done) {
withToken(scopes, token => {
done(encodeBase64(token));
});
}

View File

@ -1,10 +0,0 @@
import { revokeToken } from '../../utils/auth';
import withToken from './withToken';
export default function withRevokedToken(scopes, done) {
withToken(scopes, token => {
revokeToken(token).then(() => {
done(token);
});
});
}

View File

@ -1,5 +0,0 @@
import { createToken } from '../../utils/auth';
export default function withToken(scopes, done) {
createToken(scopes).then(done);
}

View File

@ -1,18 +0,0 @@
import { createToken } from '../utils/auth';
const defaultScopes = {};
export default function createAuth(req, res) {
createToken(defaultScopes).then(
token => {
res.send({ token });
},
error => {
console.error(error);
res.status(500).send({
error: 'Unable to generate auth token'
});
}
);
}

View File

@ -1,3 +0,0 @@
export default function serveAuth(req, res) {
res.send({ auth: req.user });
}

View File

@ -1,42 +0,0 @@
import { verifyToken } from '../utils/auth';
function decodeBase64(string) {
return Buffer.from(string, 'base64').toString();
}
/**
* Sets req.user from the payload in the auth token in the request.
*/
export default function userToken(req, res, next) {
if (req.user !== undefined) {
return next();
}
const auth = req.get('Authorization');
const token = auth && decodeBase64(auth);
if (!token) {
req.user = null;
return next();
}
verifyToken(token).then(
payload => {
req.user = payload;
next();
},
error => {
if (error.name === 'JsonWebTokenError') {
res.status(403).send({
error: `Bad auth token: ${error.message}`
});
} else {
console.error(error);
res.status(500).send({
error: 'Unable to verify auth'
});
}
}
);
}

View File

@ -1,39 +0,0 @@
import * as auth from '../auth';
describe('Auth API', () => {
beforeEach(done => {
auth.removeAllRevokedTokens().then(() => done(), done);
});
it('creates tokens with the right scopes', done => {
const scopes = {
blacklist: {
add: true,
remove: true
}
};
auth.createToken(scopes).then(token => {
auth.verifyToken(token).then(payload => {
expect(payload.jti).toEqual(expect.any(String));
expect(payload.iss).toEqual(expect.any(String));
expect(payload.iat).toEqual(expect.any(Number));
expect(payload.scopes).toMatchObject(scopes);
done();
});
});
});
it('refuses to verify revoked tokens', done => {
const scopes = {};
auth.createToken(scopes).then(token => {
auth.revokeToken(token).then(() => {
auth.verifyToken(token).then(payload => {
expect(payload).toBe(null);
done();
});
});
});
});
});

View File

@ -1,86 +0,0 @@
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();
}
});
});
}

View File

@ -1,9 +0,0 @@
import redis from 'redis';
redis.debug_mode = process.env.DEBUG_REDIS != null;
const client = redis.createClient(
process.env.DATA_URL || process.env.OPENREDIS_URL || 'redis://localhost:6379'
);
export default client;