This repository has been archived by the owner on Aug 24, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.ts
116 lines (98 loc) · 3.82 KB
/
main.ts
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import "https://deno.land/[email protected]/dotenv/load.ts";
import { DOMParser } from "https://deno.land/x/[email protected]/deno-dom-wasm.ts";
import { HTMLDocument } from "https://deno.land/x/[email protected]/src/dom/document.ts";
import { logger } from "https://deno.land/x/[email protected]/middleware.ts";
import { Hono } from "https://deno.land/x/[email protected]/mod.ts";
const FILESTASH_URL = Deno.env.get("FILESTASH_URL")!;
const FILESTASH_API_KEY = Deno.env.get("FILESTASH_API_KEY")!;
const API_PREFIX = Deno.env.get("API_PREFIX")!;
const OIDC_CONFIG_URL = Deno.env.get("OIDC_CONFIG_URL")!;
const OIDC_CLIENT_ID = Deno.env.get("OIDC_CLIENT_ID")!;
const OIDC_CLIENT_SECRET = Deno.env.get("OIDC_CLIENT_SECRET")!;
const MINIO_URL = Deno.env.get("MINIO_URL")!;
const FILESTASH_REDIRECT_URI = `${FILESTASH_URL}${API_PREFIX}/callback`;
const app = new Hono();
const domParser = new DOMParser();
app.use("*", logger());
app.get("/login", (c) => {
return c.redirect(`${API_PREFIX}/login`, 302);
});
app.get(`${API_PREFIX}/login`, async (c) => {
const config = await getOIDCConfig();
const authUrl = new URL(config.authorization_endpoint);
authUrl.searchParams.set("client_id", OIDC_CLIENT_ID);
authUrl.searchParams.set("redirect_uri", FILESTASH_REDIRECT_URI);
authUrl.searchParams.set("response_type", "code");
authUrl.searchParams.set("scope", "openid profile email groups");
return c.redirect(authUrl.toString());
});
app.get(`${API_PREFIX}/callback`, async (c) => {
const oidcResponse = await exchangeOIDCCode(c.req.query("code")!);
const s3WebId = await getMinioCreds(oidcResponse);
const setCookie = await createFilestashSession(s3WebId);
c.res.headers.set("Set-Cookie", setCookie);
return c.redirect("/");
});
interface OIDCConfiguration {
authorization_endpoint: string;
token_endpoint: string;
}
let oidcConfig: OIDCConfiguration;
async function getOIDCConfig() {
if (!oidcConfig) {
const resp = await fetch(OIDC_CONFIG_URL);
oidcConfig = await resp.json();
}
return oidcConfig;
}
interface OIDCResponse {
access_token: string;
id_token: string;
}
async function exchangeOIDCCode(code: string) {
const form = new URLSearchParams();
form.append("client_id", OIDC_CLIENT_ID);
form.append("client_secret", OIDC_CLIENT_SECRET);
form.append("grant_type", "authorization_code");
form.append("code", code);
form.append("redirect_uri", FILESTASH_REDIRECT_URI);
const config = await getOIDCConfig();
const resp = await fetch(config.token_endpoint, {
method: "POST",
body: form,
});
const json = await resp.json();
console.debug(json);
return json as OIDCResponse;
}
async function getMinioCreds(oidcResponse: OIDCResponse) {
const params = new URLSearchParams();
params.append("Action", "AssumeRoleWithWebIdentity");
params.append("WebIdentityAccessToken", oidcResponse.access_token);
params.append("WebIdentityToken", oidcResponse.id_token);
params.append("Version", "2011-06-15");
const resp = await fetch(`${MINIO_URL}/?${params}`, { method: "POST" });
const text = await resp.text();
console.debug(text);
const doc = domParser.parseFromString(text, "text/html")!; // FIXME: use a proper XML parser
return doc;
}
async function createFilestashSession(s3WebId: HTMLDocument) {
const params = new URLSearchParams();
params.append("key", FILESTASH_API_KEY);
const payload = {
type: "s3",
endpoint: MINIO_URL,
access_key_id: s3WebId.querySelector("AccessKeyId")!.textContent,
secret_access_key: s3WebId.querySelector("SecretAccessKey")!.textContent,
session_token: s3WebId.querySelector("SessionToken")!.textContent,
};
const resp = await fetch(`${FILESTASH_URL}/api/session?${params}`, {
method: "POST",
body: JSON.stringify(payload),
});
const setCookie = resp.headers.get("Set-Cookie")!;
console.debug(resp.headers);
return setCookie;
}
Deno.serve(app.fetch);