@abapify/browser-auth 0.0.0 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +270 -1
- package/package.json +32 -3
package/README.md
CHANGED
|
@@ -1,3 +1,272 @@
|
|
|
1
1
|
# @abapify/browser-auth
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/abapify/adt-cli/pkgs/npm/%40abapify%2Fbrowser-auth)
|
|
4
|
+
|
|
5
|
+
Core browser-based SSO authentication logic for SAP ADT systems. This package provides the shared authentication flow used by browser-specific adapters like Playwright and Puppeteer.
|
|
6
|
+
|
|
7
|
+
> **Note:** This is a low-level package. Most users should use `@abapify/adt-playwright` or `@abapify/adt-puppeteer` instead.
|
|
8
|
+
|
|
9
|
+
## Architecture
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
@abapify/browser-auth (this package)
|
|
13
|
+
├── BrowserAdapter interface
|
|
14
|
+
├── Event-driven auth flow
|
|
15
|
+
├── Cookie utilities
|
|
16
|
+
└── Pattern matching
|
|
17
|
+
↑
|
|
18
|
+
@abapify/adt-playwright ─────┐
|
|
19
|
+
└── Playwright adapter │
|
|
20
|
+
├── Implement BrowserAdapter
|
|
21
|
+
@abapify/adt-puppeteer ──────┘
|
|
22
|
+
└── Puppeteer adapter
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @abapify/browser-auth
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
This package is primarily used by browser adapter implementations. Direct usage:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import {
|
|
37
|
+
authenticate,
|
|
38
|
+
testCredentials,
|
|
39
|
+
toCookieHeader,
|
|
40
|
+
} from '@abapify/browser-auth';
|
|
41
|
+
import type { BrowserAdapter } from '@abapify/browser-auth';
|
|
42
|
+
|
|
43
|
+
// Create your browser adapter (see BrowserAdapter interface)
|
|
44
|
+
const adapter: BrowserAdapter = createMyAdapter();
|
|
45
|
+
|
|
46
|
+
// Authenticate
|
|
47
|
+
const credentials = await authenticate(adapter, {
|
|
48
|
+
url: 'https://sap-system.example.com',
|
|
49
|
+
headless: false,
|
|
50
|
+
userDataDir: true,
|
|
51
|
+
requiredCookies: ['SAP_SESSIONID_*', 'sap-usercontext'],
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Test if credentials are still valid
|
|
55
|
+
const result = await testCredentials(credentials);
|
|
56
|
+
console.log(result.valid); // true/false
|
|
57
|
+
|
|
58
|
+
// Convert to Cookie header string
|
|
59
|
+
const cookieHeader = toCookieHeader(credentials);
|
|
60
|
+
// "SAP_SESSIONID_XXX=abc123; sap-usercontext=..."
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## API
|
|
64
|
+
|
|
65
|
+
### `authenticate(adapter, options)`
|
|
66
|
+
|
|
67
|
+
Performs browser-based SSO authentication.
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
async function authenticate(
|
|
71
|
+
adapter: BrowserAdapter,
|
|
72
|
+
options: BrowserAuthOptions,
|
|
73
|
+
): Promise<BrowserCredentials>;
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Parameters:**
|
|
77
|
+
|
|
78
|
+
- `adapter` - Browser adapter implementing `BrowserAdapter` interface
|
|
79
|
+
- `options` - Authentication options
|
|
80
|
+
|
|
81
|
+
**Options:**
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
interface BrowserAuthOptions {
|
|
85
|
+
url: string; // SAP system URL
|
|
86
|
+
headless?: boolean; // Hide browser (default: false)
|
|
87
|
+
timeout?: number; // Login timeout in ms (default: 300000)
|
|
88
|
+
userAgent?: string; // Custom user agent
|
|
89
|
+
requiredCookies?: string[]; // Cookie patterns to wait for
|
|
90
|
+
userDataDir?: string | boolean; // Session persistence path
|
|
91
|
+
ignoreHTTPSErrors?: boolean; // Ignore SSL errors (default: true)
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Returns:** `BrowserCredentials` with captured cookies
|
|
96
|
+
|
|
97
|
+
### `testCredentials(credentials)`
|
|
98
|
+
|
|
99
|
+
Tests if credentials are still valid by making a request to the SAP system.
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
async function testCredentials(
|
|
103
|
+
credentials: BrowserCredentials,
|
|
104
|
+
): Promise<TestResult>;
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### `toCookieHeader(credentials)`
|
|
108
|
+
|
|
109
|
+
Converts credentials to a Cookie header string.
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
function toCookieHeader(credentials: BrowserCredentials): string;
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### `toHeaders(credentials)`
|
|
116
|
+
|
|
117
|
+
Creates headers object with Cookie and User-Agent.
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
function toHeaders(credentials: BrowserCredentials): Record<string, string>;
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## BrowserAdapter Interface
|
|
124
|
+
|
|
125
|
+
To create a new browser adapter, implement this interface:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
interface BrowserAdapter {
|
|
129
|
+
/** Launch browser and create context */
|
|
130
|
+
launch(options: {
|
|
131
|
+
headless: boolean;
|
|
132
|
+
userDataDir?: string;
|
|
133
|
+
ignoreHTTPSErrors?: boolean;
|
|
134
|
+
userAgent?: string;
|
|
135
|
+
}): Promise<void>;
|
|
136
|
+
|
|
137
|
+
/** Create a new page */
|
|
138
|
+
newPage(): Promise<void>;
|
|
139
|
+
|
|
140
|
+
/** Navigate to URL */
|
|
141
|
+
goto(url: string, options?: { timeout?: number }): Promise<void>;
|
|
142
|
+
|
|
143
|
+
/** Get all cookies */
|
|
144
|
+
getCookies(): Promise<CookieData[]>;
|
|
145
|
+
|
|
146
|
+
/** Get user agent string */
|
|
147
|
+
getUserAgent(): Promise<string>;
|
|
148
|
+
|
|
149
|
+
/** Close the page */
|
|
150
|
+
closePage(): Promise<void>;
|
|
151
|
+
|
|
152
|
+
/** Close browser context */
|
|
153
|
+
close(): Promise<void>;
|
|
154
|
+
|
|
155
|
+
/** Register response event handler */
|
|
156
|
+
onResponse(handler: (event: ResponseEvent) => void): void;
|
|
157
|
+
|
|
158
|
+
/** Register page close handler */
|
|
159
|
+
onPageClose(handler: () => void): void;
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Cookie Pattern Matching
|
|
164
|
+
|
|
165
|
+
The `requiredCookies` option supports wildcard patterns:
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
// Wait for any SAP session cookie
|
|
169
|
+
requiredCookies: ['SAP_SESSIONID_*'];
|
|
170
|
+
|
|
171
|
+
// Wait for specific cookies
|
|
172
|
+
requiredCookies: ['SAP_SESSIONID_S0D_200', 'sap-usercontext'];
|
|
173
|
+
|
|
174
|
+
// Multiple patterns
|
|
175
|
+
requiredCookies: ['SAP_SESSIONID_*', 'MYSAPSSO2', 'sap-usercontext'];
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Utility Functions
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
import { matchesCookiePattern, cookieMatchesAny } from '@abapify/browser-auth';
|
|
182
|
+
|
|
183
|
+
// Check single pattern
|
|
184
|
+
matchesCookiePattern('SAP_SESSIONID_S0D_200', 'SAP_SESSIONID_*'); // true
|
|
185
|
+
|
|
186
|
+
// Check multiple patterns
|
|
187
|
+
cookieMatchesAny('SAP_SESSIONID_S0D_200', ['MYSAPSSO2', 'SAP_SESSIONID_*']); // true
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Types
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
interface CookieData {
|
|
194
|
+
name: string;
|
|
195
|
+
value: string;
|
|
196
|
+
domain: string;
|
|
197
|
+
path: string;
|
|
198
|
+
expires?: number;
|
|
199
|
+
httpOnly?: boolean;
|
|
200
|
+
secure?: boolean;
|
|
201
|
+
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
interface BrowserCredentials {
|
|
205
|
+
baseUrl: string;
|
|
206
|
+
cookies: CookieData[];
|
|
207
|
+
authenticatedAt: Date;
|
|
208
|
+
userAgent?: string;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
interface TestResult {
|
|
212
|
+
valid: boolean;
|
|
213
|
+
error?: string;
|
|
214
|
+
responseTime?: number;
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Creating a New Adapter
|
|
219
|
+
|
|
220
|
+
Example: Creating a Selenium adapter
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
import type {
|
|
224
|
+
BrowserAdapter,
|
|
225
|
+
CookieData,
|
|
226
|
+
ResponseEvent,
|
|
227
|
+
} from '@abapify/browser-auth';
|
|
228
|
+
import { Builder, Browser } from 'selenium-webdriver';
|
|
229
|
+
|
|
230
|
+
export function createSeleniumAdapter(): BrowserAdapter {
|
|
231
|
+
let driver: WebDriver | null = null;
|
|
232
|
+
const responseHandlers: ((event: ResponseEvent) => void)[] = [];
|
|
233
|
+
|
|
234
|
+
return {
|
|
235
|
+
async launch(options) {
|
|
236
|
+
driver = await new Builder().forBrowser(Browser.CHROME).build();
|
|
237
|
+
},
|
|
238
|
+
|
|
239
|
+
async newPage() {
|
|
240
|
+
// Selenium uses single page model
|
|
241
|
+
},
|
|
242
|
+
|
|
243
|
+
async goto(url, options) {
|
|
244
|
+
await driver?.get(url);
|
|
245
|
+
},
|
|
246
|
+
|
|
247
|
+
async getCookies(): Promise<CookieData[]> {
|
|
248
|
+
const cookies = await driver?.manage().getCookies();
|
|
249
|
+
return (
|
|
250
|
+
cookies?.map((c) => ({
|
|
251
|
+
name: c.name,
|
|
252
|
+
value: c.value,
|
|
253
|
+
domain: c.domain || '',
|
|
254
|
+
path: c.path || '/',
|
|
255
|
+
expires: c.expiry?.getTime(),
|
|
256
|
+
httpOnly: c.httpOnly,
|
|
257
|
+
secure: c.secure,
|
|
258
|
+
})) || []
|
|
259
|
+
);
|
|
260
|
+
},
|
|
261
|
+
|
|
262
|
+
// ... implement remaining methods
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Related Packages
|
|
268
|
+
|
|
269
|
+
- [`@abapify/adt-playwright`](../adt-playwright) - Playwright adapter (recommended)
|
|
270
|
+
- [`@abapify/adt-puppeteer`](../adt-puppeteer) - Puppeteer adapter
|
|
271
|
+
- [`@abapify/adt-auth`](../adt-auth) - Authentication manager
|
|
272
|
+
- [`@abapify/adt-config`](../adt-config) - Configuration utilities
|
package/package.json
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abapify/browser-auth",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
5
|
-
|
|
3
|
+
"version": "0.3.6",
|
|
4
|
+
"description": "Browser-based SSO authentication core - shared logic for Playwright/Puppeteer plugins",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"types": "./dist/index.d.mts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": "./dist/index.mjs",
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@abapify/adt-config": "0.3.6"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^22.10.2"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/abapify/adt-cli.git",
|
|
28
|
+
"directory": "packages/browser-auth"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/abapify/adt-cli/tree/main/packages/browser-auth#readme",
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/abapify/adt-cli/issues"
|
|
33
|
+
}
|
|
34
|
+
}
|