Skip to content

Commit 515dc30

Browse files
committed
Add oidc-pkce-client (simple html/js)
1 parent 9bb4ca5 commit 515dc30

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

oidc-pkce-client/simple/index.html

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>OIDC PKCE Authentication</title>
8+
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsSHA/3.3.1/sha.min.js"></script>
9+
</head>
10+
11+
<body>
12+
<button id="loginButton">Login</button>
13+
<button id="logoutButton">Logout</button>
14+
<div id="userInfo"></div>
15+
16+
<script>
17+
const clientId = 'openeo-public';
18+
const redirectUri = window.location.origin;
19+
console.log("Using Redirect URI: " + redirectUri)
20+
const scope = 'openid profile email';
21+
const oidcConfigUrl = 'https://auth.test.eoepca.org/realms/eoepca/.well-known/openid-configuration';
22+
let authEndpoint, tokenEndpoint, userInfoEndpoint;
23+
24+
async function fetchOidcConfig() {
25+
const response = await fetch(oidcConfigUrl);
26+
const oidcConfig = await response.json();
27+
authEndpoint = oidcConfig.authorization_endpoint;
28+
tokenEndpoint = oidcConfig.token_endpoint;
29+
userInfoEndpoint = oidcConfig.userinfo_endpoint;
30+
}
31+
32+
function generateRandomString(length) {
33+
const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
34+
let randomString = '';
35+
for (let i = 0; i < length; i++) {
36+
const randomIndex = Math.floor(Math.random() * charset.length);
37+
randomString += charset.charAt(randomIndex);
38+
}
39+
return randomString;
40+
}
41+
42+
function base64UrlEncode(str) {
43+
return btoa(str).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
44+
}
45+
46+
function sha256(plain) {
47+
const shaObj = new jsSHA('SHA-256', 'TEXT');
48+
shaObj.update(plain);
49+
const hash = shaObj.getHash('BYTES');
50+
return hash;
51+
}
52+
53+
async function login() {
54+
const codeVerifier = generateRandomString(128);
55+
sessionStorage.setItem('codeVerifier', codeVerifier);
56+
57+
const codeChallenge = base64UrlEncode(sha256(codeVerifier));
58+
const state = generateRandomString(16);
59+
60+
await fetchOidcConfig();
61+
62+
const authUrl = `${authEndpoint}?response_type=code&client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}&code_challenge=${codeChallenge}&code_challenge_method=S256&state=${state}`;
63+
window.location = authUrl;
64+
}
65+
66+
async function handleCallback() {
67+
const urlParams = new URLSearchParams(window.location.search);
68+
const code = urlParams.get('code');
69+
const state = urlParams.get('state');
70+
const codeVerifier = sessionStorage.getItem('codeVerifier');
71+
72+
if (code) {
73+
await fetchOidcConfig();
74+
75+
const tokenResponse = await fetch(tokenEndpoint, {
76+
method: 'POST',
77+
headers: {
78+
'Content-Type': 'application/x-www-form-urlencoded'
79+
},
80+
body: new URLSearchParams({
81+
grant_type: 'authorization_code',
82+
code: code,
83+
client_id: clientId,
84+
redirect_uri: redirectUri,
85+
code_verifier: codeVerifier
86+
})
87+
});
88+
const tokenData = await tokenResponse.json();
89+
sessionStorage.setItem('accessToken', tokenData.access_token);
90+
fetchUserInfo(tokenData.access_token);
91+
}
92+
}
93+
94+
async function fetchUserInfo(accessToken) {
95+
const userInfoResponse = await fetch(userInfoEndpoint, {
96+
headers: {
97+
'Authorization': `Bearer ${accessToken}`
98+
}
99+
});
100+
const userInfo = await userInfoResponse.json();
101+
document.getElementById('userInfo').innerText = `Hello, ${userInfo.name}`;
102+
}
103+
104+
function logout() {
105+
sessionStorage.removeItem('accessToken');
106+
document.getElementById('userInfo').innerText = '';
107+
}
108+
109+
document.getElementById('loginButton').addEventListener('click', login);
110+
document.getElementById('logoutButton').addEventListener('click', logout);
111+
112+
window.onload = handleCallback;
113+
</script>
114+
</body>
115+
116+
</html>

0 commit comments

Comments
 (0)