#include loading.jsx #include app/info.jsx #include app/scope.jsx #include header/header.js #include header/user.jsx const MszOAuth2Verify = () => { const queryParams = new URLSearchParams(window.location.search); const loading = new MszOAuth2Loading('.js-loading'); const header = new MszOAuth2Header; const fAuths = document.querySelector('.js-verify-authorise'); const eAuthsInfo = document.querySelector('.js-verify-authorise-info'); const eAuthsScope = document.querySelector('.js-verify-authorise-scope'); const rApproved = document.querySelector('.js-verify-approved'); const rDenied = document.querySelector('.js-verify-denied'); let userCode = ''; let userHeader; const verifyAuthsRequest = async approve => { try { const { body } = await $xhr.post('/oauth2/verify', { authed: true, csrf: true, type: 'json' }, { code: userCode, approve: approve === true ? 'yes' : 'no', }); if(!body) throw 'response is empty'; if(typeof body.error === 'string') { // TODO: nicer errors if(body.error === 'auth') alert('You are not logged in.'); else if(body.error === 'csrf') alert('Request verification failed, please refresh and try again.'); else if(body.error === 'code') alert('This code is not associated with any authorisation request.'); else if(body.error === 'approval') alert('The authorisation request associated with this code is not pending approval.'); else if(body.error === 'expired') alert('The authorisation request has expired, please restart the process from the application or device.'); else if(body.error === 'invalid') alert('Invalid approval state specified.'); else if(body.error === 'scope') { alert(`Requested scope "${body.scope}" is ${body.reason}.`); loading.visible = false; rDenied.classList.remove('hidden'); return; } else alert(`An unknown error occurred: ${body.error}`); loading.visible = false; fAuths.classList.remove('hidden'); return; } loading.visible = false; if(body.approval === 'approved') rApproved.classList.remove('hidden'); else rDenied.classList.remove('hidden'); } catch(ex) { alert('Request to verify endpoint failed. Please try again.'); loading.visible = false; fAuths.classList.remove('hidden'); } }; fAuths.onsubmit = ev => { ev.preventDefault(); loading.visible = true; fAuths.classList.add('hidden'); if(userHeader) userHeader.guiseVisible = false; verifyAuthsRequest(ev.submitter.value === 'yes'); }; const fCode = document.querySelector('.js-verify-code'); const eUserCode = fCode.elements.namedItem('code'); fCode.onsubmit = ev => { ev.preventDefault(); loading.visible = true; fCode.classList.add('hidden'); userCode = encodeURIComponent(eUserCode.value); $xhr.get(`/oauth2/resolve-verify?code=${userCode}`, { authed: true, csrf: true, type: 'json' }) .then(result => { const body = result.body; if(!body) { alert('Request to resolve endpoint failed. Please try again.'); loading.visible = false; fCode.classList.remove('hidden'); return; } if(typeof body.error === 'string') { // TODO: nicer errors if(body.error === 'auth') { window.location.assign(`/auth/login.php?oauth2=1&redirect=${encodeURIComponent(`${window.location.pathname}${window.location.search}`)}`); return; } else if(body.error === 'csrf') alert('Request verification failed, please refresh and try again.'); else if(body.error === 'code') alert('This code is not associated with any authorisation request.'); else if(body.error === 'expired') alert('The authorisation request has expired, please restart the process from the application or device.'); else if(body.error === 'approval') alert('The authorisation request associated with this code is not pending approval.'); else if(body.error === 'scope') { verifyAuthsRequest(false).finally(() => { alert(`Requested scope "${body.scope}" is ${body.reason}.`); }); return; } else alert(`An unknown error occurred: ${body.error}`); loading.visible = false; fCode.classList.remove('hidden'); return; } userCode = body.req.code; userHeader = new MszOAuth2UserHeader(body.user); header.setElement(userHeader); if(body.app.trusted && body.user.guise === undefined) { if(userHeader) userHeader.guiseVisible = false; verifyAuthsRequest(true); return; } eAuthsInfo.replaceWith(new MszOAuth2AppInfo(body.app).element); eAuthsScope.replaceWith(new MszOAuth2AppScopeList(body.scope).element); loading.visible = false; fAuths.classList.remove('hidden'); }).catch(() => { alert('Request to resolve endpoint failed. Please try again.'); loading.visible = false; fCode.classList.remove('hidden'); }); }; const validateCodeInput = () => { // [A-Za-z0-8]{3}\-[A-Za-z0-8]{3}\-[A-Za-z0-8]{3} // 0 -> O, 1 -> I, 8 -> B const eCode = eUserCode.value; return eCode.length > 0; }; eUserCode.oninput = () => { validateCodeInput(); console.warn(eUserCode.value); }; if(queryParams.has('code') && eUserCode.value === '') eUserCode.value = queryParams.get('code'); if(validateCodeInput()) { fCode.requestSubmit(); } else { loading.visible = false; fCode.classList.remove('hidden'); } };