Skip to content

Commit b398fa8

Browse files
committed
chore: small-pr-updates
1 parent d807074 commit b398fa8

File tree

5 files changed

+83
-24
lines changed

5 files changed

+83
-24
lines changed
Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,67 @@
1-
# iframe-manager
1+
# @forgerock/iframe-manager
22

3-
This library was generated with [Nx](https://nx.dev).
3+
This package provides a utility for making background requests using hidden iframes, primarily intended for scenarios like silent authentication or token renewal in OAuth/OIDC flows. It extracts specified URL parameters from the final redirect URL within the iframe.
44

5-
## Building
5+
## Overview
66

7-
Run `nx build iframe-manager` to build the library.
7+
The package exports a single initialization function, `iframeManagerInit`. Calling this function returns an object containing the core API method: `getParamsFromIFrame`.
88

9-
## Running unit tests
9+
## Installation
1010

11-
Run `nx test iframe-manager` to execute the unit tests via [Vitest](https://vitest.dev/).
11+
This package is typically used within the Ping Identity JavaScript SDK monorepo. If used standalone, you would install it via npm or yarn:
12+
13+
```bash
14+
npm install @forgerock/iframe-manager
15+
# or
16+
yarn add @forgerock/iframe-manager
17+
```
18+
19+
## Usage
20+
21+
Import the initializer, call it, and then use the returned `getParamsFromIFrame` method.
22+
23+
```typescript
24+
import iframeManagerInit from '@forgerock/iframe-manager';
25+
import type { AuthorizeUrl } from '@forgerock/sdk-types';
26+
27+
// Initialize the iframe manager
28+
const iframeManager = iframeManagerInit();
29+
30+
// Define the request options
31+
const options = {
32+
url: 'https://authorization-server.com/authorize?client_id=...' as AuthorizeUrl, // Replace with your actual authorize URL
33+
requestTimeout: 5000, // Timeout in milliseconds (e.g., 5 seconds)
34+
urlParams: ['code', 'state', 'error', 'error_description'], // Specify the parameters you expect to parse
35+
};
36+
37+
// Make the request
38+
iframeManager
39+
.getParamsFromIFrame(options)
40+
.then((params) => {
41+
console.log('Successfully received parameters:', params);
42+
// Example: { code: '...', state: '...' }
43+
// Handle the received parameters (e.g., exchange code for tokens)
44+
})
45+
.catch((error) => {
46+
console.error('Iframe request failed:', error.message);
47+
// Handle the error (e.g., timeout, authorization error)
48+
});
49+
```
50+
51+
## API
52+
53+
### `iframeManagerInit()`
54+
55+
- **Description:** Initializes the iframe manager effect. Currently, it takes no configuration, but this might change in future versions.
56+
- **Returns:** `object` - An object containing the API methods.
57+
- `getParamsFromIFrame`: `(options: { urlParams: string[]; url: AuthorizeUrl; requestTimeout: number; }) => Promise<Record<string, string>>`
58+
59+
### `getParamsFromIFrame(options)`
60+
61+
- **Description:** Creates a hidden iframe, navigates it to the specified `url`, and waits for it to redirect. It then attempts to parse specified query parameters (`urlParams`) from the final URL loaded in the iframe. It rejects if the request times out, if specific OAuth error parameters (`error`, `error_description`) are found in the redirect URL, or if there's an issue accessing the iframe's content (e.g., cross-origin errors before the final expected redirect).
62+
- **Parameters:**
63+
- `options`: `object`
64+
- `url`: `AuthorizeUrl` (string) - The initial URL to load in the iframe.
65+
- `requestTimeout`: `number` - The maximum time in milliseconds to wait for the iframe to load and provide parameters before rejecting with a timeout error.
66+
- `urlParams`: `string[]` - An array of query parameter keys to extract from the final redirect URL. Only parameters listed here will be included in the resolved object.
67+
- **Returns:** `Promise<Record<string, string>>` - A promise that resolves with an object containing the key-value pairs of the extracted query parameters. It rejects with an `Error` if the operation times out, encounters an OAuth error in the URL parameters, or fails for other reasons (like cross-origin access errors).

packages/sdk-effects/iframe-manager/src/lib/iframe-manager.effects.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,12 @@ export default function iframeManagerInit(/*config: OAuthConfig*/) {
3939
* @param options - The options for the iframe request (URL, timeout).
4040
* @returns A Promise that resolves with the query parameters from the redirect URL or rejects on timeout or error.
4141
*/
42-
const getAuthCodeByIFrame = (options: {
42+
const getParamsFromIFrame = (options: {
43+
urlParams: string[];
4344
url: AuthorizeUrl;
4445
requestTimeout: number;
4546
}): Promise<ResolvedParams<string>> => {
46-
const { url, requestTimeout } = options;
47+
const { url, requestTimeout, urlParams } = options;
4748

4849
return new Promise((resolve, reject) => {
4950
let iframe: HTMLIFrameElement | null = document.createElement('iframe');
@@ -79,20 +80,18 @@ export default function iframeManagerInit(/*config: OAuthConfig*/) {
7980
if (iframe && iframe.contentWindow) {
8081
const newHref = iframe.contentWindow.location.href;
8182

82-
// Avoid processing 'about:blank' or initial load if it's not the target URL
83-
if (
84-
newHref === 'about:blank' ||
85-
!newHref.startsWith(options.url.substring(0, options.url.indexOf('?')))
86-
) {
87-
// Check if the newHref origin matches expected redirect_uri origin if possible
88-
// Or simply check if it contains expected parameters.
89-
// For now, we proceed assuming any load could be the redirect.
90-
}
91-
9283
const redirectUrl = new URL(newHref);
9384
const params: ResolvedParams<string> = {};
9485
redirectUrl.searchParams.forEach((value, key) => {
95-
params[key] = value;
86+
/**
87+
* We want to match url params in the url,
88+
* to params being passed into the iframe manager
89+
* so we will ignore params that we are not explicitly
90+
* asked to parse
91+
*/
92+
if (urlParams.includes(key)) {
93+
params[key] = value;
94+
}
9695
});
9796

9897
// Check for standard OAuth error parameters
@@ -144,6 +143,6 @@ export default function iframeManagerInit(/*config: OAuthConfig*/) {
144143

145144
// Return the public API
146145
return {
147-
getAuthCodeByIFrame,
146+
getParamsFromIFrame,
148147
};
149148
}

packages/sdk-types/src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,7 @@
88
export * from './lib/am-callback.types.js';
99
export * from './lib/legacy-config.types.js';
1010
export * from './lib/legacy-mware.types.js';
11-
export * from './lib/tokens.types.js';
1211
export * from './lib/branded.types.js';
12+
export * from './lib/authorize.types.js';
13+
export * from './lib/tokens.types.js';
14+
export * from './lib/config.types.js';

packages/sdk-types/src/lib/config.types.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
* This software may be modified and distributed under the terms
55
* of the MIT license. See the LICENSE file for details.
66
*/
7-
import { AsyncServerConfig } from './legacy-config.types.js';
8-
import { TokenStoreObject } from './tokens.types.js';
7+
import { CustomStorageObject } from './tokens.types.js';
98

109
/**
1110
* Union of possible OAuth Configs
@@ -15,7 +14,7 @@ export type OAuthConfig = DavinciOAuthConfig;
1514

1615
export interface DavinciOAuthConfig extends BaseConfig {
1716
clientId: string;
18-
tokenStore: TokenStoreObject | 'sessionStorage' | 'localStorage';
17+
tokenStore: CustomStorageObject | 'sessionStorage' | 'localStorage';
1918
redirectUri: string;
2019
scope: string;
2120
}

tsconfig.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
},
4040
{
4141
"path": "./packages/sdk-effects/storage"
42+
},
43+
{
44+
"path": "./packages/sdk-effects/iframe-manager"
4245
}
4346
]
4447
}

0 commit comments

Comments
 (0)