Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save felixguerrero12/8ff9f144b932a4b3d80711e0ef756be8 to your computer and use it in GitHub Desktop.

Select an option

Save felixguerrero12/8ff9f144b932a4b3d80711e0ef756be8 to your computer and use it in GitHub Desktop.
deviceCodeAuth.js
// deviceCodeAuth.js
import { showNotification } from '../modules/uiHelpers.js';
import { fetchPostRequest } from '../modules/api.js';
import { storeToken } from './insertToken.js';
let isDeviceCodeAuthInProgress = false;
export function initializeDeviceCodeAuth() {
const form = document.getElementById('deviceCodeAuthForm');
if (form) {
form.addEventListener('submit', handleDeviceCodeAuth);
}
const cancelButton = document.getElementById('cancelDeviceCodeAuth');
if (cancelButton) {
cancelButton.addEventListener('click', cancelDeviceCodeAuth);
}
// New code for handling custom client ID
const clientIdSelect = document.getElementById('clientIdSelect');
const customClientIdGroup = document.getElementById('customClientIdGroup');
const customClientIdInput = document.getElementById('customClientId');
if (clientIdSelect && customClientIdGroup && customClientIdInput) {
clientIdSelect.addEventListener('change', function() {
if (this.value === 'custom') {
customClientIdGroup.style.display = 'block';
customClientIdInput.setAttribute('required', 'required');
} else {
customClientIdGroup.style.display = 'none';
customClientIdInput.removeAttribute('required');
}
});
}
}
export function handleDeviceCodeAuth(e) {
e.preventDefault();
if (isDeviceCodeAuthInProgress) {
console.log('Device Code Auth already in progress');
return;
}
isDeviceCodeAuthInProgress = true;
const clientIdSelect = document.getElementById('clientIdSelect');
const customClientIdInput = document.getElementById('customClientId');
let clientId = clientIdSelect.value;
if (clientId === 'custom') {
clientId = customClientIdInput.value;
}
const tenant = document.getElementById('deviceCodeTenant').value || 'common';
const scope = document.getElementById('deviceCodeScope').value;
startDeviceCodeAuth(clientId, tenant, scope)
.finally(() => {
isDeviceCodeAuthInProgress = false;
});
}
export function startDeviceCodeAuth(clientId, tenant, scope) {
return fetchPostRequest('/device_code_auth', { client_id: clientId, tenant, scope })
.then(data => {
if (data.error) {
throw new Error(data.error);
}
displayDeviceCodeInfo(data);
return pollForToken(clientId, data.device_code, tenant, data.interval);
})
.catch(error => {
showNotification(`Error: ${error.message}`, 'error');
closeDeviceCodeAuthModal();
});
}
function displayDeviceCodeInfo(data) {
const resultElement = document.getElementById('deviceCodeResult');
resultElement.style.display = 'block';
const messageElement = document.getElementById('deviceCodeMessage');
const userCodeElement = document.getElementById('deviceCodeUserCode');
// Create clickable URL
const url = 'https://microsoft.com/devicelogin';
messageElement.innerHTML = data.message.replace(url, `<a href="${url}" target="_blank">${url}</a>`);
userCodeElement.innerHTML = `User Code: ${data.user_code} <button class="btn btn-sm btn-secondary ms-2" onclick="copyDeviceCode('${data.user_code}')">Copy</button>`;
document.getElementById('cancelDeviceCodeAuth').style.display = 'inline-block';
}
function copyDeviceCode(code) {
navigator.clipboard.writeText(code).then(() => {
showNotification('Device code copied to clipboard', 'success');
}).catch(err => {
console.error('Failed to copy: ', err);
showNotification('Failed to copy device code', 'error');
});
}
// Make sure to expose the copyDeviceCode function globally
window.copyDeviceCode = copyDeviceCode;
let pollInterval = null;
let shouldStopPolling = false;
function pollForToken(clientId, deviceCode, tenant, interval) {
return new Promise((resolve, reject) => {
shouldStopPolling = false;
pollInterval = setInterval(() => {
if (shouldStopPolling) {
clearInterval(pollInterval);
return;
}
fetchPostRequest('/poll_for_token', { client_id: clientId, device_code: deviceCode, tenant })
.then(data => {
if (data.status === 'success') {
clearInterval(pollInterval);
storeToken(data.access_token, 'access_token', tenant, null, 'Device Code')
.then(() => {
if (data.refresh_token) {
return storeToken(data.refresh_token, 'refresh_token', tenant, null, 'Device Code Flow');
}
})
.then(() => {
showNotification(data.message, 'success');
resetDeviceCodeUI();
closeDeviceCodeAuthModal();
})
.catch(error => {
console.error('Error storing token:', error);
showNotification('Error storing token', 'error');
resetDeviceCodeUI();
closeDeviceCodeAuthModal();
});
} else if (data.status === 'error') {
clearInterval(pollInterval);
showNotification(`Error: ${data.message}`, 'error');
resetDeviceCodeUI();
closeDeviceCodeAuthModal();
reject(new Error(data.message));
}
})
.catch(error => {
clearInterval(pollInterval);
showNotification(`Error: ${error.message}`, 'error');
resetDeviceCodeUI();
closeDeviceCodeAuthModal();
reject(error);
});
}, interval * 1000);
});
}
function cancelDeviceCodeAuth() {
isDeviceCodeAuthInProgress = false;
shouldStopPolling = true;
if (pollInterval) {
clearInterval(pollInterval);
}
resetDeviceCodeUI();
showNotification('Device code authentication cancelled', 'info');
closeDeviceCodeAuthModal();
}
function cleanup() {
shouldStopPolling = true;
if (pollInterval) {
clearInterval(pollInterval);
}
}
function resetDeviceCodeUI() {
document.getElementById('deviceCodeResult').style.display = 'none';
document.getElementById('deviceCodeMessage').textContent = '';
document.getElementById('deviceCodeUserCode').textContent = '';
document.getElementById('cancelDeviceCodeAuth').style.display = 'none';
}
function closeDeviceCodeAuthModal() {
console.log('Attempting to close device code auth modal');
const modal = document.getElementById('deviceCodeAuthModal');
if (modal) {
// Try Bootstrap 5 approach
const bootstrapModal = bootstrap.Modal.getInstance(modal);
if (bootstrapModal) {
bootstrapModal.hide();
} else {
console.log('Bootstrap modal instance not found, trying alternative methods');
}
// Try Bootstrap 4 approach (if you're using Bootstrap 4)
if (typeof $ !== 'undefined' && typeof $.fn.modal !== 'undefined') {
$(modal).modal('hide');
}
// Fallback: remove modal classes and backdrop
modal.classList.remove('show');
modal.style.display = 'none';
document.body.classList.remove('modal-open');
const backdrop = document.querySelector('.modal-backdrop');
if (backdrop) {
backdrop.remove();
}
} else {
console.error('Modal element not found');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment