@alteran/astro 0.6.3 → 0.7.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.
Files changed (44) hide show
  1. package/README.md +11 -0
  2. package/index.js +8 -0
  3. package/migrations/0009_oauth_session_state.sql +31 -0
  4. package/migrations/meta/0009_snapshot.json +749 -0
  5. package/migrations/meta/_journal.json +7 -0
  6. package/package.json +2 -1
  7. package/src/db/account.ts +134 -1
  8. package/src/db/schema.ts +31 -0
  9. package/src/lib/appview/proxy.ts +11 -8
  10. package/src/lib/auth.ts +34 -3
  11. package/src/lib/jwt.ts +4 -0
  12. package/src/lib/oauth/as-keys.ts +29 -0
  13. package/src/lib/oauth/clients.ts +453 -24
  14. package/src/lib/oauth/consent.ts +180 -0
  15. package/src/lib/oauth/dpop.ts +39 -5
  16. package/src/lib/oauth/resource.ts +93 -21
  17. package/src/lib/oauth/store.ts +64 -7
  18. package/src/lib/refresh-session.ts +16 -0
  19. package/src/lib/session-tokens.ts +33 -5
  20. package/src/lib/token-cleanup.ts +4 -2
  21. package/src/lib/util.ts +0 -1
  22. package/src/pages/.well-known/oauth-authorization-server.ts +15 -3
  23. package/src/pages/.well-known/oauth-protected-resource.ts +8 -4
  24. package/src/pages/oauth/authorize.ts +31 -52
  25. package/src/pages/oauth/consent.ts +163 -66
  26. package/src/pages/oauth/jwks.ts +15 -0
  27. package/src/pages/oauth/par.ts +34 -56
  28. package/src/pages/oauth/revoke.ts +75 -0
  29. package/src/pages/oauth/token.ts +148 -89
  30. package/src/pages/xrpc/[...nsid].ts +7 -6
  31. package/src/pages/xrpc/app.bsky.actor.getPreferences.ts +3 -4
  32. package/src/pages/xrpc/app.bsky.actor.putPreferences.ts +3 -4
  33. package/src/pages/xrpc/app.bsky.unspecced.getAgeAssuranceState.ts +3 -4
  34. package/src/pages/xrpc/chat.bsky.convo.getLog.ts +3 -4
  35. package/src/pages/xrpc/chat.bsky.convo.listConvos.ts +3 -4
  36. package/src/pages/xrpc/com.atproto.identity.getRecommendedDidCredentials.ts +3 -4
  37. package/src/pages/xrpc/com.atproto.identity.requestPlcOperationSignature.ts +3 -4
  38. package/src/pages/xrpc/com.atproto.identity.signPlcOperation.ts +3 -4
  39. package/src/pages/xrpc/com.atproto.identity.submitPlcOperation.ts +3 -4
  40. package/src/pages/xrpc/com.atproto.repo.listMissingBlobs.ts +3 -4
  41. package/src/pages/xrpc/com.atproto.server.checkAccountStatus.ts +3 -4
  42. package/src/pages/xrpc/com.atproto.server.deleteSession.ts +28 -9
  43. package/src/pages/xrpc/com.atproto.server.getSession.ts +3 -4
  44. package/types/env.d.ts +1 -0
@@ -1,20 +1,39 @@
1
1
  import type { APIContext } from 'astro';
2
+ import { bearerToken } from '../../lib/util';
3
+ import { verifyRefreshToken } from '../../lib/session-tokens';
4
+ import { getRefreshToken, revokeOAuthSession, deleteRefreshToken } from '../../db/account';
2
5
 
3
6
  export const prerender = false;
4
7
 
5
8
  /**
6
9
  * com.atproto.server.deleteSession
7
- * Delete the current session (logout)
10
+ * Delete the current refresh credential. OAuth refresh rows also revoke the
11
+ * owning OAuth session, which invalidates the current DPoP-bound access token.
8
12
  */
9
- export async function POST({ locals }: APIContext) {
13
+ export async function POST({ locals, request }: APIContext) {
10
14
  const { env } = locals.runtime;
15
+ const token = bearerToken(request);
16
+ if (!token) {
17
+ return new Response(JSON.stringify({ error: 'AuthRequired', message: 'No authorization token provided' }), {
18
+ status: 401,
19
+ headers: { 'Content-Type': 'application/json' },
20
+ });
21
+ }
11
22
 
12
- // TODO: Implement proper session revocation
13
- // For single-user PDS, we just return success
14
- // In a full implementation, this would:
15
- // 1. Extract refresh token from Authorization header
16
- // 2. Add it to a blacklist/revocation list
17
- // 3. Invalidate associated access tokens
23
+ const verification = await verifyRefreshToken(env, token, { ignoreExpiration: true }).catch(() => null);
24
+ const jti = verification?.decoded?.jti;
25
+ if (!jti) {
26
+ return new Response(JSON.stringify({ error: 'InvalidToken', message: 'Invalid refresh token' }), {
27
+ status: 401,
28
+ headers: { 'Content-Type': 'application/json' },
29
+ });
30
+ }
31
+
32
+ const stored = await getRefreshToken(env, jti);
33
+ if (stored?.tokenKind === 'oauth' && stored.oauthSessionId) {
34
+ await revokeOAuthSession(env, stored.oauthSessionId);
35
+ }
36
+ await deleteRefreshToken(env, jti);
18
37
 
19
38
  return new Response(JSON.stringify({}), {
20
39
  status: 200,
@@ -22,4 +41,4 @@ export async function POST({ locals }: APIContext) {
22
41
  'Content-Type': 'application/json',
23
42
  },
24
43
  });
25
- }
44
+ }
@@ -1,5 +1,5 @@
1
1
  import type { APIContext } from 'astro';
2
- import { AuthTokenExpiredError, authenticateRequest, expiredToken, unauthorized } from '../../lib/auth';
2
+ import { authErrorResponse, authenticateRequest, unauthorized } from '../../lib/auth';
3
3
  import { getAccountByIdentifier } from '../../db/account';
4
4
 
5
5
  export const prerender = false;
@@ -16,9 +16,8 @@ export async function GET({ locals, request }: APIContext) {
16
16
  try {
17
17
  authContext = await authenticateRequest(request, env);
18
18
  } catch (error) {
19
- if (error instanceof AuthTokenExpiredError) {
20
- return expiredToken();
21
- }
19
+ const handled = await authErrorResponse(env, error);
20
+ if (handled) return handled;
22
21
  throw error;
23
22
  }
24
23
  if (!authContext) {
package/types/env.d.ts CHANGED
@@ -60,6 +60,7 @@ declare global {
60
60
  // Relay crawl configuration
61
61
  PDS_RELAY_HOSTS?: string; // CSV of relay hostnames (no scheme). Default: bsky.network
62
62
  PDS_RELAY_NOTIFY?: string; // 'false' to disable auto notify
63
+ PDS_OAUTH_CLIENT_HOSTS?: string; // CSV of trusted OAuth client metadata/JWKS hostnames
63
64
  }
64
65
 
65
66
  namespace App {