Skip to content

Instantly share code, notes, and snippets.

@vgw-rhysc
Created December 19, 2017 11:01
Show Gist options
  • Save vgw-rhysc/b7c82454db671a25c2ad548996581aa5 to your computer and use it in GitHub Desktop.
Save vgw-rhysc/b7c82454db671a25c2ad548996581aa5 to your computer and use it in GitHub Desktop.
Sample SPA app that authenticates with OKAT - replace "THE CLIENT ID HERE"
const express = require('express');
const OktaJwtVerifier = require('@okta/jwt-verifier');
var cors = require('cors');
var oktaApplicationClientId = "THE CLIENT ID HERE"
const oktaJwtVerifier = new OktaJwtVerifier({
issuer: 'https://vgw.okta.com/oauth2/ausfg73gzLfAb6cKg2p6', //Auth server
assertClaims: {
cid: oktaApplicationClientId,
}
});
/**
* THIS IS A MIDDLEWARE FUNCTION!!!!
* Asserts valid access tokens and sends 401 responses if the token is not present or fails validation.
* If the token is valid its contents are attached to req.jwt
**/
function authenticationRequired(req, res, next) {
const authHeader = req.headers.authorization || '';
const match = authHeader.match(/Bearer (.+)/);
if (!match) {
console.error("No Bearer header found");
return res.status(401).end();
}
const accessToken = match[1];
return oktaJwtVerifier.verifyAccessToken(accessToken) //This will make a call to the OKTA auth server to validate the signing key (JWT header kid)
.then((jwt) => {
req.jwt = jwt;
next();
})
.catch((err) => {
console.log(err);
res.status(401).send(err.message);
});
}
/* END custom middleware */
const app = express();
// Allow serving of static content
app.use(express.static('public'))
app.use('/', express.static('./public/index.html'));
// For local testing only! Enables CORS for all domains
app.use(cors());
// Example route that requires a valid access token for authentication, and print some messages for the user if they are authenticated
app.get('/api/secure/hello', authenticationRequired, (req, res) => {
res.json([{
message: 'Hello, ' + req.jwt.claims.sub + '!'
}]);
});
// Another example route that does *not* require a valid access token for authentication
app.get('/api/hello', (req, res) => {
res.json([{
message: 'Hello, world!'
}]);
});
//start the web server
app.listen(3000, () => {
console.log('We are running - go to http://localhost:3000/');
});
{
"name": "oktaauth",
"version": "1.0.0",
"description": "SPA demo of Okta with an express back end to show authenticated request using OAuth2 implicit flow and acess token verification using the Okta auth server",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "RhysC",
"license": "ISC",
"dependencies": {
"@okta/jwt-verifier": "0.0.2",
"cors": "^2.8.4",
"express": "^4.16.2"
}
}
<html>
<head>
<!-- DOCS HERE: https://developer.okta.com/code/javascript/okta_auth_sdk?_ga=1.175804903.493946744.1506927708 -->
<!-- and here: https://developer.okta.com/code/javascript/okta_auth_sdk_ref -->
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script src="https://ok1static.oktacdn.com/assets/js/sdk/okta-auth-js/1.8.0/okta-auth-js.min.js" type="text/javascript"></script>
</head>
<body>
<div id="greeting">
Hi, please login via the OKTA console:
</div>
<strong>HINT:</strong> <small>Look in the dev console to see what is going on behind the scenes :) </small>
<br/>
<div id="apiCallButtons">
<button id="btnCallApi">Call non secured Hello API endpoint</button>
<br/>
<hr/>
<button id="btnCallSecureApi">Call Secure Hello API endpoint</button>
</div>
<div id="output">
</div>
<script type="text/javascript">
let greetUser = function(idToken){
let greetingText = `Hi ${idToken.claims.email}!`;
console.log(greetingText);
document.getElementById("greeting").innerText = greetingText
}
//OKTA LOGIN FLOW
var clientId = "THE CLIENT ID HERE",
var authClient = new OktaAuth({
url: "https://vgw.okta.com",
clientId: clientId,
redirectUri: 'http://localhost:3000/'
});
var idToken = authClient.tokenManager.get('idToken');
if (idToken) {
greetUser(idToken);
}
else if (location.hash) {
console.log("We have a URL hash, lets get the tokens from it...");
authClient.token.parseFromUrl()
.then(parameters => {
var accessToken = parameters[0];
var idToken = parameters[1];
greetUser(idToken);
// Store parsed token in Token Manager
authClient.tokenManager.add('idToken', idToken);
authClient.tokenManager.add('accessToken', accessToken);
console.log(idToken);
console.log(accessToken);
})
.catch(err=>{
console.error(err);
});
}
else {
document.getElementById("greeting").innerText = "Redirecting you to Okta to sign in...";
authClient.token.getWithRedirect({
responseType: ['token', 'id_token'],
scopes: ['openid', 'email', 'profile']
});
}
// END OKTA LOGIN FLOW
//BEGIN - API back end integration - ie our secure and non secure REST calls
var showOutput = function(response, isError=false) {
var preTag = document.createElement('pre');
preTag.innerText = JSON.stringify(response)
if(isError){
preTag.style = "color:red"
}
document.getElementById("output").appendChild(preTag);
}
function callMessagesApi(url) {
var accessToken = authClient.tokenManager.get('accessToken');
if (!accessToken) {
console.error("Request will not be authenticated, No access token found. Sending request anyway #YOLO");
accessToken = { accessToken: '' };
}
$.ajax({
url: url,
headers: {
Authorization : 'Bearer ' + accessToken.accessToken
},
success: function(response) {
console.log('Response', response);
showOutput(response);
},
error: function(response) {
console.error(response);
showOutput(response, true);
}
});
}
document.getElementById("btnCallApi").onclick = function(){ callMessagesApi('http://localhost:3000/api/hello')};
document.getElementById("btnCallSecureApi").onclick = function(){ callMessagesApi('http://localhost:3000/api/secure/hello')};
//END - API back end integration
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment