Objective
- To create a test SPA (Single Page Application) and integrate OKTA with OIDC protocol and authorization code flow with PKCE
- Develop CI/CD pipe line with Github for easy deployment.
- Enable Federation broker mode for immediate access to all users in OKTA
This document will help developers understand the work flow for integrating the custom SPA applications with OKTA using OIDC authorization code flow with PKCE
Details
Prerequisites
- Install Git
- Install node js
- Install VS code
- OKTA tenant
Flow sequence
SPA creates code_verifier and code_challenge
↓
SPA sends code_challenge to Okta
↓
Okta stores challenge and authenticates user
↓
Okta issues authorization_code
↓
SPA sends authorization_code + code_verifier
↓
Okta verifies verifier
↓
Okta issues ID Token and Access Token
Integration model
Identity provider: OKTA
Service provider: SPA
Authentication protocol: OIDC
Grant type: Authorization code flow with PKCE
Create test SPA application
Create SPA that have capability to handle OIDC authorization code flow and CI/CD pipe line with Github
Create folder structure
Open CMD prompt in local drive and run following commands
mkdir okta-interaction-code-spa
cd okta-interaction-code-spa
type nul > package.json
type nul > index.html
type nul > app.js
type nul > callback.html
type nul > .gitignore
mkdir .github
mkdir .github\workflows
type nul > .github\workflows\spa-ci.yml
To check the folders and files created. Run below command.
tree /f

Open the project in Visual Studio Code
Follow the steps below:

Package.json
We are importing the okta-auth-js SDK into the project for getting the code verifier, code challenger & authorization code flow objects and methods.
{
“name”: “okta-interaction-code-spa”,
“version”: “1.0.0”,
“scripts”: {
“start”: “http-server -p 3000”
},
“dependencies”: {
“@okta/okta-auth-js”: “^7.7.0”,
“http-server”: “^14.1.1”
}
}
Install the packages
Open the terminal and run following command
npm install

This creates
- node_modules
- Package-lock.json
package-lock.json records the exact versions of every installed package, including nested dependencies. This will prevent breaks during next builds.

Build the application components
Index.html
<!DOCTYPE html>
<html>
<head>
<title>Interaction Code Flow Testing</title>
</head>
<body>
<h2>Welcome to Interaction Code Flow Testing</h2>
<button onclick=”login()”>Login with Okta</button>
<script type=”module” src=”app.js”></script>
</body>
</html>

Create OIDC application in OKTA
SPA end points
Base URL: http://localhost:3000
Sign-in redirect URI / Call back URL: http://localhost:3000/callback.html
Sign-out redirect URI: http://localhost:3000
- Login to Okta
- Go to Applications>Applications

- Create new OIDC app integration

- Select Application Type as Single-Page Application




Copy Client ID for integrating with SPA
Client ID: : 0oa110oicxdNrfDf2698





Enable Federation Broker

Check trusted origins
- Go to Security>API
- Click Trusted Origins tab
Trusted origin has been created

Assign users to the application in the OKTA
- Since federation broker is enabled, configure app sign-in policy
- Go to the OIDC Application that was created and click Assignments

Configure App Sign-In policy
Configure Sign On Policy
Add a rule or Edit the rule





Assign the application to the policy

Add authorization server policy






Continue the SPA configurations
Navigate to VS code to access app.js

app.js
import { OktaAuth } from ‘https://cdn.skypack.dev/@okta/okta-auth-js’;
const oktaAuth = new OktaAuth({
issuer: ‘https://integrator-3863631.okta.com/oauth2/default’,
clientId: ‘0oa110oicxdNrfDf2698’,
redirectUri: ‘http://localhost:3000/callback.html’,
scopes: [‘openid’, ‘profile’, ’email’],
pkce: true
});
async function login() {
const meta = await oktaAuth.token.prepareTokenParams();
console.log(“CODE VERIFIER:”, meta.codeVerifier);
console.log(“CODE CHALLENGE:”, meta.codeChallenge);
await oktaAuth.token.getWithRedirect({
responseType: ‘code’
});
}
window.login = login;

callback.html
<!DOCTYPE html>
<html>
<head>
<title>Callback</title>
</head>
<body>
<h2>Processing login…</h2>
<script type=”module”>
import { OktaAuth } from ‘https://cdn.skypack.dev/@okta/okta-auth-js’;
const oktaAuth = new OktaAuth({
issuer: ‘https://integrator-3863631.okta.com/oauth2/default’,
clientId: ‘0oa110oicxdNrfDf2698’,
redirectUri: ‘http://localhost:3000/callback.html’,
scopes: [‘openid’, ‘profile’, ’email’],
pkce: true
});
async function handleLogin() {
const tokens = await oktaAuth.token.parseFromUrl();
console.log(“TOKENS:”, tokens);
document.body.innerHTML =
“<h2>Welcome to Interaction Code Flow Testing. You are logged in.</h2>”;
}
handleLogin();
</script>
</body>
</html>

Initiate the flow
npm start in the terminal


- In the browser execute
- Open developer tools and check console
- SPA generated the code verifier and code challenger

- Click on login with OKTA button
- User is redirected to OKTA




Create CI/CD pipe line
Update spa-ci.yml
name: SPA CI/CD
on:
push:
branches:
– main
jobs:
build:
runs-on: ubuntu-latest
steps:
– name: Checkout source
uses: actions/checkout@v4
– name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
– name: Install dependencies
run: npm install
– name: Verify project files
run: |
ls -l
test -f index.html
test -f app.js
test -f callback.html
– name: Create deploy package
run: zip -r okta-interaction-code-spa.zip .
– name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: spa-package
path: okta-interaction-code-spa.zip

Update package.json
{
“name”: “okta-interaction-code-spa”,
“version”: “1.0.0”,
“type”: “module”,
“scripts”: {
“start”: “http-server -p 3000”,
“verify”: “echo SPA verification successful”
},
“dependencies”: {
“@okta/okta-auth-js”: “^7.7.0”,
“http-server”: “^14.1.1”
}
}

Create a repository in Github

Initialize Git
In the terminal run the command: git init

Add Github remote
Run the command: git remote add origin https://github.com/rmadabhushi/okta-interaction-code-spa.git

Verify remote
Run the command: git remote -v

.gitignore
Update the file to ignore node modules pushing to Github

Commit
Run the commands:
git add .
git commit -m “initial okta spa project with CI/CD”

Set main branch
Run the command: git branch -M main

Git push
Run the command: git push -u origin main

The repositories are available in Github


The files can be downloaded from the below link
rmadabhushi/okta-interaction-code-spa: okta-interaction-code-spa
Author
Rangarajan Madabhushi
Ranga Vinjamuri
Rajya Tupuri