@@ -9,6 +9,15 @@ import type {
99} from '../types/auth' ;
1010
1111export class NostrBiometricServer {
12+ /** Maximum number of concurrent sessions before cleanup is triggered */
13+ private static readonly MAX_SESSIONS = 10000 ;
14+ /** Session time-to-live: 24 hours */
15+ private static readonly SESSION_TTL = 24 * 60 * 60 * 1000 ;
16+ /** Maximum number of concurrent magic links before cleanup is triggered */
17+ private static readonly MAX_MAGIC_LINKS = 10000 ;
18+ /** Magic link time-to-live: 1 hour */
19+ private static readonly MAGIC_LINK_TTL = 60 * 60 * 1000 ;
20+
1221 private options : AuthenticationOptions ;
1322 private magicLinks : Map < string , MagicLinkPayload > ;
1423 private sessions : Map < string , SessionToken > ;
@@ -19,11 +28,62 @@ export class NostrBiometricServer {
1928 this . sessions = new Map ( ) ;
2029 }
2130
31+ /**
32+ * Remove expired sessions to free up space
33+ */
34+ private cleanupExpiredSessions ( ) : void {
35+ const now = Date . now ( ) ;
36+ for ( const [ key , session ] of this . sessions ) {
37+ if ( now - session . createdAt > NostrBiometricServer . SESSION_TTL || now > session . expiresAt ) {
38+ this . sessions . delete ( key ) ;
39+ }
40+ }
41+ }
42+
43+ /**
44+ * Remove expired magic links to free up space
45+ */
46+ private cleanupExpiredMagicLinks ( ) : void {
47+ const now = Date . now ( ) ;
48+ for ( const [ key , link ] of this . magicLinks ) {
49+ if ( now - link . createdAt > NostrBiometricServer . MAGIC_LINK_TTL || now > link . expiresAt ) {
50+ this . magicLinks . delete ( key ) ;
51+ }
52+ }
53+ }
54+
55+ /**
56+ * Enforce session map size limit, cleaning up expired entries first
57+ * @throws Error if limit is still exceeded after cleanup
58+ */
59+ private enforceSessionLimit ( ) : void {
60+ if ( this . sessions . size >= NostrBiometricServer . MAX_SESSIONS ) {
61+ this . cleanupExpiredSessions ( ) ;
62+ if ( this . sessions . size >= NostrBiometricServer . MAX_SESSIONS ) {
63+ throw new Error ( 'Session limit reached' ) ;
64+ }
65+ }
66+ }
67+
68+ /**
69+ * Enforce magic link map size limit, cleaning up expired entries first
70+ * @throws Error if limit is still exceeded after cleanup
71+ */
72+ private enforceMagicLinkLimit ( ) : void {
73+ if ( this . magicLinks . size >= NostrBiometricServer . MAX_MAGIC_LINKS ) {
74+ this . cleanupExpiredMagicLinks ( ) ;
75+ if ( this . magicLinks . size >= NostrBiometricServer . MAX_MAGIC_LINKS ) {
76+ throw new Error ( 'Magic link limit reached' ) ;
77+ }
78+ }
79+ }
80+
2281 /**
2382 * Create and send a magic link for the given npub
2483 * @param npub The user's npub to authenticate
2584 */
2685 async createMagicLink ( npub : string ) : Promise < void > {
86+ this . enforceMagicLinkLimit ( ) ;
2787 // TODO: Implement magic link creation and sending
2888 }
2989
@@ -51,9 +111,10 @@ export class NostrBiometricServer {
51111 * @param response The WebAuthn response
52112 */
53113 async verifyWebAuthnAndCreateSession (
54- npub : string ,
114+ npub : string ,
55115 response : any
56116 ) : Promise < SessionToken > {
117+ this . enforceSessionLimit ( ) ;
57118 // TODO: Implement WebAuthn verification and session creation
58119 throw new Error ( 'Not implemented' ) ;
59120 }
0 commit comments