oidc-spa 6.13.2 → 6.14.1
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 +5 -2
- package/core/OidcMetadata.d.ts +266 -0
- package/core/OidcMetadata.js +5 -0
- package/core/OidcMetadata.js.map +1 -0
- package/core/createOidc.d.ts +13 -0
- package/core/createOidc.js +9 -6
- package/core/createOidc.js.map +1 -1
- package/core/debug966975.d.ts +7 -0
- package/core/debug966975.js +88 -0
- package/core/debug966975.js.map +1 -0
- package/core/handleOidcCallback.js +49 -11
- package/core/handleOidcCallback.js.map +1 -1
- package/core/loginSilent.d.ts +1 -0
- package/core/loginSilent.js +5 -3
- package/core/loginSilent.js.map +1 -1
- package/core/oidcClientTsUserToTokens.js +1 -1
- package/core/oidcClientTsUserToTokens.js.map +1 -1
- package/package.json +13 -1
- package/src/core/OidcMetadata.ts +271 -0
- package/src/core/createOidc.ts +22 -4
- package/src/core/debug966975.ts +85 -0
- package/src/core/handleOidcCallback.ts +75 -9
- package/src/core/loginSilent.ts +7 -2
- package/src/core/oidcClientTsUserToTokens.ts +1 -1
- package/src/tools/getUserEnvironmentInfo.ts +42 -0
- package/tools/getUserEnvironmentInfo.d.ts +1 -0
- package/tools/getUserEnvironmentInfo.js +48 -0
- package/tools/getUserEnvironmentInfo.js.map +1 -0
package/src/core/createOidc.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
type User as OidcClientTsUser,
|
|
5
5
|
InMemoryWebStorage
|
|
6
6
|
} from "../vendor/frontend/oidc-client-ts-and-jwt-decode";
|
|
7
|
+
import type { OidcMetadata } from "./OidcMetadata";
|
|
7
8
|
import { id, assert, is, type Equals } from "../vendor/frontend/tsafe";
|
|
8
9
|
import { setTimeout, clearTimeout } from "../tools/workerTimers";
|
|
9
10
|
import { Deferred } from "../tools/Deferred";
|
|
@@ -165,6 +166,19 @@ export type ParamsOfCreateOidc<
|
|
|
165
166
|
* Use at your own risk, this is a hack.
|
|
166
167
|
*/
|
|
167
168
|
__unsafe_useIdTokenAsAccessToken?: boolean;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* This option should only be used as a last resort.
|
|
172
|
+
*
|
|
173
|
+
* If your OIDC provider is correctly configured, this should not be necessary.
|
|
174
|
+
*
|
|
175
|
+
* The metadata is normally retrieved automatically from:
|
|
176
|
+
* `${issuerUri}/.well-known/openid-configuration`
|
|
177
|
+
*
|
|
178
|
+
* Use this only if that endpoint is not accessible (e.g. due to missing CORS headers
|
|
179
|
+
* or non-standard deployments), and you cannot fix the server-side configuration.
|
|
180
|
+
*/
|
|
181
|
+
__metadata?: Partial<OidcMetadata>;
|
|
168
182
|
};
|
|
169
183
|
|
|
170
184
|
const globalContext = {
|
|
@@ -287,7 +301,8 @@ export async function createOidc_nonMemoized<
|
|
|
287
301
|
autoLogin = false,
|
|
288
302
|
postLoginRedirectUrl: postLoginRedirectUrl_default,
|
|
289
303
|
__unsafe_clientSecret,
|
|
290
|
-
__unsafe_useIdTokenAsAccessToken = false
|
|
304
|
+
__unsafe_useIdTokenAsAccessToken = false,
|
|
305
|
+
__metadata
|
|
291
306
|
} = params;
|
|
292
307
|
|
|
293
308
|
const { issuerUri, clientId, scopes, configId, log } = preProcessedParams;
|
|
@@ -416,7 +431,8 @@ export async function createOidc_nonMemoized<
|
|
|
416
431
|
}),
|
|
417
432
|
stateStore: new WebStorageStateStore({ store: localStorage, prefix: STATE_STORE_KEY_PREFIX }),
|
|
418
433
|
client_secret: __unsafe_clientSecret,
|
|
419
|
-
fetch: trustedFetch
|
|
434
|
+
fetch: trustedFetch,
|
|
435
|
+
metadata: __metadata
|
|
420
436
|
});
|
|
421
437
|
|
|
422
438
|
const evtIsUserLoggedIn = createEvt<boolean>();
|
|
@@ -638,7 +654,8 @@ export async function createOidc_nonMemoized<
|
|
|
638
654
|
configId,
|
|
639
655
|
transformUrlBeforeRedirect_next,
|
|
640
656
|
getExtraQueryParams,
|
|
641
|
-
getExtraTokenParams
|
|
657
|
+
getExtraTokenParams,
|
|
658
|
+
autoLogin
|
|
642
659
|
});
|
|
643
660
|
|
|
644
661
|
assert(result_loginSilent.outcome !== "token refreshed using refresh token", "876995");
|
|
@@ -1029,7 +1046,8 @@ export async function createOidc_nonMemoized<
|
|
|
1029
1046
|
configId,
|
|
1030
1047
|
transformUrlBeforeRedirect_next,
|
|
1031
1048
|
getExtraQueryParams,
|
|
1032
|
-
getExtraTokenParams: () => extraTokenParams
|
|
1049
|
+
getExtraTokenParams: () => extraTokenParams,
|
|
1050
|
+
autoLogin
|
|
1033
1051
|
});
|
|
1034
1052
|
|
|
1035
1053
|
if (result_loginSilent.outcome === "failure") {
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { getUserEnvironmentInfo } from "../tools/getUserEnvironmentInfo";
|
|
2
|
+
|
|
3
|
+
const LOCAL_STORAGE_KEY = "oidc-spa_966975_diagnostic";
|
|
4
|
+
const appInstanceId = Math.random().toString(36).slice(2);
|
|
5
|
+
|
|
6
|
+
type LogEntry = {
|
|
7
|
+
appInstanceId: string;
|
|
8
|
+
time: number;
|
|
9
|
+
message: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
function log(message: string) {
|
|
13
|
+
const logEntry: LogEntry = {
|
|
14
|
+
appInstanceId,
|
|
15
|
+
time: Date.now(),
|
|
16
|
+
message
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const value = localStorage.getItem(LOCAL_STORAGE_KEY);
|
|
20
|
+
|
|
21
|
+
const value_parsed: LogEntry[] = value === null ? [] : JSON.parse(value);
|
|
22
|
+
|
|
23
|
+
if (value_parsed.length === 100) {
|
|
24
|
+
value_parsed.shift();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
value_parsed.push(logEntry);
|
|
28
|
+
|
|
29
|
+
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(value_parsed));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function report() {
|
|
33
|
+
const logEntries: LogEntry[] = (() => {
|
|
34
|
+
const value = localStorage.getItem(LOCAL_STORAGE_KEY);
|
|
35
|
+
|
|
36
|
+
if (value === null) {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return JSON.parse(value);
|
|
41
|
+
})();
|
|
42
|
+
|
|
43
|
+
localStorage.removeItem(LOCAL_STORAGE_KEY);
|
|
44
|
+
|
|
45
|
+
const report = [
|
|
46
|
+
getUserEnvironmentInfo(),
|
|
47
|
+
...logEntries.map(
|
|
48
|
+
({ appInstanceId, time, message }) => `${appInstanceId} (${time}): ${message}`
|
|
49
|
+
),
|
|
50
|
+
getOidcLocalStorageDump()
|
|
51
|
+
].join("\n");
|
|
52
|
+
|
|
53
|
+
const key_report = `${LOCAL_STORAGE_KEY}_report_b64`;
|
|
54
|
+
|
|
55
|
+
localStorage.setItem(key_report, btoa(report));
|
|
56
|
+
|
|
57
|
+
console.warn(
|
|
58
|
+
[
|
|
59
|
+
"If you see this message there's been unexpected behavior in oidc-spa",
|
|
60
|
+
"It is a hard to reproduce case, could you please open an issue on https://github.com/keycloakify/oidc-spa",
|
|
61
|
+
`and include the value of \`localStorage["${key_report}"]\` in the message?`,
|
|
62
|
+
"Alternatively, you can send an email at joseph.garrone@protonmail.com",
|
|
63
|
+
"Thanks in advance for helping me figure this out"
|
|
64
|
+
].join(" ")
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const debug966975 = {
|
|
69
|
+
log,
|
|
70
|
+
report
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
function getOidcLocalStorageDump(): string {
|
|
74
|
+
const entries: string[] = [];
|
|
75
|
+
|
|
76
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
77
|
+
const key = localStorage.key(i);
|
|
78
|
+
if (key && key.startsWith("oidc.")) {
|
|
79
|
+
const value = localStorage.getItem(key);
|
|
80
|
+
entries.push(`${key} = ${value}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return entries.join("\n");
|
|
85
|
+
}
|
|
@@ -8,6 +8,7 @@ import { assert, id } from "../vendor/frontend/tsafe";
|
|
|
8
8
|
import type { AuthResponse } from "./AuthResponse";
|
|
9
9
|
import { initialLocationHref } from "./initialLocationHref";
|
|
10
10
|
import { captureFetch } from "./trustedFetch";
|
|
11
|
+
import { debug966975 } from "./debug966975";
|
|
11
12
|
|
|
12
13
|
captureFetch();
|
|
13
14
|
|
|
@@ -15,8 +16,19 @@ const globalContext = {
|
|
|
15
16
|
previousCall: id<{ isHandled: boolean } | undefined>(undefined)
|
|
16
17
|
};
|
|
17
18
|
|
|
19
|
+
debug966975.log(
|
|
20
|
+
`=================== Evaluating the handleOidcCallback file, isInIframe: ${
|
|
21
|
+
window.self !== window.top ? "true" : "false"
|
|
22
|
+
}, location.href: ${initialLocationHref}`
|
|
23
|
+
);
|
|
24
|
+
|
|
18
25
|
export function handleOidcCallback(): { isHandled: boolean } {
|
|
19
26
|
if (globalContext.previousCall !== undefined) {
|
|
27
|
+
debug966975.log(
|
|
28
|
+
`handleOidcCallback() call, it has been called previously ${JSON.stringify(
|
|
29
|
+
globalContext.previousCall
|
|
30
|
+
)}`
|
|
31
|
+
);
|
|
20
32
|
return globalContext.previousCall;
|
|
21
33
|
}
|
|
22
34
|
|
|
@@ -24,16 +36,20 @@ export function handleOidcCallback(): { isHandled: boolean } {
|
|
|
24
36
|
}
|
|
25
37
|
|
|
26
38
|
function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
|
|
39
|
+
debug966975.log(`In handleOidcCallback_nonMemoized()`);
|
|
40
|
+
|
|
27
41
|
const location_urlObj = new URL(initialLocationHref);
|
|
28
42
|
|
|
29
43
|
const stateQueryParamValue = (() => {
|
|
30
44
|
const stateQueryParamValue = location_urlObj.searchParams.get("state");
|
|
31
45
|
|
|
32
46
|
if (stateQueryParamValue === null) {
|
|
47
|
+
debug966975.log("No state in url");
|
|
33
48
|
return undefined;
|
|
34
49
|
}
|
|
35
50
|
|
|
36
51
|
if (!getIsStatQueryParamValue({ maybeStateQueryParamValue: stateQueryParamValue })) {
|
|
52
|
+
debug966975.log(`State query param value ${stateQueryParamValue} is malformed`);
|
|
37
53
|
return undefined;
|
|
38
54
|
}
|
|
39
55
|
|
|
@@ -42,6 +58,9 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
|
|
|
42
58
|
location_urlObj.searchParams.get("response_type") !== null &&
|
|
43
59
|
location_urlObj.searchParams.get("redirect_uri") !== null
|
|
44
60
|
) {
|
|
61
|
+
debug966975.log(
|
|
62
|
+
"NOTE: We are probably in a Keycloakify theme and oidc-spa was loaded by mistake."
|
|
63
|
+
);
|
|
45
64
|
// NOTE: We are probably in a Keycloakify theme and oidc-spa was loaded by mistake.
|
|
46
65
|
return undefined;
|
|
47
66
|
}
|
|
@@ -49,9 +68,13 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
|
|
|
49
68
|
return stateQueryParamValue;
|
|
50
69
|
})();
|
|
51
70
|
|
|
71
|
+
debug966975.log(`state query param value ${stateQueryParamValue ?? "undefined"}`);
|
|
72
|
+
|
|
52
73
|
if (stateQueryParamValue === undefined) {
|
|
53
74
|
const backForwardTracker = readBackForwardTracker();
|
|
54
75
|
|
|
76
|
+
debug966975.log(`backForwardTracker: ${JSON.stringify(backForwardTracker)}`);
|
|
77
|
+
|
|
55
78
|
if (backForwardTracker !== undefined) {
|
|
56
79
|
writeBackForwardTracker({
|
|
57
80
|
backForwardTracker: {
|
|
@@ -61,6 +84,8 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
|
|
|
61
84
|
});
|
|
62
85
|
}
|
|
63
86
|
|
|
87
|
+
debug966975.log("returning isHandled false");
|
|
88
|
+
|
|
64
89
|
return { isHandled: false };
|
|
65
90
|
}
|
|
66
91
|
|
|
@@ -73,6 +98,8 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
|
|
|
73
98
|
|
|
74
99
|
const stateData = getStateData({ stateQueryParamValue });
|
|
75
100
|
|
|
101
|
+
debug966975.log(`stateData: ${JSON.stringify(stateData)}`);
|
|
102
|
+
|
|
76
103
|
if (
|
|
77
104
|
stateData === undefined ||
|
|
78
105
|
(stateData.context === "redirect" && stateData.hasBeenProcessedByCallback)
|
|
@@ -96,6 +123,8 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
|
|
|
96
123
|
}
|
|
97
124
|
})();
|
|
98
125
|
|
|
126
|
+
debug966975.log(`historyMethod: ${historyMethod}`);
|
|
127
|
+
|
|
99
128
|
writeBackForwardTracker({
|
|
100
129
|
backForwardTracker: {
|
|
101
130
|
previousHistoryMethod: historyMethod,
|
|
@@ -105,7 +134,13 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
|
|
|
105
134
|
|
|
106
135
|
reloadOnBfCacheNavigation();
|
|
107
136
|
|
|
108
|
-
|
|
137
|
+
setTimeout(() => {
|
|
138
|
+
debug966975.log(`(callback 0) Calling window.history.${historyMethod}()`);
|
|
139
|
+
|
|
140
|
+
window.history[historyMethod]();
|
|
141
|
+
}, 0);
|
|
142
|
+
|
|
143
|
+
debug966975.log(`returning isHandled: ${isHandled ? "true" : "false"}`);
|
|
109
144
|
|
|
110
145
|
return { isHandled };
|
|
111
146
|
}
|
|
@@ -118,9 +153,14 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
|
|
|
118
153
|
|
|
119
154
|
assert(authResponse.state !== "", "063965");
|
|
120
155
|
|
|
156
|
+
debug966975.log(`authResponse: ${JSON.stringify(authResponse)}`);
|
|
157
|
+
|
|
121
158
|
switch (stateData.context) {
|
|
122
159
|
case "iframe":
|
|
123
|
-
|
|
160
|
+
setTimeout(() => {
|
|
161
|
+
debug966975.log(`(callback 0) posting message to parent`);
|
|
162
|
+
parent.postMessage(authResponse, location.origin);
|
|
163
|
+
}, 0);
|
|
124
164
|
break;
|
|
125
165
|
case "redirect":
|
|
126
166
|
markStateDataAsProcessedByCallback({ stateQueryParamValue });
|
|
@@ -129,16 +169,24 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
|
|
|
129
169
|
authResponses: [...readRedirectAuthResponses(), authResponse]
|
|
130
170
|
});
|
|
131
171
|
reloadOnBfCacheNavigation();
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
172
|
+
setTimeout(() => {
|
|
173
|
+
const href = (() => {
|
|
174
|
+
if (stateData.action === "login" && authResponse.error === "consent_required") {
|
|
175
|
+
return stateData.redirectUrl_consentRequiredCase;
|
|
176
|
+
}
|
|
136
177
|
|
|
137
|
-
|
|
138
|
-
|
|
178
|
+
return stateData.redirectUrl;
|
|
179
|
+
})();
|
|
180
|
+
|
|
181
|
+
debug966975.log(`(callback 0) location.href = "${href}";`);
|
|
182
|
+
|
|
183
|
+
location.href = href;
|
|
184
|
+
}, 0);
|
|
139
185
|
break;
|
|
140
186
|
}
|
|
141
187
|
|
|
188
|
+
debug966975.log(`Returning isHandled: ${isHandled ? "true" : "false"}`);
|
|
189
|
+
|
|
142
190
|
return { isHandled };
|
|
143
191
|
}
|
|
144
192
|
|
|
@@ -172,16 +220,31 @@ export function retrieveRedirectAuthResponseAndStateData(params: {
|
|
|
172
220
|
}): { authResponse: AuthResponse; stateData: StateData.Redirect } | undefined {
|
|
173
221
|
const { configId } = params;
|
|
174
222
|
|
|
223
|
+
debug966975.log(`>>> In retrieveRedirectAuthResponseAndStateData(${JSON.stringify({ configId })})`);
|
|
224
|
+
|
|
175
225
|
const authResponses = readRedirectAuthResponses();
|
|
176
226
|
|
|
227
|
+
debug966975.log(`authResponses: ${JSON.stringify(authResponses)}`);
|
|
228
|
+
|
|
177
229
|
let authResponseAndStateData:
|
|
178
230
|
| { authResponse: AuthResponse; stateData: StateData.Redirect }
|
|
179
231
|
| undefined = undefined;
|
|
180
232
|
|
|
181
233
|
for (const authResponse of [...authResponses]) {
|
|
234
|
+
debug966975.log(`authResponse: ${JSON.stringify(authResponse)}`);
|
|
235
|
+
|
|
182
236
|
const stateData = getStateData({ stateQueryParamValue: authResponse.state });
|
|
183
237
|
|
|
184
|
-
|
|
238
|
+
debug966975.log(`stateDate: ${JSON.stringify(stateData)}`);
|
|
239
|
+
|
|
240
|
+
try {
|
|
241
|
+
assert(stateData !== undefined, "966975");
|
|
242
|
+
} catch {
|
|
243
|
+
authResponses.splice(authResponses.indexOf(authResponse), 1);
|
|
244
|
+
debug966975.report();
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
|
|
185
248
|
assert(stateData.context === "redirect", "474728");
|
|
186
249
|
|
|
187
250
|
if (stateData.configId !== configId) {
|
|
@@ -194,9 +257,12 @@ export function retrieveRedirectAuthResponseAndStateData(params: {
|
|
|
194
257
|
}
|
|
195
258
|
|
|
196
259
|
if (authResponseAndStateData !== undefined) {
|
|
260
|
+
debug966975.log(`writeRedirectAuthResponses(${JSON.stringify({ authResponses })})`);
|
|
197
261
|
writeRedirectAuthResponses({ authResponses });
|
|
198
262
|
}
|
|
199
263
|
|
|
264
|
+
debug966975.log(`Returning ${JSON.stringify({ authResponseAndStateData })} <<<<<<<<<`);
|
|
265
|
+
|
|
200
266
|
return authResponseAndStateData;
|
|
201
267
|
}
|
|
202
268
|
|
package/src/core/loginSilent.ts
CHANGED
|
@@ -36,6 +36,7 @@ export async function loginSilent(params: {
|
|
|
36
36
|
| undefined;
|
|
37
37
|
|
|
38
38
|
getExtraTokenParams: (() => Record<string, string | undefined>) | undefined;
|
|
39
|
+
autoLogin: boolean;
|
|
39
40
|
}): Promise<ResultOfLoginSilent> {
|
|
40
41
|
const {
|
|
41
42
|
oidcClientTsUserManager,
|
|
@@ -43,17 +44,21 @@ export async function loginSilent(params: {
|
|
|
43
44
|
configId,
|
|
44
45
|
transformUrlBeforeRedirect_next,
|
|
45
46
|
getExtraQueryParams,
|
|
46
|
-
getExtraTokenParams
|
|
47
|
+
getExtraTokenParams,
|
|
48
|
+
autoLogin
|
|
47
49
|
} = params;
|
|
48
50
|
|
|
49
51
|
const dResult = new Deferred<ResultOfLoginSilent>();
|
|
50
52
|
|
|
51
53
|
const timeoutDelayMs: number = (() => {
|
|
54
|
+
if (autoLogin) {
|
|
55
|
+
return 25_000;
|
|
56
|
+
}
|
|
57
|
+
|
|
52
58
|
const downlinkAndRtt = getDownlinkAndRtt();
|
|
53
59
|
const isDev = getIsDev();
|
|
54
60
|
|
|
55
61
|
// Base delay is the minimum delay we should wait in any case
|
|
56
|
-
//const BASE_DELAY_MS = 3000;
|
|
57
62
|
const BASE_DELAY_MS = isDev ? 9_000 : 7_000;
|
|
58
63
|
|
|
59
64
|
if (downlinkAndRtt === undefined) {
|
|
@@ -148,7 +148,7 @@ export function oidcClientTsUserToTokens<DecodedIdToken extends Record<string, u
|
|
|
148
148
|
) {
|
|
149
149
|
console.warn(
|
|
150
150
|
[
|
|
151
|
-
"The OIDC refresh token shorter than the one of the access token.",
|
|
151
|
+
"The OIDC refresh token expirationTime is shorter than the one of the access token.",
|
|
152
152
|
"This is very unusual and probably a misconfiguration."
|
|
153
153
|
].join(" ")
|
|
154
154
|
);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export function getUserEnvironmentInfo(): string {
|
|
2
|
+
function safeGet<T>(getter: () => T, fallback: string = "Unknown"): string {
|
|
3
|
+
try {
|
|
4
|
+
const value = getter();
|
|
5
|
+
return value != null ? String(value) : fallback;
|
|
6
|
+
} catch {
|
|
7
|
+
return fallback;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const ua = safeGet(() => navigator.userAgent);
|
|
12
|
+
const platform = safeGet(() => navigator.platform);
|
|
13
|
+
const language = safeGet(() => navigator.language || (navigator as any).userLanguage);
|
|
14
|
+
const screenSize = safeGet(() => `${screen.width}x${screen.height}`);
|
|
15
|
+
const timezone = safeGet(() => Intl.DateTimeFormat().resolvedOptions().timeZone);
|
|
16
|
+
|
|
17
|
+
const browser: string = (() => {
|
|
18
|
+
if (ua.includes("Firefox/")) return "Firefox";
|
|
19
|
+
if (ua.includes("Edg/")) return "Edge";
|
|
20
|
+
if (ua.includes("Chrome/") && !ua.includes("Edg/")) return "Chrome";
|
|
21
|
+
if (ua.includes("Safari/") && !ua.includes("Chrome/")) return "Safari";
|
|
22
|
+
if (ua.includes("OPR/") || ua.includes("Opera/")) return "Opera";
|
|
23
|
+
return "Unknown";
|
|
24
|
+
})();
|
|
25
|
+
|
|
26
|
+
const os: string = (() => {
|
|
27
|
+
if (platform.startsWith("Win")) return "Windows";
|
|
28
|
+
if (platform.startsWith("Mac")) return "macOS";
|
|
29
|
+
if (platform.startsWith("Linux")) return "Linux";
|
|
30
|
+
if (/Android/.test(ua)) return "Android";
|
|
31
|
+
if (/iPhone|iPad|iPod/.test(ua)) return "iOS";
|
|
32
|
+
return "Unknown";
|
|
33
|
+
})();
|
|
34
|
+
|
|
35
|
+
return `Browser: ${browser}
|
|
36
|
+
OS: ${os}
|
|
37
|
+
Platform: ${platform}
|
|
38
|
+
Language: ${language}
|
|
39
|
+
Screen: ${screenSize}
|
|
40
|
+
Timezone: ${timezone}
|
|
41
|
+
User Agent: ${ua}`;
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getUserEnvironmentInfo(): string;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getUserEnvironmentInfo = getUserEnvironmentInfo;
|
|
4
|
+
function getUserEnvironmentInfo() {
|
|
5
|
+
function safeGet(getter, fallback) {
|
|
6
|
+
if (fallback === void 0) { fallback = "Unknown"; }
|
|
7
|
+
try {
|
|
8
|
+
var value = getter();
|
|
9
|
+
return value != null ? String(value) : fallback;
|
|
10
|
+
}
|
|
11
|
+
catch (_a) {
|
|
12
|
+
return fallback;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
var ua = safeGet(function () { return navigator.userAgent; });
|
|
16
|
+
var platform = safeGet(function () { return navigator.platform; });
|
|
17
|
+
var language = safeGet(function () { return navigator.language || navigator.userLanguage; });
|
|
18
|
+
var screenSize = safeGet(function () { return "".concat(screen.width, "x").concat(screen.height); });
|
|
19
|
+
var timezone = safeGet(function () { return Intl.DateTimeFormat().resolvedOptions().timeZone; });
|
|
20
|
+
var browser = (function () {
|
|
21
|
+
if (ua.includes("Firefox/"))
|
|
22
|
+
return "Firefox";
|
|
23
|
+
if (ua.includes("Edg/"))
|
|
24
|
+
return "Edge";
|
|
25
|
+
if (ua.includes("Chrome/") && !ua.includes("Edg/"))
|
|
26
|
+
return "Chrome";
|
|
27
|
+
if (ua.includes("Safari/") && !ua.includes("Chrome/"))
|
|
28
|
+
return "Safari";
|
|
29
|
+
if (ua.includes("OPR/") || ua.includes("Opera/"))
|
|
30
|
+
return "Opera";
|
|
31
|
+
return "Unknown";
|
|
32
|
+
})();
|
|
33
|
+
var os = (function () {
|
|
34
|
+
if (platform.startsWith("Win"))
|
|
35
|
+
return "Windows";
|
|
36
|
+
if (platform.startsWith("Mac"))
|
|
37
|
+
return "macOS";
|
|
38
|
+
if (platform.startsWith("Linux"))
|
|
39
|
+
return "Linux";
|
|
40
|
+
if (/Android/.test(ua))
|
|
41
|
+
return "Android";
|
|
42
|
+
if (/iPhone|iPad|iPod/.test(ua))
|
|
43
|
+
return "iOS";
|
|
44
|
+
return "Unknown";
|
|
45
|
+
})();
|
|
46
|
+
return "Browser: ".concat(browser, "\nOS: ").concat(os, "\nPlatform: ").concat(platform, "\nLanguage: ").concat(language, "\nScreen: ").concat(screenSize, "\nTimezone: ").concat(timezone, "\nUser Agent: ").concat(ua);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=getUserEnvironmentInfo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getUserEnvironmentInfo.js","sourceRoot":"","sources":["../src/tools/getUserEnvironmentInfo.ts"],"names":[],"mappings":";;AAAA,wDAyCC;AAzCD,SAAgB,sBAAsB;IAClC,SAAS,OAAO,CAAI,MAAe,EAAE,QAA4B;QAA5B,yBAAA,EAAA,oBAA4B;QAC7D,IAAI,CAAC;YACD,IAAM,KAAK,GAAG,MAAM,EAAE,CAAC;YACvB,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QACpD,CAAC;QAAC,WAAM,CAAC;YACL,OAAO,QAAQ,CAAC;QACpB,CAAC;IACL,CAAC;IAED,IAAM,EAAE,GAAG,OAAO,CAAC,cAAM,OAAA,SAAS,CAAC,SAAS,EAAnB,CAAmB,CAAC,CAAC;IAC9C,IAAM,QAAQ,GAAG,OAAO,CAAC,cAAM,OAAA,SAAS,CAAC,QAAQ,EAAlB,CAAkB,CAAC,CAAC;IACnD,IAAM,QAAQ,GAAG,OAAO,CAAC,cAAM,OAAA,SAAS,CAAC,QAAQ,IAAK,SAAiB,CAAC,YAAY,EAArD,CAAqD,CAAC,CAAC;IACtF,IAAM,UAAU,GAAG,OAAO,CAAC,cAAM,OAAA,UAAG,MAAM,CAAC,KAAK,cAAI,MAAM,CAAC,MAAM,CAAE,EAAlC,CAAkC,CAAC,CAAC;IACrE,IAAM,QAAQ,GAAG,OAAO,CAAC,cAAM,OAAA,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ,EAAhD,CAAgD,CAAC,CAAC;IAEjF,IAAM,OAAO,GAAW,CAAC;QACrB,IAAI,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC;YAAE,OAAO,SAAS,CAAC;QAC9C,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;QACvC,IAAI,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,QAAQ,CAAC;QACpE,IAAI,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,OAAO,QAAQ,CAAC;QACvE,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,OAAO,OAAO,CAAC;QACjE,OAAO,SAAS,CAAC;IACrB,CAAC,CAAC,EAAE,CAAC;IAEL,IAAM,EAAE,GAAW,CAAC;QAChB,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QACjD,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,OAAO,OAAO,CAAC;QAC/C,IAAI,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,OAAO,OAAO,CAAC;QACjD,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,OAAO,SAAS,CAAC;QACzC,IAAI,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,OAAO,KAAK,CAAC;QAC9C,OAAO,SAAS,CAAC;IACrB,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO,mBAAY,OAAO,mBACxB,EAAE,yBACI,QAAQ,yBACR,QAAQ,uBACV,UAAU,yBACR,QAAQ,2BACN,EAAE,CAAE,CAAC;AACnB,CAAC"}
|