const axios = require('axios'); async function getDeviceCode(clientId) { const params = new URLSearchParams({ client_id: clientId, scope: 'SDPOnDemand.requests.READ', grant_type: 'device_request', access_type: 'offline' }); const res = await axios.post('https://accounts.zoho.com/oauth/v3/device/code', params); return res.data; } function pollForToken(clientId, clientSecret, deviceCode, interval, expiresIn) { const pollParams = new URLSearchParams({ client_id: clientId, client_secret: clientSecret, code: deviceCode, grant_type: 'device_token' }); return new Promise((resolve, reject) => { const deadline = Date.now() + (expiresIn || 300) * 1000; const timer = setInterval(async () => { if (Date.now() > deadline) { clearInterval(timer); reject(new Error('Expired try again.')); return; } try { const res = await axios.post('https://accounts.zoho.com/oauth/v3/device/token', pollParams); if (res.data.access_token) { clearInterval(timer); resolve(res.data.access_token); } } catch (err) { } }, interval + 500); }); } async function startAuthentication({ clientId, clientSecret, state }) { state.auth = 'pending'; state.lastError = null; const deviceData = await getDeviceCode(clientId); state.verificationUrl = deviceData.verification_uri_complete; state.userCode = deviceData.user_code; console.log('Open this URL and authorize:', deviceData.verification_uri_complete); console.log('Code: ', deviceData.user_code); try { const accessToken = await pollForToken( clientId, clientSecret, deviceData.device_code, deviceData.interval, deviceData.expires_in ); state.auth = 'connected'; state.verificationUrl = null; state.userCode = null; return { accessToken }; } catch (err) { state.auth = 'error'; state.lastError = err.message; state.verificationUrl = null; state.userCode = null; return null; } } module.exports = { startAuthentication };