@@ -149,14 +149,113 @@ async function getActiveUserBlocking() {
149149 }
150150}
151151
152+ class RefreshIdpTokenResult {
153+ idpConfigId ;
154+ idToken ;
155+ }
156+
152157class TokenRefreshHandlerImpl {
158+ /**
159+ * Opens a popup to get a 3P ID token and Config ID from the user.
160+ * @returns {Promise<RefreshIdpTokenResult> } A promise that resolves with the result object.
161+ */
153162 refreshToken ( ) {
154- log ( "inside here" ) ;
155- console . log ( "inside handler" ) ;
156- return ;
163+ log ( 'inside here' ) ;
164+ console . log ( 'inside handler - opening popup for 3p token' ) ;
165+
166+ // This function handles the popup logic and returns the required object
167+ return this . promptForTokenAndConfigId ( ) ;
168+ }
169+
170+ /**
171+ * Opens a Bootstrap modal to ask the user for an ID token and IDP Config ID.
172+ *
173+ * This function dynamically creates a modal, shows it, and waits for
174+ * user input. It returns a Promise that resolves or rejects based
175+ * on the user's action.
176+ *
177+ * @returns {Promise<RefreshIdpTokenResult> } A promise that resolves with the
178+ * RefreshIdpTokenResult object, or rejects if the user cancels.
179+ */
180+ promptForTokenAndConfigId ( ) {
181+ // We return a Promise that will be resolved/rejected by the modal's buttons
182+ return new Promise ( ( resolve , reject ) => {
183+ // A flag to track if the promise has been settled
184+ let isSubmitted = false ;
185+ const modalId = 'third-party-token-modal' ;
186+
187+ // 1. Define Modal HTML with two input fields
188+ const modalHtml = `
189+ <div class="modal fade" id="${ modalId } " tabindex="-1" role="dialog" aria-labelledby="tokenModalLabel">
190+ <div class="modal-dialog" role="document">
191+ <div class="modal-content">
192+ <div class="modal-header">
193+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
194+ <span aria-hidden="true">×</span>
195+ </button>
196+ <h4 class="modal-title" id="tokenModalLabel">Enter 3P Token Details</h4>
197+ </div>
198+ <div class="modal-body">
199+ <p>Please enter the third-party token details:</p>
200+ <div class="form-group">
201+ <label for="idp-config-id-input-field">IDP Config ID</label>
202+ <input type="text" class="form-control" id="idp-config-id-input-field" placeholder="eg: idp.example.com">
203+ </div>
204+ <div class="form-group">
205+ <label for="id-token-input-field">ID Token</label>
206+ <input type="text" class="form-control" id="id-token-input-field" placeholder="Paste ID Token here">
207+ </div>
208+ </div>
209+ <div class="modal-footer">
210+ <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
211+ <button type="button" class="btn btn-primary" id="token-submit-btn">Submit</button>
212+ </div>
213+ </div>
214+ </div>
215+ </div>
216+ ` ;
217+
218+ // 2. Append modal to body and get a jQuery reference
219+ $ ( 'body' ) . append ( modalHtml ) ;
220+ const $modal = $ ( `#${ modalId } ` ) ;
221+
222+ // 3. Setup Event Handlers
223+
224+ // Handle Submit button click
225+ $modal . find ( '#token-submit-btn' ) . on ( 'click' , ( ) => {
226+ isSubmitted = true ;
227+
228+ // Read values from *both* input fields
229+ const configId = $modal . find ( '#idp-config-id-input-field' ) . val ( ) ;
230+ const token = $modal . find ( '#id-token-input-field' ) . val ( ) ;
231+
232+ $modal . modal ( 'hide' ) ; // Hide the modal
233+
234+ // Create the result object as requested
235+ const result = new RefreshIdpTokenResult ( ) ;
236+ result . idpConfigId = configId ;
237+ result . idToken = token ;
238+
239+ resolve ( result ) ; // Resolve the promise with the object
240+ } ) ;
241+
242+ // Handle modal being closed (by 'x', 'Cancel' button, backdrop click, or ESC)
243+ $modal . on ( 'hidden.bs.modal' , ( ) => {
244+ $modal . remove ( ) ; // Clean up the modal from the DOM
245+
246+ // If the modal was hidden *without* submitting, reject the promise
247+ if ( ! isSubmitted ) {
248+ reject ( new Error ( 'User cancelled token input.' ) ) ;
249+ }
250+ } ) ;
251+
252+ // 4. Show the modal
253+ $modal . modal ( 'show' ) ;
254+ } ) ;
157255 }
158256}
159257
258+
160259/**
161260 * Refreshes the current user data in the UI, displaying a user info box if
162261 * a user is signed in, or removing it.
@@ -1528,16 +1627,17 @@ async function exchangeCIAMToken(token) {
15281627function onExchangeToken ( event ) {
15291628 event . preventDefault ( ) ;
15301629 const byoCiamInput = document . getElementById ( 'byo-ciam-token' ) ;
1531- const byoCiamResult = document . getElementById ( 'byo-ciam-result ' ) ;
1630+ const firebaseTokenStatus = document . getElementById ( 'firebase-token-status ' ) ;
15321631
1533- byoCiamResult . textContent = 'Exchanging token...' ;
1632+ firebaseTokenStatus . textContent = 'Exchanging token...' ;
15341633
15351634 exchangeCIAMToken ( byoCiamInput . value )
15361635 . then ( response => {
1537- byoCiamResult . textContent = response ;
1636+ firebaseTokenStatus . textContent = '✅ Firebase token is set: ' + response ;
15381637 console . log ( 'Token:' , response ) ;
15391638 } )
15401639 . catch ( error => {
1640+ ( firebaseTokenStatus . textContent = 'Error exchanging token: ' ) , error ;
15411641 console . error ( 'Error exchanging token:' , error ) ;
15421642 } ) ;
15431643}
@@ -2101,6 +2201,19 @@ function initApp() {
21012201 const tokenRefreshHandler = new TokenRefreshHandlerImpl ( ) ;
21022202 regionalAuth . setTokenRefreshHandler ( tokenRefreshHandler ) ;
21032203
2204+ const firebaseTokenStatus = document . getElementById ( 'firebase-token-status' ) ;
2205+ setTimeout ( ( ) => {
2206+ if ( regionalAuth . firebaseToken ) {
2207+ firebaseTokenStatus . textContent =
2208+ '✅ Firebase token is set: ' + regionalAuth . firebaseToken . token ;
2209+ } else {
2210+ firebaseTokenStatus . textContent =
2211+ 'No CIAM token found. User not logged in.' ;
2212+ }
2213+ console . log ( 'firebaseToken after delay: ' , regionalAuth . firebaseToken ) ;
2214+ } , 1000 ) ;
2215+
2216+
21042217 tempApp = initializeApp (
21052218 {
21062219 apiKey : config . apiKey ,
0 commit comments