[next] Permit (#1899)

* feat: replaced custom auth extraction logic with permit

* fix: fixed tests
This commit is contained in:
Wyatt Johnson
2018-09-21 22:06:46 +00:00
committed by GitHub
parent 18e6638162
commit 85af8d1bbf
5 changed files with 53 additions and 68 deletions
+5
View File
@@ -18041,6 +18041,11 @@
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
},
"permit": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/permit/-/permit-0.2.4.tgz",
"integrity": "sha512-Mp2XTEMD3mPsZIWq3bp0claE4IxXKa4C6nhSDPZgGri8Q4CLjEjAQrP/xGKq2548a2KFENmA1V7W0Lob8kTuzw=="
},
"pify": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+1
View File
@@ -74,6 +74,7 @@
"passport-oauth2": "^1.4.0",
"passport-strategy": "^1.0.0",
"performance-now": "^2.1.0",
"permit": "^0.2.4",
"subscriptions-transport-ws": "^0.9.12",
"tlds": "^1.203.1",
"uuid": "^3.3.2"
@@ -4,65 +4,34 @@ import { Config } from "talk-common/config";
import {
createJWTSigningConfig,
extractJWTFromRequest,
parseAuthHeader,
} from "talk-server/app/middleware/passport/jwt";
import { Request } from "talk-server/types/express";
describe("parseAuthHeader", () => {
it("parses valid headers", () => {
const parsed = {
scheme: "bearer",
value: "token",
};
expect(parseAuthHeader("Bearer token")).toEqual(parsed);
expect(parseAuthHeader("bearer token")).toEqual(parsed);
expect(parseAuthHeader("bearer token")).toEqual(parsed);
});
it("parses invalid headers", () => {
expect(parseAuthHeader("this-is-a-wrong-header")).toEqual(null);
expect(parseAuthHeader("bearerthis-is-a-wrong-header")).toEqual(null);
});
});
describe("extractJWTFromRequest", () => {
it("extracts the token from header", () => {
const req = {
get: sinon
.stub()
.withArgs("authorization")
.returns("Bearer token"),
headers: {
authorization: "Bearer token",
},
url: "",
};
expect(extractJWTFromRequest((req as any) as Request)).toEqual("token");
expect(req.get.calledOnce).toBeTruthy();
req.get.reset();
req.get.returns(null);
delete req.headers.authorization;
expect(extractJWTFromRequest((req as any) as Request)).toEqual(null);
expect(req.get.calledOnce).toBeTruthy();
});
it("extracts the token from query string", () => {
const req = {
get: sinon
.stub()
.withArgs("authorization")
.returns(null),
query: { access_token: "token" },
url: "",
};
expect(extractJWTFromRequest((req as any) as Request)).toEqual(null);
req.url = "https://talk.coralproject.net/api?access_token=token";
expect(extractJWTFromRequest((req as any) as Request)).toEqual("token");
expect(req.get.calledOnce).toBeTruthy();
delete req.query.access_token;
req.get.reset();
expect(extractJWTFromRequest((req as any) as Request)).toEqual(null);
expect(req.get.calledOnce).toBeTruthy();
});
});
+6 -27
View File
@@ -2,41 +2,20 @@ import { Redis } from "ioredis";
import jwt, { SignOptions } from "jsonwebtoken";
import { Db } from "mongodb";
import { Strategy } from "passport-strategy";
import { Bearer } from "permit";
import uuid from "uuid";
import { Config } from "talk-common/config";
import { retrieveUser, User } from "talk-server/models/user";
import { Request } from "talk-server/types/express";
const authHeaderRegex = /(\S+)\s+(\S+)/;
export function parseAuthHeader(header: string) {
const matches = header.match(authHeaderRegex);
if (!matches || matches.length < 3) {
return null;
}
return {
scheme: matches[1].toLowerCase(),
value: matches[2],
};
}
export function extractJWTFromRequest(req: Request) {
const header = req.get("authorization");
if (header) {
const parts = parseAuthHeader(header);
if (parts && parts.scheme === "bearer") {
return parts.value;
}
}
const permit = new Bearer({
basic: "password",
query: "access_token",
});
const token: string | undefined | false = req.query && req.query.access_token;
if (token) {
return token;
}
return null;
return permit.check(req) || null;
}
function generateJTIBlacklistKey(jti: string) {
+31
View File
@@ -0,0 +1,31 @@
// TODO: (wyattjoh) following https://github.com/DefinitelyTyped/DefinitelyTyped/pull/29061 to merge then replace this with @types/permit.
declare module "permit" {
import { IncomingMessage, ServerResponse } from "http";
export interface PermitOptions {
scheme?: string;
proxy?: string;
realm?: string;
}
export interface BearerOptions extends PermitOptions {
basic?: string;
header?: string;
query?: string;
}
export class Permit {
constructor(options: PermitOptions);
check(req: IncomingMessage): void;
fail(res: ServerResponse): void;
}
export class Bearer extends Permit {
constructor(options: BearerOptions);
check(req: IncomingMessage): string;
}
export class Basic extends Permit {
check(req: IncomingMessage): [string, string];
}
}