1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import { encodeBase64 } from "https://deno.land/std@0.214.0/encoding/base64.ts";
type AuthTokenData =
| {
bearer: string;
}
| { username: string; password: String };
class AuthToken {
host: string;
token: AuthTokenData;
constructor(host: string, token: AuthTokenData) {
this.host = host;
this.token = token;
}
toString() {
if ("bearer" in this.token) {
return `Bearer ${this.token.bearer}`;
} else {
return `Basic ${encodeBase64(`${this.token.username}:${this.token.password}`)}`;
}
}
}
export class AuthTokens {
tokens: AuthToken[];
/// Create a new set of tokens based on the provided string. It is intended
/// that the string be the value of an environment variable and the string is
/// parsed for token values. The string is expected to be a semi-colon
/// separated string, where each value is `{token}@{hostname}`.
constructor(maybe_tokens_str?: string) {
let tokens: AuthToken[] = [];
if (maybe_tokens_str) {
const tokens_str = maybe_tokens_str;
for (const token_str of tokens_str.split(";")) {
if (token_str.includes("@")) {
let pair: string[] = token_str.match(/^(.+)@(.+?)$/)!.slice(1);
let token = pair[0];
let host = pair[1].toLowerCase();
if (token.includes(":")) {
let pair: string[] = token.match(/^(.+):(.+?)$/)!.slice(1);
let username = pair[0];
let password = pair[1];
tokens.push(new AuthToken(host, { username, password }));
} else {
tokens.push(new AuthToken(host, { bearer: token }));
}
} else {
throw new TypeError("Badly formed auth token discarded.");
}
}
// console.debug(`Parsed ${tokens.length} auth token(s).`);
}
this.tokens = tokens;
}
/// Attempt to match the provided specifier to the tokens in the set. The
/// matching occurs from the right of the hostname plus port, irrespective of
/// scheme. For example `https://www.deno.land:8080/` would match a token
/// with a host value of `deno.land:8080` but not match `www.deno.land`. The
/// matching is case insensitive.
get(url: string): AuthToken | void {
return this.tokens.find((t) => {
const parsedSpecifier = new URL(url);
let hostname = parsedSpecifier.port
? `${parsedSpecifier.hostname}:${parsedSpecifier.port}`
: parsedSpecifier.hostname;
return `.${hostname.toLowerCase()}`.endsWith(`.${t.host}`);
});
}
}
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
February 2, 2024