@@ -239,18 +239,12 @@ pub struct JwtTokenMap {
239239 /// The algorithm used to sign and verify JWT tokens.
240240 /// Default is HS256 (HMAC with SHA-256).
241241 algorithm : Algorithm ,
242-
242+
243243 /// Additional claims to include in tokens
244244 ///
245245 /// This allows adding extra claims to the JWT tokens being generated.
246246 /// Used for including user-specific information in tokens.
247247 claims : HashMap < String , Value > ,
248-
249- /// Token hook for extensibility
250- ///
251- /// A callback function that allows modifying token responses during issuance.
252- /// Used for enriching tokens with additional data.
253- token_hook : Option < Box < dyn FnMut ( & mut oxide_auth:: code_grant:: accesstoken:: TokenResponse ) + Send > > ,
254248}
255249
256250impl JwtTokenMap {
@@ -267,7 +261,6 @@ impl JwtTokenMap {
267261 usage_counter : 0 ,
268262 algorithm : Algorithm :: HS256 , // Default to HMAC-SHA256
269263 claims : HashMap :: new ( ) ,
270- token_hook : None ,
271264 }
272265 }
273266
@@ -288,7 +281,6 @@ impl JwtTokenMap {
288281 usage_counter : 0 ,
289282 algorithm,
290283 claims : HashMap :: new ( ) ,
291- token_hook : None ,
292284 }
293285 }
294286
@@ -320,7 +312,6 @@ impl JwtTokenMap {
320312 usage_counter : 0 ,
321313 algorithm : Algorithm :: RS256 ,
322314 claims : HashMap :: new ( ) ,
323- token_hook : None ,
324315 } )
325316 }
326317
@@ -342,9 +333,40 @@ impl JwtTokenMap {
342333 self
343334 }
344335
345- /// Create JWT claims from a grant
336+ /// Add user information to token claims that will be included in the next issued token
337+ pub fn add_user_claims ( & mut self , username : & str , permissions : & [ String ] ) -> & mut Self {
338+ // Clear previous user claims to avoid accumulation
339+ self . claims . retain ( |key, _| !key. starts_with ( "user_" ) ) ;
340+
341+ // Add user information to claims that will be included in JWT
342+ self . claims . insert (
343+ "user_id" . to_string ( ) ,
344+ Value :: public ( Some ( username. to_string ( ) ) )
345+ ) ;
346+
347+ // Add permissions as a space-separated string
348+ let perms_str = permissions. join ( " " ) ;
349+ self . claims . insert (
350+ "user_permissions" . to_string ( ) ,
351+ Value :: public ( Some ( perms_str) )
352+ ) ;
353+
354+ // Common identity claims
355+ self . claims . insert (
356+ "preferred_username" . to_string ( ) ,
357+ Value :: public ( Some ( username. to_string ( ) ) ) ,
358+ ) ;
359+ self . claims . insert (
360+ "user_name" . to_string ( ) ,
361+ Value :: public ( Some ( username. to_string ( ) ) ) ,
362+ ) ;
363+
364+ self
365+ }
366+
367+ /// Create JWT claims from a grant, including any additional user claims
346368 fn create_claims ( & self , grant : & Grant , now : DateTime < Utc > , expiry : DateTime < Utc > ) -> JwtClaims {
347- // Create a map for any public extensions
369+ // Create a map for any public extensions and additional claims
348370 let mut metadata = HashMap :: new ( ) ;
349371
350372 // Add grant extensions to metadata
@@ -356,12 +378,18 @@ impl JwtTokenMap {
356378 }
357379 }
358380
359- // Add any additional claims
381+ // Add any additional claims (including user claims)
360382 for ( key, value) in & self . claims {
361- if let Some ( val) = value {
362- metadata. insert ( key. to_string ( ) , val. to_string ( ) ) ;
363- } else {
364- metadata. insert ( key. to_string ( ) , "true" . to_string ( ) ) ;
383+ match value {
384+ Value :: Public ( Some ( val) ) => {
385+ metadata. insert ( key. to_string ( ) , val. to_string ( ) ) ;
386+ }
387+ Value :: Public ( None ) => {
388+ metadata. insert ( key. to_string ( ) , "true" . to_string ( ) ) ;
389+ }
390+ Value :: Private ( _) => {
391+ // Skip private values
392+ }
365393 }
366394 }
367395
@@ -387,27 +415,6 @@ impl JwtTokenMap {
387415 } ,
388416 }
389417 }
390-
391- /// Add user information to token claims
392- pub fn add_user_claims ( & mut self , username : & str , permissions : & [ String ] ) -> & mut Self {
393- // Add user information to claims
394- self . claims . insert ( "sub" . to_string ( ) , Value :: public ( Some ( username. to_string ( ) ) ) ) ;
395-
396- // Add permissions as a space-separated string
397- let perms_str = permissions. join ( " " ) ;
398- self . claims . insert ( "permissions" . to_string ( ) , Value :: public ( Some ( perms_str) ) ) ;
399-
400- // Common identity claims
401- self . claims . insert ( "preferred_username" . to_string ( ) , Value :: public ( Some ( username. to_string ( ) ) ) ) ;
402- self . claims . insert ( "name" . to_string ( ) , Value :: public ( Some ( username. to_string ( ) ) ) ) ;
403-
404- self
405- }
406-
407- /// Set a token hook function
408- pub fn set_token_hook ( & mut self , hook : Box < dyn FnMut ( & mut oxide_auth:: code_grant:: accesstoken:: TokenResponse ) + Send > ) {
409- self . token_hook = Some ( hook) ;
410- }
411418}
412419
413420impl Issuer for JwtTokenMap {
@@ -418,7 +425,7 @@ impl Issuer for JwtTokenMap {
418425 grant. until = now + duration;
419426 }
420427
421- // Generate claims
428+ // Generate claims (this now includes user claims automatically)
422429 let claims = self . create_claims ( & grant, now, grant. until ) ;
423430
424431 // Create JWT token with specific algorithm
@@ -446,25 +453,16 @@ impl Issuer for JwtTokenMap {
446453 }
447454
448455 // Create the token response
449- let mut token = IssuedToken {
456+ let token = IssuedToken {
450457 token : access_token,
451458 refresh : refresh_token,
452459 until : grant. until ,
453460 token_type : TokenType :: Bearer ,
454461 } ;
455462
456- // Apply token hook if present
457- if let Some ( hook) = & mut self . token_hook {
458- // Convert IssuedToken to TokenResponse for the hook
459- let mut token_response = oxide_auth:: code_grant:: accesstoken:: TokenResponse :: from ( token. clone ( ) ) ;
460-
461- // Call the hook with our token response
462- hook ( & mut token_response) ;
463-
464- // No need to convert back as we already have our IssuedToken
465- }
463+ // Clear user claims after use to prevent them from being included in subsequent tokens
464+ self . claims . retain ( |key, _| !key. starts_with ( "user_" ) ) ;
466465
467- // Return the issued token
468466 Ok ( token)
469467 }
470468
@@ -527,25 +525,16 @@ impl Issuer for JwtTokenMap {
527525 }
528526
529527 // Create the refreshed token
530- let mut token = RefreshedToken {
528+ let token = RefreshedToken {
531529 token : new_access_token,
532530 refresh : new_refresh_token,
533531 until : grant. until ,
534532 token_type : TokenType :: Bearer ,
535533 } ;
536534
537- // Apply token hook if present
538- if let Some ( hook) = & mut self . token_hook {
539- // Convert RefreshedToken to TokenResponse for the hook
540- let mut token_response = oxide_auth:: code_grant:: accesstoken:: TokenResponse :: from ( token. clone ( ) ) ;
541-
542- // Call the hook with our token response
543- hook ( & mut token_response) ;
544-
545- // No need to convert back as we already have our RefreshedToken
546- }
535+ // Clear user claims after use
536+ self . claims . retain ( |key, _| !key. starts_with ( "user_" ) ) ;
547537
548- // Return the refreshed token
549538 Ok ( token)
550539 }
551540
@@ -711,12 +700,6 @@ impl JwtIssuer {
711700 }
712701 self
713702 }
714-
715- /// Set a token hook function
716- pub fn set_token_hook ( & mut self , hook : Box < dyn FnMut ( & mut oxide_auth:: code_grant:: accesstoken:: TokenResponse ) + Send > ) {
717- let mut map = self . 0 . lock ( ) . unwrap ( ) ;
718- map. set_token_hook ( hook) ;
719- }
720703
721704 /// Print the decoded contents of a JWT token for debugging purposes
722705 /// Returns Ok if the token could be decoded, Err otherwise
0 commit comments