@@ -662,6 +662,65 @@ export async function getKeycloakToken(): Promise<string> {
662662 return data . access_token ;
663663}
664664
665+ async function getExistingKeycloakUserId (
666+ keycloakDomain : string ,
667+ keycloakRealm : string ,
668+ username : string
669+ ) : Promise < string > {
670+ // User already exists in Keycloak — look up their ID so we can still update the DB.
671+ // Without this, keycloakUserId stays empty and login silently falls through to Supabase.
672+ logger . log ( `⚠️ User ${ username } already exists in Keycloak — looking up existing user ID` ) ;
673+ const lookupToken = await getKeycloakToken ( ) ;
674+ const lookupRes = await fetch (
675+ `${ keycloakDomain } admin/realms/${ keycloakRealm } /users?username=${ encodeURIComponent ( username ) } &exact=true` ,
676+ {
677+ headers : { Authorization : `Bearer ${ lookupToken } ` }
678+ }
679+ ) ;
680+ if ( ! lookupRes . ok ) {
681+ const errText = await lookupRes . text ( ) ;
682+ throw new Error ( `Failed to look up existing Keycloak user (${ lookupRes . status } ): ${ errText } ` ) ;
683+ }
684+ const existingUsers = await lookupRes . json ( ) ;
685+ if ( ! Array . isArray ( existingUsers ) || 0 === existingUsers . length ) {
686+ throw new Error ( `Keycloak returned 409 but no user found for username: ${ username } ` ) ;
687+ }
688+ const userId = existingUsers [ 0 ] . id ;
689+ logger . log ( `✅ Found existing Keycloak user ID: ${ userId } ` ) ;
690+ return userId ;
691+ }
692+
693+ async function updatePlatformAdminInDb (
694+ userId : string ,
695+ adminKeycloakId : string ,
696+ adminKeycloakSecret : string ,
697+ cryptoPrivateKey : string
698+ ) : Promise < void > {
699+ logger . log ( 'Check if platform admin exists' ) ;
700+ const existingUser = await prisma . user . findUnique ( {
701+ where : { email : cachedConfig . platformEmail }
702+ } ) ;
703+
704+ if ( ! existingUser ) {
705+ throw new Error ( `User with email ${ cachedConfig . platformEmail } not found in database` ) ;
706+ }
707+ logger . log ( `✅ Platform admin found in database` ) ;
708+
709+ const encClientId = CryptoJS . AES . encrypt ( JSON . stringify ( adminKeycloakId ) , cryptoPrivateKey ) . toString ( ) ;
710+
711+ const encClientSecret = CryptoJS . AES . encrypt ( JSON . stringify ( adminKeycloakSecret ) , cryptoPrivateKey ) . toString ( ) ;
712+
713+ await prisma . user . update ( {
714+ where : { email : cachedConfig . platformEmail } ,
715+ data : {
716+ keycloakUserId : userId ,
717+ clientId : encClientId ,
718+ clientSecret : encClientSecret
719+ }
720+ } ) ;
721+ logger . log ( `✅ Platform admin keycloakUserId, clientId, clientSecret updated in DB successfully` ) ;
722+ }
723+
665724export async function createKeycloakUser ( ) : Promise < void > {
666725 logger . log ( `✅ Creating keycloak user for platform admin` ) ;
667726 const { platformAdminData } = JSON . parse ( configData ) ;
@@ -731,26 +790,7 @@ export async function createKeycloakUser(): Promise<void> {
731790 let userId : string | undefined ;
732791
733792 if ( HttpStatus . CONFLICT === res . status ) {
734- // User already exists in Keycloak — look up their ID so we can still update the DB.
735- // Without this, keycloakUserId stays empty and login silently falls through to Supabase.
736- logger . log ( `⚠️ User ${ user . username } already exists in Keycloak — looking up existing user ID` ) ;
737- const lookupToken = await getKeycloakToken ( ) ;
738- const lookupRes = await fetch (
739- `${ KEYCLOAK_DOMAIN } admin/realms/${ KEYCLOAK_REALM } /users?username=${ encodeURIComponent ( user . username ) } &exact=true` ,
740- {
741- headers : { Authorization : `Bearer ${ lookupToken } ` }
742- }
743- ) ;
744- if ( ! lookupRes . ok ) {
745- const errText = await lookupRes . text ( ) ;
746- throw new Error ( `Failed to look up existing Keycloak user (${ lookupRes . status } ): ${ errText } ` ) ;
747- }
748- const existingUsers = await lookupRes . json ( ) ;
749- if ( ! Array . isArray ( existingUsers ) || 0 === existingUsers . length ) {
750- throw new Error ( `Keycloak returned 409 but no user found for username: ${ user . username } ` ) ;
751- }
752- userId = existingUsers [ 0 ] . id ;
753- logger . log ( `✅ Found existing Keycloak user ID: ${ userId } ` ) ;
793+ userId = await getExistingKeycloakUserId ( KEYCLOAK_DOMAIN , KEYCLOAK_REALM , user . username ) ;
754794 } else if ( HttpStatus . CREATED !== res . status ) {
755795 const errorText = await res . text ( ) ;
756796 throw new Error ( `Failed to create Keycloak user (${ res . status } ): ${ errorText } ` ) ;
@@ -763,29 +803,7 @@ export async function createKeycloakUser(): Promise<void> {
763803 }
764804
765805 if ( userId ) {
766- logger . log ( 'Check if platform admin exists' ) ;
767- const existingUser = await prisma . user . findUnique ( {
768- where : { email : cachedConfig . platformEmail }
769- } ) ;
770-
771- if ( ! existingUser ) {
772- throw new Error ( `User with email ${ cachedConfig . platformEmail } not found in database` ) ;
773- }
774- logger . log ( `✅ Platform admin found in database` ) ;
775-
776- const encClientId = CryptoJS . AES . encrypt ( JSON . stringify ( ADMIN_KEYCLOAK_ID ) , CRYPTO_PRIVATE_KEY ) . toString ( ) ;
777-
778- const encClientSecret = CryptoJS . AES . encrypt ( JSON . stringify ( ADMIN_KEYCLOAK_SECRET ) , CRYPTO_PRIVATE_KEY ) . toString ( ) ;
779-
780- await prisma . user . update ( {
781- where : { email : cachedConfig . platformEmail } ,
782- data : {
783- keycloakUserId : userId ,
784- clientId : encClientId ,
785- clientSecret : encClientSecret
786- }
787- } ) ;
788- logger . log ( `✅ Platform admin keycloakUserId, clientId, clientSecret updated in DB successfully` ) ;
806+ await updatePlatformAdminInDb ( userId , ADMIN_KEYCLOAK_ID , ADMIN_KEYCLOAK_SECRET , CRYPTO_PRIVATE_KEY ) ;
789807 } else {
790808 throw new Error ( 'Failed to extract user ID from Location header' ) ;
791809 }
0 commit comments