ServiceAPIDeviceCodeAuth/DeviceCode.cshtml (131 lines of code) (raw):
@page
@model SphereOBOTest.Pages.DeviceCodeModel
@{
}
<!DOCTYPE html>
<html>
<head>
<title>Azure Sphere Token using Device Code</title>
<meta charset="utf-8" />
<style type="text/css">
body {
font-family: Tahoma;
padding: 3em;
}
</style>
</head>
<body>
<p>
A minimal sample app using OAuth 2.0 Device Code to obtain
an access token from Azure Active Directory and make an API request.
</p>
<p>
<a href="#" onclick="login(); return false;">Log in</a> |
<a href="#" onclick="logout(); return false;">Log out</a>
</p>
<p>
<span id="devicecodetxt"></span>
</p>
<p>
<span id="username" style="font-weight:bold">Not signed in.</span>
</p>
<mark>Sphere API response</mark>
<pre id="apiresponse" style="width:80%"></pre>
<script type="text/javascript">
const getLoginCode = async () => {
const options = {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
};
try {
const response = await fetch(`/DeviceCode?handler=DeviceLogin`, options);
if (response.status == 200) {
const json = JSON.parse(await response.text());
return json;
}
} catch (err) {
console.log('Error calling api', err);
}
}
const getAuthToken = async (code) => {
const options = {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
};
try {
const response = await fetch(`/DeviceCode?handler=token&code=` + code, options)
if (response.status == 200) {
const json = JSON.parse(await response.text());
return json;
}
} catch (err) {
console.log('Error calling api', err);
}
}
const login = async () => {
const left = (screen.width / 2) - (600 / 2);
const top = (screen.height / 2) - (800 / 2);
const childWindow = window.open(loginCode.verification_uri, "LoginWindow", "directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,toolbar=no,scrollbars=yes,width=600,height=800,top=" + top + ",left=" + left);
const getToken = async () => {
const tokenData = await getAuthToken(loginCode.device_code);
if (tokenData) {
if (!tokenData.error) {
childWindow.close();
clearInterval(poll);
getLoggedinUser(tokenData.access_token);
getTenants(tokenData.access_token);
}
else if (tokenData.error.indexOf("authorization_pending") < 0) {
clearInterval(poll);
}
}
};
const poll = setInterval(getToken, parseInt(loginCode.interval) * 1000);
const childwindowtimer = setInterval(async () => {
if (childWindow.closed) {
await getToken();
clearInterval(poll);
clearInterval(childwindowtimer);
}
}, 500);
}
const logout = () => location.href = "https://login.microsoftonline.com/common/oauth2/v2.0/logout"
const getLoggedinUser = (access_token) => {
const base64Url = access_token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
const user = JSON.parse(jsonPayload);
document.getElementById('username').textContent = `Welcome ${user.name} !!!`;
}
const getTenants = async (access_token) => {
document.getElementById('apiresponse').textContent = 'Calling API...';
const options = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
"Authorization": "Bearer " + access_token
}
};
try {
const response = await fetch(`https://prod.core.sphere.azure.net/v2/tenants`, options);
const json = await response.json();
document.getElementById('apiresponse').textContent = JSON.stringify(json, null, ' ');
} catch (err) {
console.log('Error calling api', err);
document.getElementById('apiresponse').textContent = 'ERROR';
}
}
let loginCode = null;
window.onload = async () => {
loginCode = await getLoginCode();
document.getElementById('devicecodetxt').textContent = `Login with code ${loginCode.user_code}`;
}
</script>
</body>
</html>