Skip to content

Commit 98f1e5c

Browse files
committed
feat(oidc-client): add oidc session check with response type of id_token and none
1 parent 354a238 commit 98f1e5c

20 files changed

Lines changed: 1720 additions & 80 deletions

.changeset/brave-foxes-dance.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@forgerock/iframe-manager': minor
3+
'@forgerock/oidc-client': minor
4+
---
5+
6+
Add `session.check()` method to oidc client for OIDC prompt=none session verification, with `response_type=none` and `response_type=id_token` support.

e2e/oidc-app/src/ping-am/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ <h1>OIDC App | PingAM Login</h1>
2121
<button id="logout">Logout</button>
2222
<button id="user-info-btn">User Info</button>
2323
<button id="revoke">Revoke Token</button>
24+
<button id="session-check-btn">Session Check (none)</button>
25+
<button id="session-check-id-token-btn">Session Check (id_token)</button>
2426
<a href="/ping-am/">Start Over</a>
2527
</div>
2628
<script type="module" src="./main.ts"></script>

e2e/oidc-app/src/ping-one/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ <h1>OIDC App | P1 Login</h1>
2121
<button id="logout">Logout</button>
2222
<button id="user-info-btn">User Info</button>
2323
<button id="revoke">Revoke Token</button>
24+
<button id="session-check-btn">Session Check (none)</button>
25+
<button id="session-check-id-token-btn">Session Check (id_token)</button>
2426
<a href="/ping-one/">Start Over</a>
2527
</div>
2628
<script type="module" src="./main.ts"></script>

e2e/oidc-app/src/utils/oidc-app.ts

Lines changed: 112 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,16 @@ import { oidc } from '@forgerock/oidc-client';
1010
import type {
1111
AuthorizationError,
1212
GenericError,
13-
GetAuthorizationUrlOptions,
1413
OauthTokens,
1514
OidcClient,
15+
OidcConfig,
16+
SessionCheckOptions,
1617
TokenExchangeErrorResponse,
1718
} from '@forgerock/oidc-client/types';
1819

1920
let tokenIndex = 0;
2021

