Skip to content

Instantly share code, notes, and snippets.

@thameera
Created March 21, 2022 06:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thameera/5a1b5ab41fd82ce498cdc6b8a5b64330 to your computer and use it in GitHub Desktop.
Save thameera/5a1b5ab41fd82ce498cdc6b8a5b64330 to your computer and use it in GitHub Desktop.
Getting an MFA API token with Auth0 SPA JS SDK
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="https://cdn.auth0.com/js/auth0-spa-js/1.20/auth0-spa-js.production.js"></script>
<title>MFA API Test</title>
<style>
.hidden { display: none; }
</style>
</head>
<body>
<a id="homeurl" href="#">Home</a>
<h2>MFA API Test</h2>
<div id="loading">Initializing...</div>
<div id="buttons" class="hidden">
<h3>Step 1: Log in</h3>
<div><button type="button" onclick="initialLogin()">Login</button></div>
<h3>Step 2: Get MFA API token</h3>
<div><button type="button" onclick="getMFAToken()">Get MFA API token</button></div>
<h3>Optional: Log out</h3>
<button type="button" onclick="logout()">Logout</button>
</div>
<hr>
<div id="logs"></div>
<script>
const URL = window.location.href.split('#')[0].split('?')[0]
document.querySelector('a#homeurl').href = URL
const logs = document.querySelector('#logs')
const write = (s, isCode) => {
if (s === '---') {
logs.innerHTML = `${logs.innerHTML}<hr>`
return
}
const tag = isCode ? 'code' : 'p'
logs.innerHTML = `${logs.innerHTML}<${tag}>${s}</${tag}>`
if (isCode) logs.innerHTML += '<br>'
}
const writeCollapsible = (summary, details) => {
const sum = `<summary>${summary}</summary>`
logs.innerHTML = `${logs.innerHTML}<details>${sum}<pre>${details}</pre></details>`
}
let auth0
const init = async () => {
auth0 = new Auth0Client({
"domain": "TENANT.auth0.com",
"client_id": "CLIENT_ID",
"redirect_uri": "URL_TO_THIS_PAGE",
"scope": "openid profile email",
"audience": "API_AUDIENCE_IDENTIFIER"
})
document.getElementById('loading').classList.add('hidden')
document.getElementById('buttons').classList.remove('hidden')
const query = window.location.search;
if (query.includes('state=')) {
try {
await auth0.handleRedirectCallback()
const token = await auth0.getTokenSilently()
writeAuthDetails(token)
} catch (e) {
writeError(e)
}
}
}
const writeAuthDetails = async (token) => {
const authenticated = await auth0.isAuthenticated()
if (!authenticated) {
write('<strong>Login failed</strong>')
return
}
write('<strong>Login successful</strong>')
write('Access token:')
write(token, true)
if (token.startsWith('eyJ')) {
const atp = JSON.parse(atob(token.split('.')[1]))
write('Access token payload:')
writeCollapsible(JSON.stringify(atp), JSON.stringify(atp, 0, 4))
}
}
const writeError = e => {
window.err = e // for debugging
write('<strong>Error received</strong>')
write(`Error: ${e.error}\n`, true)
write(`Message: ${e.error_description}`, true)
}
// We perform the initial login here, and get a token for our regular API
window.initialLogin = async () => {
await auth0.loginWithRedirect()
}
// Here we perform silent authentication while requesting an MFA API token
window.getMFAToken = async () => {
try {
const token = await auth0.getTokenSilently({
audience: 'https://TENANT.auth0.com/mfa/',
scope: 'read:authenticators'
})
writeAuthDetails(token)
} catch (e) {
writeError(e)
return
}
}
window.logout = async () => {
auth0.logout({
"returnTo": "URL_TO_THIS_PAGE",
"client_id": "CLIENT_ID"
})
}
window.onload = init
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment