Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/auth/demo/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,7 @@
<div class="tab-pane" id="tab-byo-ciam-content">
<h2>Sign in with your CIAM token</h2>
<div id="firebase-token-status">No CIAM token found. User not logged in.</div>
<input type="text" id="idp-config-id" class="form-control" placeholder="IDP Config ID" />
<input type="text" id="byo-ciam-token"
class="form-control" placeholder="Enter CIAM token" />
<button class="btn btn-block btn-primary"
Expand Down
119 changes: 112 additions & 7 deletions packages/auth/demo/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,112 @@ async function getActiveUserBlocking() {
}
}

class RefreshIdpTokenResult {
idpConfigId;
idToken;
}

class TokenRefreshHandlerImpl {
/**
* Opens a popup to get a 3P ID token and Config ID from the user.
* @returns {Promise<RefreshIdpTokenResult>} A promise that resolves with the result object.
*/
refreshIdpToken() {
log('inside here');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Do we need this or can we do it more descriptive?

console.log('inside handler - opening popup for 3p token');

// This function handles the popup logic and returns the required object
return this.promptForTokenAndConfigId();
}

/**
* Opens a Bootstrap modal to ask the user for an ID token and IDP Config ID.
*
* This function dynamically creates a modal, shows it, and waits for
* user input. It returns a Promise that resolves or rejects based
* on the user's action.
*
* @returns {Promise<RefreshIdpTokenResult>} A promise that resolves with the
* RefreshIdpTokenResult object, or rejects if the user cancels.
*/
promptForTokenAndConfigId() {
// We return a Promise that will be resolved/rejected by the modal's buttons
return new Promise((resolve, reject) => {
// A flag to track if the promise has been settled
let isSubmitted = false;
const modalId = 'third-party-token-modal';

// 1. Define Modal HTML with two input fields
const modalHtml = `
<div class="modal fade" id="${modalId}" tabindex="-1" role="dialog" aria-labelledby="tokenModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title" id="tokenModalLabel">Enter 3P Token Details</h4>
</div>
<div class="modal-body">
<p>Please enter the third-party token details:</p>
<div class="form-group">
<label for="idp-config-id-input-field">IDP Config ID</label>
<input type="text" class="form-control" id="idp-config-id-input-field" placeholder="eg: idp.example.com">
</div>
<div class="form-group">
<label for="id-token-input-field">ID Token</label>
<input type="text" class="form-control" id="id-token-input-field" placeholder="Paste ID Token here">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="token-submit-btn">Submit</button>
</div>
</div>
</div>
</div>
`;

// 2. Append modal to body and get a jQuery reference
$('body').append(modalHtml);
const $modal = $(`#${modalId}`);

// 3. Setup Event Handlers

// Handle Submit button click
$modal.find('#token-submit-btn').on('click', () => {
isSubmitted = true;

// Read values from *both* input fields
const configId = $modal.find('#idp-config-id-input-field').val();
const token = $modal.find('#id-token-input-field').val();

$modal.modal('hide'); // Hide the modal

// Create the result object as requested
const result = new RefreshIdpTokenResult();
result.idpConfigId = configId;
result.idToken = token;

resolve(result); // Resolve the promise with the object
});

// Handle modal being closed (by 'x', 'Cancel' button, backdrop click, or ESC)
$modal.on('hidden.bs.modal', () => {
$modal.remove(); // Clean up the modal from the DOM

// If the modal was hidden *without* submitting, reject the promise
if (!isSubmitted) {
reject(new Error('User cancelled token input.'));
}
});

// 4. Show the modal
$modal.modal('show');
});
}
}

/**
* Refreshes the current user data in the UI, displaying a user info box if
* a user is signed in, or removing it.
Expand Down Expand Up @@ -1509,23 +1615,20 @@ function onFinalizeSignInWithTotpMultiFactor(event) {
}, onAuthError);
}

async function exchangeCIAMToken(token) {
const firebaseToken = await exchangeToken(
regionalAuth,
(idpConfigId = 'Bar-e2e-idpconfig-002'),
token
);
async function exchangeCIAMToken(idpConfigId, token) {
const firebaseToken = await exchangeToken(regionalAuth, idpConfigId, token);
return firebaseToken;
}

function onExchangeToken(event) {
event.preventDefault();
const byoCiamInput = document.getElementById('byo-ciam-token');
const idpConfigId = document.getElementById('idp-config-id');
const firebaseTokenStatus = document.getElementById('firebase-token-status');

firebaseTokenStatus.textContent = 'Exchanging token...';

exchangeCIAMToken(byoCiamInput.value)
exchangeCIAMToken(idpConfigId.value, byoCiamInput.value)
.then(response => {
firebaseTokenStatus.textContent = '✅ Firebase token is set: ' + response;
console.log('Token:', response);
Expand Down Expand Up @@ -2092,6 +2195,8 @@ function initApp() {
popupRedirectResolver: browserPopupRedirectResolver,
tenantConfig: tenantConfig
});
const tokenRefreshHandler = new TokenRefreshHandlerImpl();
regionalAuth.setTokenRefreshHandler(tokenRefreshHandler);

const firebaseTokenStatus = document.getElementById('firebase-token-status');
setTimeout(async () => {
Expand Down
Loading