21-
function displayError(error) {
22+
function displayError(error: unknown) {
2223
const errorEl = document.createElement('div');
2324
errorEl.innerHTML = `<p><strong>Error:</strong> <span class="error">${JSON.stringify(error, null, 2)}</span></p>`;
2425
document.body.appendChild(errorEl);
@@ -27,25 +28,44 @@ function displayError(error) {
2728
function displayTokenResponse(
2829
response: OauthTokens | TokenExchangeErrorResponse | GenericError | AuthorizationError,
2930
) {
30-
const appEl = document.getElementById('app');
3131
if ('error' in response || !('accessToken' in response)) {
3232
console.error('Token Error:', response);
3333
displayError(response);
3434
} else {
3535
console.log('Token Response:', response);
36-
document.getElementById('logout').style.display = 'block';
37-
document.getElementById('user-info-btn').style.display = 'block';
38-
document.getElementById('login-background').style.display = 'none';
39-
document.getElementById('login-redirect').style.display = 'none';
36+
const appEl = document.getElementById('app');
37+
const logoutEl = document.getElementById('logout');
38+
const userInfoBtnEl = document.getElementById('user-info-btn');
39+
const loginBackgroundEl = document.getElementById('login-background');
40+
const loginRedirectEl = document.getElementById('login-redirect');
41+
42+
if (logoutEl) {
43+
logoutEl.style.display = 'block';
44+
}
45+
if (userInfoBtnEl) {
46+
userInfoBtnEl.style.display = 'block';
47+
}
48+
if (loginBackgroundEl) {
49+
loginBackgroundEl.style.display = 'none';
50+
}
51+
if (loginRedirectEl) {
52+
loginRedirectEl.style.display = 'none';
53+
}
4054

4155
const tokenInfoEl = document.createElement('div');
4256
tokenInfoEl.innerHTML = `<p><strong>Access Token:</strong> <span id="accessToken-${tokenIndex}">${response.accessToken}</span></p>`;
43-
appEl.appendChild(tokenInfoEl);
57+
appEl?.appendChild(tokenInfoEl);
4458
tokenIndex++;
4559
}
4660
}
4761

48-
export async function oidcApp({ config, urlParams }) {
62+
export async function oidcApp({
63+
config,
64+
urlParams,
65+
}: {
66+
config: OidcConfig;
67+
urlParams: URLSearchParams;
68+
}) {
4969
const code = urlParams.get('code');
5070
const state = urlParams.get('state');
5171
const piflow = urlParams.get('piflow');
@@ -56,20 +76,23 @@ export async function oidcApp({ config, urlParams }) {
5676
});
5777
if ('error' in oidcClient) {
5878
displayError(oidcClient);
79+
return;
5980
}
6081

61-
document.getElementById('login-background').addEventListener('click', async () => {
62-
const authorizeOptions: GetAuthorizationUrlOptions =
82+
document.getElementById('login-background')?.addEventListener('click', async () => {
83+
const authorizeOptions =
6384
piflow === 'true'
6485
? {
6586
clientId: config.clientId,
6687
redirectUri: config.redirectUri,
6788
scope: config.scope,
6889
responseType: config.responseType ?? 'code',
69-
responseMode: 'pi.flow',
90+
responseMode: 'pi.flow' as const,
7091
}
7192
: undefined;
72-
const response = await oidcClient.authorize.background(authorizeOptions);
93+
const response = await oidcClient.authorize?.background(authorizeOptions);
94+
95+
if (!response) return;
7396

7497
if ('error' in response) {
7598
console.error('Authorization Error:', response);
@@ -85,13 +108,16 @@ export async function oidcApp({ config, urlParams }) {
85108
// Handle success response from background authorization
86109
} else if ('code' in response) {
87110
console.log('Authorization Code:', response.code);
88-
const tokenResponse = await oidcClient.token.exchange(response.code, response.state);
89-
displayTokenResponse(tokenResponse);
111+
const tokenResponse = await oidcClient.token?.exchange(response.code, response.state);
112+
if (tokenResponse) {
113+
displayTokenResponse(tokenResponse);
114+
}
90115
}
91116
});
92117

93-
document.getElementById('login-redirect').addEventListener('click', async () => {
94-
const authorizeUrl = await oidcClient.authorize.url();
118+
document.getElementById('login-redirect')?.addEventListener('click', async () => {
119+
const authorizeUrl = await oidcClient.authorize?.url();
120+
if (!authorizeUrl) return;
95121
if (typeof authorizeUrl !== 'string' && 'error' in authorizeUrl) {
96122
console.error('Authorization URL Error:', authorizeUrl);
97123
displayError(authorizeUrl);
@@ -102,23 +128,31 @@ export async function oidcApp({ config, urlParams }) {
102128
}
103129
});
104130

105-
document.getElementById('get-tokens').addEventListener('click', async () => {
106-
const response = await oidcClient.token.get();
107-
displayTokenResponse(response);
131+
document.getElementById('get-tokens')?.addEventListener('click', async () => {
132+
const response = await oidcClient.token?.get();
133+
if (response) {
134+
displayTokenResponse(response);
135+
}
108136
});
109137

110-
document.getElementById('get-tokens-background').addEventListener('click', async () => {
111-
const response = await oidcClient.token.get({ backgroundRenew: true });
112-
displayTokenResponse(response);
138+
document.getElementById('get-tokens-background')?.addEventListener('click', async () => {
139+
const response = await oidcClient.token?.get({ backgroundRenew: true });
140+
if (response) {
141+
displayTokenResponse(response);
142+
}
113143
});
114144

115-
document.getElementById('renew-tokens').addEventListener('click', async () => {
116-
const response = await oidcClient.token.get({ backgroundRenew: true, forceRenew: true });
117-
displayTokenResponse(response);
145+
document.getElementById('renew-tokens')?.addEventListener('click', async () => {
146+
const response = await oidcClient.token?.get({ backgroundRenew: true, forceRenew: true });
147+
if (response) {
148+
displayTokenResponse(response);
149+
}
118150
});
119151

120-
document.getElementById('user-info-btn').addEventListener('click', async () => {
121-
const userInfo = await oidcClient.user.info();
152+
document.getElementById('user-info-btn')?.addEventListener('click', async () => {
153+
const userInfo = await oidcClient.user?.info();
154+
155+
if (!userInfo) return;
122156

123157
if ('error' in userInfo) {
124158
console.error('User Info Error:', userInfo);
@@ -129,42 +163,78 @@ export async function oidcApp({ config, urlParams }) {
129163
const appEl = document.getElementById('app');
130164
const userInfoEl = document.createElement('div');
131165
userInfoEl.innerHTML = `<p><strong>User Info:</strong> <span id="userInfo">${JSON.stringify(userInfo, null, 2)}</span></p>`;
132-
appEl.appendChild(userInfoEl);
166+
appEl?.appendChild(userInfoEl);
133167
}
134168
});
135169

136-
document.getElementById('revoke').addEventListener('click', async () => {
137-
const response = await oidcClient.token.revoke();
170+
document.getElementById('revoke')?.addEventListener('click', async () => {
171+
const response = await oidcClient.token?.revoke();
172+
173+
if (!response) return;
138174

139175
if ('error' in response) {
140176
console.error('Token Revocation Error:', response);
141177
displayError(response);
142178
} else {
143179
const appEl = document.getElementById('app');
144-
const userInfoEl = document.createElement('div');
145-
userInfoEl.innerHTML = `<p>Token successfully revoked</p>`;
146-
appEl.appendChild(userInfoEl);
180+
const revokeEl = document.createElement('div');
181+
revokeEl.innerHTML = `<p>Token successfully revoked</p>`;
182+
appEl?.appendChild(revokeEl);
147183
}
148184
});
149185

150-
document.getElementById('logout').addEventListener('click', async () => {
151-
const response = await oidcClient.user.logout();
186+
document.getElementById('logout')?.addEventListener('click', async () => {
187+
const response = await oidcClient.user?.logout();
188+
189+
if (!response) return;
152190

153191
if ('error' in response) {
154192
console.error('Logout Error:', response);
155193
displayError(response);
156194
} else {
157195
console.log('Logout successful');
158-
document.getElementById('logout').style.display = 'none';
159-
document.getElementById('user-info-btn').style.display = 'none';
160-
document.getElementById('login-background').style.display = 'block';
161-
document.getElementById('login-redirect').style.display = 'block';
196+
const logoutEl = document.getElementById('logout');
197+
const userInfoBtnEl = document.getElementById('user-info-btn');
198+
const loginBackgroundEl = document.getElementById('login-background');
199+
const loginRedirectEl = document.getElementById('login-redirect');
200+
201+
if (logoutEl) {
202+
logoutEl.style.display = 'none';
203+
}
204+
if (userInfoBtnEl) {
205+
userInfoBtnEl.style.display = 'none';
206+
}
207+
if (loginBackgroundEl) {
208+
loginBackgroundEl.style.display = 'block';
209+
}
210+
if (loginRedirectEl) {
211+
loginRedirectEl.style.display = 'block';
212+
}
162213
window.location.assign(window.location.origin + window.location.pathname);
163214
}
164215
});
165216

217+
document.getElementById('session-check-btn')?.addEventListener('click', async () => {
218+
const result = await oidcClient.session?.check();
219+
const appEl = document.getElementById('app');
220+
const el = document.createElement('div');
221+
el.innerHTML = `<p><strong>Session Check (none):</strong></p><pre id="session-check-result">${JSON.stringify(result, null, 2)}</pre>`;
222+
appEl?.appendChild(el);
223+
});
224+
225+
document.getElementById('session-check-id-token-btn')?.addEventListener('click', async () => {
226+
const options: SessionCheckOptions = { responseType: 'id_token' };
227+
const result = await oidcClient.session?.check(options);
228+
const appEl = document.getElementById('app');
229+
const el = document.createElement('div');
230+
el.innerHTML = `<p><strong>Session Check (id_token):</strong></p><pre id="session-check-id-token-result">${JSON.stringify(result, null, 2)}</pre>`;
231+
appEl?.appendChild(el);
232+
});
233+
166234
if (code && state) {
167-
const response = await oidcClient.token.exchange(code, state);
168-
displayTokenResponse(response);
235+
const response = await oidcClient.token?.exchange(code, state);
236+
if (response) {
237+
displayTokenResponse(response);
238+
}
169239
}
170240
}

0 commit comments

Comments
 (0)