@@ -74,8 +74,15 @@ export class SsoService {
7474 try {
7575 this . logger . log ( `Starting SSO authentication for provider: ${ ssoRequestDto . ssoProvider } ` , 'SSO_SERVICE' ) ;
7676
77- // Step 1: Apply default values if not provided
78- if ( ! ssoRequestDto . tenantId ) {
77+ // Step 1: Validate tenantId if provided, otherwise apply default
78+ if ( ssoRequestDto . tenantId ) {
79+ // Validate UUID format
80+ const uuidRegex = / ^ [ 0 - 9 a - f ] { 8 } - [ 0 - 9 a - f ] { 4 } - [ 0 - 9 a - f ] { 4 } - [ 0 - 9 a - f ] { 4 } - [ 0 - 9 a - f ] { 12 } $ / i;
81+ if ( ! uuidRegex . test ( ssoRequestDto . tenantId ) ) {
82+ throw new HttpException ( 'Please enter valid Tenant UUID In URL' , HttpStatus . BAD_REQUEST ) ;
83+ }
84+ this . logger . log ( `Using provided tenant ID: ${ ssoRequestDto . tenantId } ` , 'SSO_SERVICE' ) ;
85+ } else {
7986 ssoRequestDto . tenantId = SSO_DEFAULTS . DEFAULT_TENANT_ID ;
8087 this . logger . log ( `Using default tenant ID: ${ SSO_DEFAULTS . DEFAULT_TENANT_ID } ` , 'SSO_SERVICE' ) ;
8188 }
@@ -304,6 +311,9 @@ export class SsoService {
304311
305312 //Map User to Role and Tenant
306313
314+ // Sanitize userId for use in custom fields
315+ const sanitizedNewtonUserId = this . sanitizeUUID ( newtonResponse . userId ) || createdUser . userId ;
316+
307317 // Update custom fields if newtonData is available
308318 if ( newtonResponse . newtonData && Object . keys ( newtonResponse . newtonData ) . length > 0 ) {
309319 for ( const [ fieldLabel , fieldValue ] of Object . entries ( newtonResponse . newtonData ) ) {
@@ -318,8 +328,8 @@ export class SsoService {
318328 {
319329 tenantId : ssoRequestDto . tenantId ,
320330 contextType : "USER" ,
321- createdBy : newtonResponse . userId ,
322- updatedBy : newtonResponse . userId
331+ createdBy : sanitizedNewtonUserId ,
332+ updatedBy : sanitizedNewtonUserId
323333 }
324334 ) ;
325335 }
@@ -354,6 +364,45 @@ export class SsoService {
354364 }
355365 }
356366
367+ /**
368+ * Sanitize and validate UUID by removing invalid characters
369+ * @param uuid - UUID string that may contain invalid characters
370+ * @returns Sanitized UUID string or null if invalid
371+ */
372+ private sanitizeUUID ( uuid : string | undefined | null ) : string | null {
373+ if ( ! uuid || typeof uuid !== 'string' ) {
374+ return null ;
375+ }
376+
377+ // Remove any trailing/leading whitespace and invalid characters
378+ // UUID format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
379+ // Remove any characters that are not valid UUID characters (hex digits and hyphens)
380+ let sanitized = uuid . trim ( ) ;
381+
382+ // Remove any trailing special characters (like asterisks, spaces, etc.)
383+ sanitized = sanitized . replace ( / [ ^ a - f A - F 0 - 9 - ] + $ / , '' ) ;
384+
385+ // Remove any leading special characters
386+ sanitized = sanitized . replace ( / ^ [ ^ a - f A - F 0 - 9 ] + / , '' ) ;
387+
388+ // Remove any invalid characters within the UUID (keep only hex digits and hyphens)
389+ sanitized = sanitized . replace ( / [ ^ a - f A - F 0 - 9 - ] / g, '' ) ;
390+
391+ // Validate UUID format: should be 8-4-4-4-12 hex digits separated by hyphens
392+ const uuidRegex = / ^ [ 0 - 9 a - f ] { 8 } - [ 0 - 9 a - f ] { 4 } - [ 0 - 9 a - f ] { 4 } - [ 0 - 9 a - f ] { 4 } - [ 0 - 9 a - f ] { 12 } $ / i;
393+
394+ if ( uuidRegex . test ( sanitized ) ) {
395+ return sanitized ;
396+ }
397+
398+ this . logger . warn (
399+ `Invalid UUID format after sanitization: ${ uuid } -> ${ sanitized } ` ,
400+ 'SSO_SERVICE'
401+ ) ;
402+
403+ return null ;
404+ }
405+
357406 /**
358407 * Map Newton API response to UserCreateDto with name parsing
359408 * @param newtonResponse - Newton API response
@@ -374,8 +423,31 @@ export class SsoService {
374423 EMAIL : newtonResponse . email || ''
375424 } ;
376425
426+ // Sanitize userId from Newton response or userData
427+ const rawUserId = newtonResponse . userId || userData . USER_ID ;
428+ const sanitizedUserId = this . sanitizeUUID ( rawUserId ) ;
429+
430+ if ( ! sanitizedUserId ) {
431+ this . logger . error (
432+ `Invalid userId received from Newton API: ${ rawUserId } . Cannot create user.` ,
433+ 'SSO_SERVICE'
434+ ) ;
435+ throw new HttpException (
436+ `Invalid user ID format received from authentication service: ${ rawUserId } ` ,
437+ HttpStatus . BAD_REQUEST
438+ ) ;
439+ }
440+
441+ // Log if sanitization changed the value
442+ if ( rawUserId !== sanitizedUserId ) {
443+ this . logger . warn (
444+ `UserId sanitized: "${ rawUserId } " -> "${ sanitizedUserId } "` ,
445+ 'SSO_SERVICE'
446+ ) ;
447+ }
448+
377449 return {
378- userId : newtonResponse . userId || userData . USER_ID ,
450+ userId : sanitizedUserId ,
379451 username : newtonResponse . email || userData . EMAIL ,
380452 firstName : firstName ,
381453 middleName : undefined ,
@@ -391,8 +463,8 @@ export class SsoService {
391463 password : undefined , // No password for SSO users
392464 createdAt : new Date ( ) . toISOString ( ) ,
393465 updatedAt : new Date ( ) . toISOString ( ) ,
394- createdBy : newtonResponse . userId , // Use the Newton user ID as creator
395- updatedBy : newtonResponse . userId , // Use the Newton user ID as updater
466+ createdBy : sanitizedUserId , // Use the sanitized Newton user ID as creator
467+ updatedBy : sanitizedUserId , // Use the sanitized Newton user ID as updater
396468 customFields : [ ] ,
397469 automaticMember : undefined ,
398470 tenantCohortRoleMapping : [ {
@@ -527,18 +599,40 @@ export class SsoService {
527599
528600
529601 // Use decoded userId if available, otherwise fallback to newtonResponse.userId or ssoRequestDto.userId
530- const userId = newtonResponse . userId || ssoRequestDto . userId ;
602+ const rawUserId = newtonResponse . userId || ssoRequestDto . userId ;
531603
532- if ( ! userId ) {
604+ if ( ! rawUserId ) {
533605 this . logger . error ( 'No userId available for existing user' , 'SSO_SERVICE' ) ;
534606 throw new HttpException (
535607 'Unable to determine user ID for existing user' ,
536608 HttpStatus . BAD_REQUEST
537609 ) ;
538610 }
539611
612+ // Sanitize userId to remove any invalid characters
613+ const userId = this . sanitizeUUID ( rawUserId ) ;
614+
615+ if ( ! userId ) {
616+ this . logger . error (
617+ `Invalid userId format for existing user: ${ rawUserId } ` ,
618+ 'SSO_SERVICE'
619+ ) ;
620+ throw new HttpException (
621+ `Invalid user ID format: ${ rawUserId } ` ,
622+ HttpStatus . BAD_REQUEST
623+ ) ;
624+ }
625+
626+ // Log if sanitization changed the value
627+ if ( rawUserId !== userId ) {
628+ this . logger . warn (
629+ `UserId sanitized for existing user: "${ rawUserId } " -> "${ userId } "` ,
630+ 'SSO_SERVICE'
631+ ) ;
632+ }
633+
540634 this . logger . log (
541- `Processing existing user: ${ userId } ) ` ,
635+ `Processing existing user: ${ userId } ` ,
542636 'SSO_SERVICE'
543637 ) ;
544638
0 commit comments