Use sha256 for access tokens

This commit is contained in:
simojenki
2021-04-09 17:08:28 +10:00
parent 10ef9c8f09
commit 234e841032
3 changed files with 94 additions and 3 deletions

View File

@@ -1,5 +1,7 @@
import dayjs, { Dayjs } from "dayjs";
import { v4 as uuid } from "uuid";
import crypto from "crypto";
import { Encryption } from "./encryption";
import logger from "./logger";
@@ -94,3 +96,25 @@ export class AccessTokenPerAuthToken implements AccessTokens {
authTokenFor = (value: string): string | undefined => this.accessTokenToAuthToken.get(value);
}
export const sha256 = (salt: string) => (authToken: string) => crypto
.createHash("sha256")
.update(`${authToken}${salt}`)
.digest("hex")
export class InMemoryAccessTokens implements AccessTokens {
tokens = new Map<string, string>();
minter;
constructor(minter: (authToken: string) => string) {
this.minter = minter
}
mint = (authToken: string): string => {
const accessToken = this.minter(authToken);
this.tokens.set(accessToken, authToken);
return accessToken;
}
authTokenFor = (value: string): string | undefined => this.tokens.get(value);
}

View File

@@ -3,6 +3,8 @@ import server from "./server";
import logger from "./logger";
import { Navidrome } from "./navidrome";
import encryption from "./encryption";
import { InMemoryAccessTokens, sha256 } from "./access_tokens";
import { InMemoryLinkCodes } from "./link_codes";
const PORT = +(process.env["BONOB_PORT"] || 4534);
const WEB_ADDRESS =
@@ -18,6 +20,7 @@ const bonob = bonobService(
WEB_ADDRESS,
"AppLink"
);
const secret = process.env["BONOB_SECRET"] || "bonob";
const sonosSystem = sonos(SONOS_DEVICE_DISCOVERY, SONOS_SEED_HOST);
if(process.env["BONOB_SONOS_AUTO_REGISTER"] == "true") {
@@ -34,8 +37,10 @@ const app = server(
WEB_ADDRESS,
new Navidrome(
process.env["BONOB_NAVIDROME_URL"] || "http://localhost:4533",
encryption(process.env["BONOB_SECRET"] || "bonob")
)
encryption(secret)
),
new InMemoryLinkCodes(),
new InMemoryAccessTokens(sha256(secret))
);
app.listen(PORT, () => {

View File

@@ -5,6 +5,8 @@ import {
AccessTokenPerAuthToken,
EncryptedAccessTokens,
ExpiringAccessTokens,
InMemoryAccessTokens,
sha256
} from "../src/access_tokens";
import { Encryption } from "../src/encryption";
@@ -207,5 +209,65 @@ describe("AccessTokenPerAuthToken", () => {
expect(accessTokens.authTokenFor(uuid())).toBeUndefined();
});
});
});
describe('sha256 minter', () => {
it('should return the same value for the same salt and authToken', () => {
const authToken = uuid();
const token1 = sha256("salty")(authToken);
const token2 = sha256("salty")(authToken);
expect(token1).not.toEqual(authToken);
expect(token1).toEqual(token2);
});
it('should returrn different values for the same salt but different authTokens', () => {
const authToken1 = uuid();
const authToken2 = uuid();
const token1 = sha256("salty")(authToken1);
const token2= sha256("salty")(authToken2);
expect(token1).not.toEqual(token2);
});
it('should return different values for the same authToken but different salts', () => {
const authToken = uuid();
const token1 = sha256("salt1")(authToken);
const token2= sha256("salt2")(authToken);
expect(token1).not.toEqual(token2);
});
});
describe("InMemoryAccessTokens", () => {
const reverseAuthToken = (authToken: string) => authToken.split("").reverse().join("");
const accessTokens = new InMemoryAccessTokens(reverseAuthToken);
it("should return the same access token for the same auth token", () => {
const authToken = "token1";
const accessToken1 = accessTokens.mint(authToken);
const accessToken2 = accessTokens.mint(authToken);
expect(accessToken1).not.toEqual(authToken);
expect(accessToken1).toEqual(accessToken2);
});
describe("when there is an auth token for the access token", () => {
it("should be able to retrieve it", () => {
const authToken = uuid();
const accessToken = accessTokens.mint(authToken);
expect(accessTokens.authTokenFor(accessToken)).toEqual(authToken);
});
});
describe("when there is no auth token for the access token", () => {
it("should return undefined", () => {
expect(accessTokens.authTokenFor(uuid())).toBeUndefined();
});
});
});