Step 3: ATproto OAuth + SurrealDB JWT - Implement database-backed OAuth state storage (lib/auth/oauth-state.ts) - Add session helpers for JWT decoding (lib/auth/session.ts) - Fix OAuth callback to properly handle state retrieval - Create /chat page displaying authenticated user handle - Configure headless mode for Magnitude testing Step 4: SurrealDB Schema & Permissions - Define JWT-based access control (HS512 algorithm) - Create user table with DID-based identity - Create node table with row-level security (users can only access their own data) - Create links_to relation table for graph edges - Define vector search index (1536 dimensions for gemini-embedding-001) - Add Docker Compose for local SurrealDB development 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
70 lines
1.6 KiB
TypeScript
70 lines
1.6 KiB
TypeScript
import jwt from 'jsonwebtoken';
|
|
|
|
export interface UserSession {
|
|
did: string;
|
|
handle: string;
|
|
iss: string;
|
|
aud: string;
|
|
exp: number;
|
|
iat: number;
|
|
}
|
|
|
|
/**
|
|
* Mints a new JWT for our application's session management.
|
|
* This token is what SurrealDB will validate.
|
|
*
|
|
* @param did - The user's canonical ATproto DID (e.g., "did:plc:...")
|
|
* @param handle - The user's Bluesky handle (e.g., "user.bsky.social")
|
|
* @returns A signed JWT string.
|
|
*/
|
|
export function mintSurrealJwt(did: string, handle: string): string {
|
|
const secret = process.env.SURREALDB_JWT_SECRET;
|
|
if (!secret) {
|
|
throw new Error('SURREALDB_JWT_SECRET is not set in environment.');
|
|
}
|
|
|
|
// This payload is critical. The `did` claim will be used
|
|
// in SurrealDB's PERMISSIONS clauses.
|
|
const payload = {
|
|
// Standard JWT claims
|
|
iss: 'Ponderants',
|
|
aud: 'SurrealDB',
|
|
|
|
// Custom claims
|
|
did: did,
|
|
handle: handle,
|
|
};
|
|
|
|
// Token expires in 7 days
|
|
const token = jwt.sign(payload, secret, {
|
|
algorithm: 'HS512',
|
|
expiresIn: '7d',
|
|
});
|
|
|
|
return token;
|
|
}
|
|
|
|
/**
|
|
* Verifies and decodes a JWT token.
|
|
*
|
|
* @param token - The JWT token to verify
|
|
* @returns The decoded user session, or null if invalid
|
|
*/
|
|
export function verifySurrealJwt(token: string): UserSession | null {
|
|
const secret = process.env.SURREALDB_JWT_SECRET;
|
|
if (!secret) {
|
|
throw new Error('SURREALDB_JWT_SECRET is not set in environment.');
|
|
}
|
|
|
|
try {
|
|
const decoded = jwt.verify(token, secret, {
|
|
algorithms: ['HS512'],
|
|
}) as UserSession;
|
|
|
|
return decoded;
|
|
} catch (error) {
|
|
console.error('JWT verification failed:', error);
|
|
return null;
|
|
}
|
|
}
|