@terrafirmagreg-team/auth 0.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,24 +1,22 @@
1
1
  {
2
2
  "name": "@terrafirmagreg-team/auth",
3
- "version": "0.1.0",
3
+ "version": "1.2.1",
4
4
  "type": "module",
5
+ "description": "GitHub OAuth sign-in and cookie sessions",
6
+ "license": "LGPL-3.0-only",
5
7
  "exports": {
6
8
  ".": "./src/lib/index.ts",
7
- "./*": [
8
- "./src/*.ts",
9
- "./src/*.tsx",
10
- "./src/*/index.ts",
11
- "./src/*/index.tsx"
9
+ "./lib/*": [
10
+ "./src/lib/*.ts",
11
+ "./src/lib/*/index.ts"
12
12
  ]
13
13
  },
14
14
  "files": [
15
- "src",
16
- "styles",
17
- "styles.css",
18
- "locales"
15
+ "src"
19
16
  ],
20
17
  "dependencies": {
21
- "@terrafirmagreg-team/data": "0.1.0"
18
+ "@terrafirmagreg-team/data": "1.2.1",
19
+ "arctic": "^3.7.0"
22
20
  },
23
21
  "devDependencies": {
24
22
  "@types/node": "^26.6.5"
@@ -47,6 +47,9 @@ export function githubCookieAuth({
47
47
  )
48
48
  .catch(() => null);
49
49
  cache.set(token, session);
50
+ session.then((s) => {
51
+ if (!s && cache.get(token) === session) cache.delete(token);
52
+ });
50
53
  }
51
54
  return session;
52
55
  },
@@ -67,3 +70,4 @@ export function devCookieAuth({
67
70
  },
68
71
  };
69
72
  }
73
+
package/src/lib/config.ts CHANGED
@@ -12,16 +12,7 @@ export function authMode(): AuthMode {
12
12
 
13
13
  export function authEnabled() {
14
14
  if (authMode() === 'dev') return true;
15
- return Boolean(
16
- env('COMMENTS_TOKEN_SECRET') && env('GITHUB_COMMENTS_CLIENT_ID'),
17
- );
18
- }
19
-
20
- export function authOwnerLogins() {
21
- return (env('GITHUB_COMMENTS_OWNER_LOGINS') ?? '')
22
- .split(',')
23
- .map((login) => login.trim())
24
- .filter(Boolean);
15
+ return Boolean(env('DISCUSSIONS_SECRET') && env('APP_CLIENT_ID'));
25
16
  }
26
17
 
27
18
  export interface AuthConfig {
@@ -38,14 +29,15 @@ export interface AuthConfig {
38
29
 
39
30
  export function authConfig(): AuthConfig {
40
31
  return {
41
- clientId: env('GITHUB_COMMENTS_CLIENT_ID')!,
42
- clientSecret: env('GITHUB_COMMENTS_CLIENT_SECRET')!,
43
- tokenSecret: env('COMMENTS_TOKEN_SECRET')!,
32
+ clientId: env('APP_CLIENT_ID')!,
33
+ clientSecret: env('APP_SECRET')!,
34
+ tokenSecret: env('DISCUSSIONS_SECRET') ?? 'dev-token-secret',
44
35
  cookieName: authCookie,
45
36
  devCookieName: devAuthCookie,
46
37
  callbackPath: '/api/comments/oauth/callback',
47
38
  loginPath: '/api/comments/oauth/login',
48
- scope: 'public_repo',
39
+ scope: '',
49
40
  mode: authMode(),
50
41
  };
51
42
  }
43
+
package/src/lib/index.ts CHANGED
@@ -2,7 +2,6 @@ export {
2
2
  authConfig,
3
3
  authEnabled,
4
4
  authMode,
5
- authOwnerLogins,
6
5
  authCookie,
7
6
  devAuthCookie,
8
7
  type AuthConfig,
@@ -23,3 +22,4 @@ import { authConfig } from './config';
23
22
  const flow = createOAuthFlow(authConfig);
24
23
 
25
24
  export const { login, callback, logout, devLogin } = flow;
25
+
package/src/lib/oauth.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import { decrypt, encrypt } from '@terrafirmagreg-team/data';
2
+ import { GitHub } from 'arctic';
2
3
  import type { AuthConfig } from './config';
3
4
 
4
- const GITHUB_AUTHORIZE = 'https://github.com/login/oauth/authorize';
5
- const GITHUB_ACCESS_TOKEN = 'https://github.com/login/oauth/access_token';
6
5
  const STATE_TTL = 10 * 60 * 1000;
7
6
  const COOKIE_MAX_AGE = 60 * 60 * 24 * 365;
8
7
  const COOKIE_BASE = 'Path=/; Max-Age=%d; SameSite=Lax; HttpOnly; Secure';
@@ -78,18 +77,24 @@ button:hover{opacity:.85}
78
77
  }
79
78
 
80
79
  export function createOAuthFlow(getConfig: () => AuthConfig): OAuthFlow {
80
+ function github(config: AuthConfig, self: string): GitHub {
81
+ return new GitHub(
82
+ config.clientId,
83
+ config.clientSecret,
84
+ `${self}${config.callbackPath}`,
85
+ );
86
+ }
87
+
81
88
  function login(request: Request): Response {
82
89
  const config = getConfig();
83
90
  if (config.mode === 'dev') return devLoginForm(request, config);
84
91
  const self = new URL(request.url).origin;
85
92
  const returnUrl = sameOrigin(new URL(request.url).searchParams.get('return'), self);
86
- const params = new URLSearchParams({
87
- client_id: config.clientId,
88
- redirect_uri: `${self}${config.callbackPath}`,
89
- scope: config.scope,
90
- state: encodeState(returnUrl, config.tokenSecret),
91
- });
92
- return Response.redirect(`${GITHUB_AUTHORIZE}?${params}`, 302);
93
+ const url = github(config, self).createAuthorizationURL(
94
+ encodeState(returnUrl, config.tokenSecret),
95
+ config.scope.split(' ').filter(Boolean),
96
+ );
97
+ return Response.redirect(url, 302);
93
98
  }
94
99
 
95
100
  async function devLogin(request: Request): Promise<Response> {
@@ -134,27 +139,14 @@ export function createOAuthFlow(getConfig: () => AuthConfig): OAuthFlow {
134
139
  if (url.searchParams.get('error') || !code)
135
140
  return Response.redirect(returnUrl, 302);
136
141
  try {
137
- const res = await fetch(GITHUB_ACCESS_TOKEN, {
138
- method: 'POST',
139
- headers: {
140
- accept: 'application/json',
141
- 'content-type': 'application/x-www-form-urlencoded',
142
- },
143
- body: new URLSearchParams({
144
- client_id: config.clientId,
145
- client_secret: config.clientSecret,
146
- code,
147
- }),
148
- });
149
- const { access_token } = (await res.json()) as { access_token?: string };
150
- if (!access_token) throw new Error('no token');
142
+ const tokens = await github(config, self).validateAuthorizationCode(code);
151
143
  return new Response(null, {
152
144
  status: 302,
153
145
  headers: {
154
146
  location: returnUrl,
155
147
  'set-cookie': setCookieHeader(
156
148
  config.cookieName,
157
- encrypt(access_token, config.tokenSecret),
149
+ encrypt(tokens.accessToken(), config.tokenSecret),
158
150
  COOKIE_MAX_AGE,
159
151
  ),
160
152
  },
@@ -180,3 +172,4 @@ export function createOAuthFlow(getConfig: () => AuthConfig): OAuthFlow {
180
172
 
181
173
  return { login, devLogin, callback, logout };
182
174
  }
175
+