@dynamic-labs/utils 3.0.0-alpha.6 → 3.0.0-alpha.60
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/CHANGELOG.md +585 -0
- package/_virtual/_tslib.cjs +15 -0
- package/_virtual/_tslib.js +14 -1
- package/package.json +4 -4
- package/src/errors/MfaInvalidOtpError.cjs +1 -1
- package/src/errors/MfaInvalidOtpError.js +1 -1
- package/src/errors/MfaRateLimitedError.cjs +14 -0
- package/src/errors/MfaRateLimitedError.d.ts +4 -0
- package/src/errors/MfaRateLimitedError.js +10 -0
- package/src/errors/NoAccessError.cjs +3 -1
- package/src/errors/NoAccessError.d.ts +5 -1
- package/src/errors/NoAccessError.js +3 -1
- package/src/errors/SandboxMaximumThresholdReachedError.cjs +15 -0
- package/src/errors/SandboxMaximumThresholdReachedError.d.ts +5 -0
- package/src/errors/SandboxMaximumThresholdReachedError.js +11 -0
- package/src/errors/UserRejectedRequestError.cjs +14 -0
- package/src/errors/UserRejectedRequestError.d.ts +4 -0
- package/src/errors/UserRejectedRequestError.js +10 -0
- package/src/errors/WalletAddressMismatchError.cjs +17 -0
- package/src/errors/WalletAddressMismatchError.d.ts +11 -0
- package/src/errors/WalletAddressMismatchError.js +13 -0
- package/src/errors/index.d.ts +4 -0
- package/src/handleMobileWalletRedirect/handleMobileWalletRedirect.cjs +0 -6
- package/src/handleMobileWalletRedirect/handleMobileWalletRedirect.js +0 -6
- package/src/index.cjs +15 -0
- package/src/index.d.ts +2 -0
- package/src/index.js +8 -1
- package/src/isMobile.cjs +11 -0
- package/src/isMobile.d.ts +1 -0
- package/src/isMobile.js +11 -1
- package/src/nativeMobileOauthStateParam.cjs +13 -0
- package/src/nativeMobileOauthStateParam.d.ts +14 -0
- package/src/nativeMobileOauthStateParam.js +9 -0
- package/src/retryableFn.cjs +1 -5
- package/src/retryableFn.js +1 -5
- package/src/services/FetchService/FetchService.cjs +10 -5
- package/src/services/FetchService/FetchService.d.ts +2 -2
- package/src/services/FetchService/FetchService.js +10 -5
- package/src/services/Oauth2Service/Oauth2Service.cjs +38 -0
- package/src/services/Oauth2Service/Oauth2Service.d.ts +41 -0
- package/src/services/Oauth2Service/Oauth2Service.js +34 -0
- package/src/services/Oauth2Service/createWindowOauth2Service/createWindowOauth2Service.cjs +176 -0
- package/src/services/Oauth2Service/createWindowOauth2Service/createWindowOauth2Service.d.ts +2 -0
- package/src/services/Oauth2Service/createWindowOauth2Service/createWindowOauth2Service.js +172 -0
- package/src/services/Oauth2Service/createWindowOauth2Service/index.d.ts +1 -0
- package/src/services/Oauth2Service/index.d.ts +2 -0
- package/src/services/Oauth2Service/utils/connectWithAppleId/connectWithAppleId.cjs +26 -0
- package/src/services/Oauth2Service/utils/connectWithAppleId/connectWithAppleId.d.ts +7 -0
- package/src/services/Oauth2Service/utils/connectWithAppleId/connectWithAppleId.js +22 -0
- package/src/services/Oauth2Service/utils/connectWithAppleId/index.d.ts +1 -0
- package/src/services/Oauth2Service/utils/loadAppleId/index.d.ts +1 -0
- package/src/services/Oauth2Service/utils/loadAppleId/loadAppleId.cjs +34 -0
- package/src/services/Oauth2Service/utils/loadAppleId/loadAppleId.d.ts +1 -0
- package/src/services/Oauth2Service/utils/loadAppleId/loadAppleId.js +30 -0
- package/src/services/PlatformService/PlatformService.cjs +38 -13
- package/src/services/PlatformService/PlatformService.d.ts +25 -3
- package/src/services/PlatformService/PlatformService.js +40 -15
- package/src/services/PlatformService/createBrowserPlatformService/createBrowserPlatformService.cjs +1 -3
- package/src/services/PlatformService/createBrowserPlatformService/createBrowserPlatformService.js +1 -3
- package/src/services/PlatformService/types.d.ts +5 -4
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
'use client'
|
|
2
|
+
import { __classPrivateFieldGet, __classPrivateFieldSet } from '../../../_virtual/_tslib.js';
|
|
3
|
+
|
|
4
|
+
var _a, _FetchService_implementation;
|
|
2
5
|
/**
|
|
3
6
|
* Class implementing the fetch service with a configurable fetch implementation.
|
|
4
7
|
*/
|
|
5
8
|
class FetchService {
|
|
6
9
|
static get implementation() {
|
|
7
|
-
if (!
|
|
10
|
+
if (!__classPrivateFieldGet(_a, _a, "f", _FetchService_implementation)) {
|
|
8
11
|
return { fetch: window.fetch.bind(window) };
|
|
9
12
|
}
|
|
10
|
-
return
|
|
13
|
+
return __classPrivateFieldGet(_a, _a, "f", _FetchService_implementation);
|
|
11
14
|
}
|
|
12
|
-
static
|
|
13
|
-
|
|
15
|
+
static set implementation(implementation) {
|
|
16
|
+
__classPrivateFieldSet(_a, _a, implementation, "f", _FetchService_implementation);
|
|
14
17
|
}
|
|
15
18
|
static get fetch() {
|
|
16
|
-
return
|
|
19
|
+
return _a.implementation.fetch;
|
|
17
20
|
}
|
|
18
21
|
}
|
|
22
|
+
_a = FetchService;
|
|
23
|
+
_FetchService_implementation = { value: void 0 };
|
|
19
24
|
|
|
20
25
|
export { FetchService };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var _tslib = require('../../../_virtual/_tslib.cjs');
|
|
7
|
+
var types = require('@dynamic-labs/types');
|
|
8
|
+
var createWindowOauth2Service = require('./createWindowOauth2Service/createWindowOauth2Service.cjs');
|
|
9
|
+
|
|
10
|
+
var _a, _Oauth2Service_implementation;
|
|
11
|
+
/**
|
|
12
|
+
* Class implementing the fetch service with a configurable fetch implementation.
|
|
13
|
+
*/
|
|
14
|
+
class Oauth2Service {
|
|
15
|
+
static get implementation() {
|
|
16
|
+
if (!_tslib.__classPrivateFieldGet(_a, _a, "f", _Oauth2Service_implementation)) {
|
|
17
|
+
return createWindowOauth2Service.createWindowOauth2Service();
|
|
18
|
+
}
|
|
19
|
+
return _tslib.__classPrivateFieldGet(_a, _a, "f", _Oauth2Service_implementation);
|
|
20
|
+
}
|
|
21
|
+
static set implementation(implementation) {
|
|
22
|
+
_tslib.__classPrivateFieldSet(_a, _a, implementation, "f", _Oauth2Service_implementation);
|
|
23
|
+
}
|
|
24
|
+
static get getOauthCode() {
|
|
25
|
+
return _a.implementation.getOauthCode;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
_a = Oauth2Service;
|
|
29
|
+
_Oauth2Service_implementation = { value: void 0 };
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
|
+
Oauth2Service.isGetOauthCodeError = (error) => error === 'user-cancelled' ||
|
|
32
|
+
(typeof error === 'object' &&
|
|
33
|
+
'code' in error &&
|
|
34
|
+
Object.values(types.SocialOAuthErrorCode).includes(error.code) &&
|
|
35
|
+
'message' in error &&
|
|
36
|
+
typeof error.message === 'string');
|
|
37
|
+
|
|
38
|
+
exports.Oauth2Service = Oauth2Service;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { OauthResultResponse, Provider, ProviderEnum } from '@dynamic-labs/sdk-api-core';
|
|
2
|
+
import { SocialOAuthErrorCode } from '@dynamic-labs/types';
|
|
3
|
+
export type GetOauthCodeProps = {
|
|
4
|
+
provider: ProviderEnum;
|
|
5
|
+
apiProvider: Provider | undefined;
|
|
6
|
+
setIsProcessing: (value: boolean) => void;
|
|
7
|
+
onSettled?: VoidFunction;
|
|
8
|
+
getOAuthResultFromApi: () => Promise<OauthResultResponse | undefined>;
|
|
9
|
+
initWebAuth: (options?: {
|
|
10
|
+
redirectUrl?: string;
|
|
11
|
+
}) => Promise<void>;
|
|
12
|
+
state: string;
|
|
13
|
+
oauthLoginUrl: URL;
|
|
14
|
+
/**
|
|
15
|
+
* The preferred strategy to use for the OAuth2 flow.
|
|
16
|
+
*/
|
|
17
|
+
strategy: 'popup' | 'redirect';
|
|
18
|
+
sessionTimeout: number;
|
|
19
|
+
/**
|
|
20
|
+
* Overrides the default redirectUrl coming from the DynamicContextProvider
|
|
21
|
+
*/
|
|
22
|
+
redirectUrl?: string;
|
|
23
|
+
isMobile?: boolean;
|
|
24
|
+
};
|
|
25
|
+
export type IOauth2Service = {
|
|
26
|
+
getOauthCode: (props: GetOauthCodeProps) => Promise<string>;
|
|
27
|
+
};
|
|
28
|
+
export type GetOauthCodeError = 'user-cancelled' | {
|
|
29
|
+
code: SocialOAuthErrorCode;
|
|
30
|
+
message: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Class implementing the fetch service with a configurable fetch implementation.
|
|
34
|
+
*/
|
|
35
|
+
export declare class Oauth2Service {
|
|
36
|
+
#private;
|
|
37
|
+
static get implementation(): IOauth2Service;
|
|
38
|
+
static set implementation(implementation: IOauth2Service);
|
|
39
|
+
static get getOauthCode(): (props: GetOauthCodeProps) => Promise<string>;
|
|
40
|
+
static isGetOauthCodeError: (error: any) => error is GetOauthCodeError;
|
|
41
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { __classPrivateFieldGet, __classPrivateFieldSet } from '../../../_virtual/_tslib.js';
|
|
3
|
+
import { SocialOAuthErrorCode } from '@dynamic-labs/types';
|
|
4
|
+
import { createWindowOauth2Service } from './createWindowOauth2Service/createWindowOauth2Service.js';
|
|
5
|
+
|
|
6
|
+
var _a, _Oauth2Service_implementation;
|
|
7
|
+
/**
|
|
8
|
+
* Class implementing the fetch service with a configurable fetch implementation.
|
|
9
|
+
*/
|
|
10
|
+
class Oauth2Service {
|
|
11
|
+
static get implementation() {
|
|
12
|
+
if (!__classPrivateFieldGet(_a, _a, "f", _Oauth2Service_implementation)) {
|
|
13
|
+
return createWindowOauth2Service();
|
|
14
|
+
}
|
|
15
|
+
return __classPrivateFieldGet(_a, _a, "f", _Oauth2Service_implementation);
|
|
16
|
+
}
|
|
17
|
+
static set implementation(implementation) {
|
|
18
|
+
__classPrivateFieldSet(_a, _a, implementation, "f", _Oauth2Service_implementation);
|
|
19
|
+
}
|
|
20
|
+
static get getOauthCode() {
|
|
21
|
+
return _a.implementation.getOauthCode;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
_a = Oauth2Service;
|
|
25
|
+
_Oauth2Service_implementation = { value: void 0 };
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
Oauth2Service.isGetOauthCodeError = (error) => error === 'user-cancelled' ||
|
|
28
|
+
(typeof error === 'object' &&
|
|
29
|
+
'code' in error &&
|
|
30
|
+
Object.values(SocialOAuthErrorCode).includes(error.code) &&
|
|
31
|
+
'message' in error &&
|
|
32
|
+
typeof error.message === 'string');
|
|
33
|
+
|
|
34
|
+
export { Oauth2Service };
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var _tslib = require('../../../../_virtual/_tslib.cjs');
|
|
7
|
+
var types = require('@dynamic-labs/types');
|
|
8
|
+
var logger = require('../../../logger/logger.cjs');
|
|
9
|
+
var connectWithAppleId = require('../utils/connectWithAppleId/connectWithAppleId.cjs');
|
|
10
|
+
var isMobile = require('../../../isMobile.cjs');
|
|
11
|
+
|
|
12
|
+
let authWindowInterval;
|
|
13
|
+
const createWindowOauth2Service = () => ({
|
|
14
|
+
getOauthCode: ({ apiProvider, provider, redirectUrl, setIsProcessing, state, oauthLoginUrl, initWebAuth, strategy, }) => new Promise((resolve, _reject) => {
|
|
15
|
+
/**
|
|
16
|
+
* Use AppleID SDK for Apple provider on mobile
|
|
17
|
+
* It should use the strategy setting, but on ios or safari
|
|
18
|
+
* it should use the appleId always as it is the best experience
|
|
19
|
+
*/
|
|
20
|
+
if (provider === types.ProviderEnum.Apple &&
|
|
21
|
+
(isMobile.isSafariBrowser() || isMobile.isIOS() || strategy === 'redirect')) {
|
|
22
|
+
initWebAuth({
|
|
23
|
+
redirectUrl: redirectUrl || window.location.href,
|
|
24
|
+
}).then(() => connectWithAppleId.connectWithAppleId({
|
|
25
|
+
clientId: apiProvider === null || apiProvider === void 0 ? void 0 : apiProvider.clientId,
|
|
26
|
+
oauthLoginUrl,
|
|
27
|
+
state,
|
|
28
|
+
}).catch(_reject));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Use redirect flow on mobile for all providers except Telegram
|
|
33
|
+
*/
|
|
34
|
+
if (strategy === 'redirect' && provider !== types.ProviderEnum.Telegram) {
|
|
35
|
+
initWebAuth({
|
|
36
|
+
redirectUrl: redirectUrl || window.location.href,
|
|
37
|
+
}).then(() => {
|
|
38
|
+
window.location.assign(oauthLoginUrl);
|
|
39
|
+
});
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
// When we catch this error we assume it follows this type, so we must enforce it
|
|
43
|
+
// here to ensure the assumption is correct
|
|
44
|
+
const typedReject = (params) => _reject(params);
|
|
45
|
+
// Clear any potential pending timeouts and intervals
|
|
46
|
+
clearInterval(authWindowInterval);
|
|
47
|
+
const providersWaitingOauthMessage = {};
|
|
48
|
+
const authWindow = window.open('', '_blank', 'width=500,height=600');
|
|
49
|
+
const clearListeners = () => {
|
|
50
|
+
window.removeEventListener('message', handleWindowMessage);
|
|
51
|
+
providersWaitingOauthMessage[provider] = false;
|
|
52
|
+
};
|
|
53
|
+
const handleWindowMessage = (event) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
54
|
+
const message = event.data;
|
|
55
|
+
const expectedOrigin = getExpectedOrigin(apiProvider);
|
|
56
|
+
if (!expectedOrigin) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if ((message === null || message === void 0 ? void 0 : message.type) === 'origin_check' && authWindow) {
|
|
60
|
+
logger.logger.debug('Origin check message received. Sending response now.', {
|
|
61
|
+
data: message,
|
|
62
|
+
expectedOrigin,
|
|
63
|
+
});
|
|
64
|
+
authWindow.postMessage('origin_check_response', expectedOrigin);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const isTelegramCompletedMessage = (message === null || message === void 0 ? void 0 : message.type) === 'telegram_completed';
|
|
68
|
+
const isAuthorizationMessage = (message === null || message === void 0 ? void 0 : message.type) === 'authorization_response';
|
|
69
|
+
if (isAuthorizationMessage || isTelegramCompletedMessage) {
|
|
70
|
+
logger.logger.debug('Message received', { data: message });
|
|
71
|
+
}
|
|
72
|
+
const isExpectedOrigin = event.origin === expectedOrigin;
|
|
73
|
+
const isValidMessage = ((isAuthorizationMessage && (message === null || message === void 0 ? void 0 : message.provider) === provider) ||
|
|
74
|
+
isTelegramCompletedMessage) &&
|
|
75
|
+
isExpectedOrigin;
|
|
76
|
+
// don't process invalid messages for provider
|
|
77
|
+
if (!isValidMessage) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
setIsProcessing(true);
|
|
81
|
+
if (!providersWaitingOauthMessage[provider]) {
|
|
82
|
+
typedReject({
|
|
83
|
+
code: types.SocialOAuthErrorCode.SESSION_TIMEOUT,
|
|
84
|
+
message: `Connecting ${provider} account session timeout.`,
|
|
85
|
+
});
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
clearListeners();
|
|
89
|
+
if (isTelegramCompletedMessage) {
|
|
90
|
+
handleTelegramCompletionMessage(message, state);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
handleAuthorizationMessage(message, provider, state);
|
|
94
|
+
});
|
|
95
|
+
const getExpectedOrigin = (apiProvider) => {
|
|
96
|
+
if (!(apiProvider === null || apiProvider === void 0 ? void 0 : apiProvider.redirectUrl)) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
const redirectUri = new URL(apiProvider.redirectUrl);
|
|
101
|
+
return redirectUri.origin;
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
logger.logger.error('Failed to parse social provider redirect url', {
|
|
105
|
+
error: e,
|
|
106
|
+
});
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const handleTelegramCompletionMessage = (message, state) => {
|
|
111
|
+
logger.logger.debug('Telegram completion message received', {
|
|
112
|
+
data: message,
|
|
113
|
+
});
|
|
114
|
+
const { code, state: authState } = message;
|
|
115
|
+
// check that the state we receive from message is the same state we calculated earlier
|
|
116
|
+
// this could be an attack
|
|
117
|
+
if (state !== authState) {
|
|
118
|
+
typedReject({
|
|
119
|
+
code: types.SocialOAuthErrorCode.OAUTH_ERROR,
|
|
120
|
+
message: 'Failed to connect telegram account: Invalid random state',
|
|
121
|
+
});
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
resolve(code);
|
|
125
|
+
setIsProcessing(false);
|
|
126
|
+
};
|
|
127
|
+
const handleAuthorizationMessage = (message, provider, state) => {
|
|
128
|
+
const { code, error, state: authState } = message;
|
|
129
|
+
if (error && error !== 'undefined') {
|
|
130
|
+
typedReject({
|
|
131
|
+
code: types.SocialOAuthErrorCode.OAUTH_ERROR,
|
|
132
|
+
message: `Failed to connect ${provider} social account: ${error}`,
|
|
133
|
+
});
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
// check that the state we receive from message is the same state we calculated earlier
|
|
137
|
+
// this could be an attack
|
|
138
|
+
// this state check is used only by providers with an open window opener reference (eg, not twitter)
|
|
139
|
+
if (state !== authState) {
|
|
140
|
+
typedReject({
|
|
141
|
+
code: types.SocialOAuthErrorCode.OAUTH_ERROR,
|
|
142
|
+
message: `Failed to connect ${provider} social account: Invalid random state`,
|
|
143
|
+
});
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (!code) {
|
|
147
|
+
typedReject({
|
|
148
|
+
code: types.SocialOAuthErrorCode.NO_AUTH_CODE,
|
|
149
|
+
message: `Failed to connect ${provider} social account: no authorization code`,
|
|
150
|
+
});
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
resolve(code);
|
|
154
|
+
setIsProcessing(false);
|
|
155
|
+
};
|
|
156
|
+
if (!providersWaitingOauthMessage[provider]) {
|
|
157
|
+
window.addEventListener('message', handleWindowMessage);
|
|
158
|
+
providersWaitingOauthMessage[provider] = true;
|
|
159
|
+
}
|
|
160
|
+
// First we store the state in backend
|
|
161
|
+
initWebAuth().then(() => {
|
|
162
|
+
authWindow === null || authWindow === void 0 ? void 0 : authWindow.location.assign(oauthLoginUrl);
|
|
163
|
+
authWindowInterval = setInterval(() => {
|
|
164
|
+
if (!(authWindow === null || authWindow === void 0 ? void 0 : authWindow.closed))
|
|
165
|
+
return;
|
|
166
|
+
clearInterval(authWindowInterval);
|
|
167
|
+
setIsProcessing(false);
|
|
168
|
+
// user didn't complete oauth
|
|
169
|
+
if (providersWaitingOauthMessage[provider])
|
|
170
|
+
typedReject('user-cancelled');
|
|
171
|
+
}, 2000);
|
|
172
|
+
});
|
|
173
|
+
}),
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
exports.createWindowOauth2Service = createWindowOauth2Service;
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { __awaiter } from '../../../../_virtual/_tslib.js';
|
|
3
|
+
import { ProviderEnum, SocialOAuthErrorCode } from '@dynamic-labs/types';
|
|
4
|
+
import { logger } from '../../../logger/logger.js';
|
|
5
|
+
import { connectWithAppleId } from '../utils/connectWithAppleId/connectWithAppleId.js';
|
|
6
|
+
import { isSafariBrowser, isIOS } from '../../../isMobile.js';
|
|
7
|
+
|
|
8
|
+
let authWindowInterval;
|
|
9
|
+
const createWindowOauth2Service = () => ({
|
|
10
|
+
getOauthCode: ({ apiProvider, provider, redirectUrl, setIsProcessing, state, oauthLoginUrl, initWebAuth, strategy, }) => new Promise((resolve, _reject) => {
|
|
11
|
+
/**
|
|
12
|
+
* Use AppleID SDK for Apple provider on mobile
|
|
13
|
+
* It should use the strategy setting, but on ios or safari
|
|
14
|
+
* it should use the appleId always as it is the best experience
|
|
15
|
+
*/
|
|
16
|
+
if (provider === ProviderEnum.Apple &&
|
|
17
|
+
(isSafariBrowser() || isIOS() || strategy === 'redirect')) {
|
|
18
|
+
initWebAuth({
|
|
19
|
+
redirectUrl: redirectUrl || window.location.href,
|
|
20
|
+
}).then(() => connectWithAppleId({
|
|
21
|
+
clientId: apiProvider === null || apiProvider === void 0 ? void 0 : apiProvider.clientId,
|
|
22
|
+
oauthLoginUrl,
|
|
23
|
+
state,
|
|
24
|
+
}).catch(_reject));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Use redirect flow on mobile for all providers except Telegram
|
|
29
|
+
*/
|
|
30
|
+
if (strategy === 'redirect' && provider !== ProviderEnum.Telegram) {
|
|
31
|
+
initWebAuth({
|
|
32
|
+
redirectUrl: redirectUrl || window.location.href,
|
|
33
|
+
}).then(() => {
|
|
34
|
+
window.location.assign(oauthLoginUrl);
|
|
35
|
+
});
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
// When we catch this error we assume it follows this type, so we must enforce it
|
|
39
|
+
// here to ensure the assumption is correct
|
|
40
|
+
const typedReject = (params) => _reject(params);
|
|
41
|
+
// Clear any potential pending timeouts and intervals
|
|
42
|
+
clearInterval(authWindowInterval);
|
|
43
|
+
const providersWaitingOauthMessage = {};
|
|
44
|
+
const authWindow = window.open('', '_blank', 'width=500,height=600');
|
|
45
|
+
const clearListeners = () => {
|
|
46
|
+
window.removeEventListener('message', handleWindowMessage);
|
|
47
|
+
providersWaitingOauthMessage[provider] = false;
|
|
48
|
+
};
|
|
49
|
+
const handleWindowMessage = (event) => __awaiter(void 0, void 0, void 0, function* () {
|
|
50
|
+
const message = event.data;
|
|
51
|
+
const expectedOrigin = getExpectedOrigin(apiProvider);
|
|
52
|
+
if (!expectedOrigin) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if ((message === null || message === void 0 ? void 0 : message.type) === 'origin_check' && authWindow) {
|
|
56
|
+
logger.debug('Origin check message received. Sending response now.', {
|
|
57
|
+
data: message,
|
|
58
|
+
expectedOrigin,
|
|
59
|
+
});
|
|
60
|
+
authWindow.postMessage('origin_check_response', expectedOrigin);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const isTelegramCompletedMessage = (message === null || message === void 0 ? void 0 : message.type) === 'telegram_completed';
|
|
64
|
+
const isAuthorizationMessage = (message === null || message === void 0 ? void 0 : message.type) === 'authorization_response';
|
|
65
|
+
if (isAuthorizationMessage || isTelegramCompletedMessage) {
|
|
66
|
+
logger.debug('Message received', { data: message });
|
|
67
|
+
}
|
|
68
|
+
const isExpectedOrigin = event.origin === expectedOrigin;
|
|
69
|
+
const isValidMessage = ((isAuthorizationMessage && (message === null || message === void 0 ? void 0 : message.provider) === provider) ||
|
|
70
|
+
isTelegramCompletedMessage) &&
|
|
71
|
+
isExpectedOrigin;
|
|
72
|
+
// don't process invalid messages for provider
|
|
73
|
+
if (!isValidMessage) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
setIsProcessing(true);
|
|
77
|
+
if (!providersWaitingOauthMessage[provider]) {
|
|
78
|
+
typedReject({
|
|
79
|
+
code: SocialOAuthErrorCode.SESSION_TIMEOUT,
|
|
80
|
+
message: `Connecting ${provider} account session timeout.`,
|
|
81
|
+
});
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
clearListeners();
|
|
85
|
+
if (isTelegramCompletedMessage) {
|
|
86
|
+
handleTelegramCompletionMessage(message, state);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
handleAuthorizationMessage(message, provider, state);
|
|
90
|
+
});
|
|
91
|
+
const getExpectedOrigin = (apiProvider) => {
|
|
92
|
+
if (!(apiProvider === null || apiProvider === void 0 ? void 0 : apiProvider.redirectUrl)) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
const redirectUri = new URL(apiProvider.redirectUrl);
|
|
97
|
+
return redirectUri.origin;
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
logger.error('Failed to parse social provider redirect url', {
|
|
101
|
+
error: e,
|
|
102
|
+
});
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
const handleTelegramCompletionMessage = (message, state) => {
|
|
107
|
+
logger.debug('Telegram completion message received', {
|
|
108
|
+
data: message,
|
|
109
|
+
});
|
|
110
|
+
const { code, state: authState } = message;
|
|
111
|
+
// check that the state we receive from message is the same state we calculated earlier
|
|
112
|
+
// this could be an attack
|
|
113
|
+
if (state !== authState) {
|
|
114
|
+
typedReject({
|
|
115
|
+
code: SocialOAuthErrorCode.OAUTH_ERROR,
|
|
116
|
+
message: 'Failed to connect telegram account: Invalid random state',
|
|
117
|
+
});
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
resolve(code);
|
|
121
|
+
setIsProcessing(false);
|
|
122
|
+
};
|
|
123
|
+
const handleAuthorizationMessage = (message, provider, state) => {
|
|
124
|
+
const { code, error, state: authState } = message;
|
|
125
|
+
if (error && error !== 'undefined') {
|
|
126
|
+
typedReject({
|
|
127
|
+
code: SocialOAuthErrorCode.OAUTH_ERROR,
|
|
128
|
+
message: `Failed to connect ${provider} social account: ${error}`,
|
|
129
|
+
});
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
// check that the state we receive from message is the same state we calculated earlier
|
|
133
|
+
// this could be an attack
|
|
134
|
+
// this state check is used only by providers with an open window opener reference (eg, not twitter)
|
|
135
|
+
if (state !== authState) {
|
|
136
|
+
typedReject({
|
|
137
|
+
code: SocialOAuthErrorCode.OAUTH_ERROR,
|
|
138
|
+
message: `Failed to connect ${provider} social account: Invalid random state`,
|
|
139
|
+
});
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (!code) {
|
|
143
|
+
typedReject({
|
|
144
|
+
code: SocialOAuthErrorCode.NO_AUTH_CODE,
|
|
145
|
+
message: `Failed to connect ${provider} social account: no authorization code`,
|
|
146
|
+
});
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
resolve(code);
|
|
150
|
+
setIsProcessing(false);
|
|
151
|
+
};
|
|
152
|
+
if (!providersWaitingOauthMessage[provider]) {
|
|
153
|
+
window.addEventListener('message', handleWindowMessage);
|
|
154
|
+
providersWaitingOauthMessage[provider] = true;
|
|
155
|
+
}
|
|
156
|
+
// First we store the state in backend
|
|
157
|
+
initWebAuth().then(() => {
|
|
158
|
+
authWindow === null || authWindow === void 0 ? void 0 : authWindow.location.assign(oauthLoginUrl);
|
|
159
|
+
authWindowInterval = setInterval(() => {
|
|
160
|
+
if (!(authWindow === null || authWindow === void 0 ? void 0 : authWindow.closed))
|
|
161
|
+
return;
|
|
162
|
+
clearInterval(authWindowInterval);
|
|
163
|
+
setIsProcessing(false);
|
|
164
|
+
// user didn't complete oauth
|
|
165
|
+
if (providersWaitingOauthMessage[provider])
|
|
166
|
+
typedReject('user-cancelled');
|
|
167
|
+
}, 2000);
|
|
168
|
+
});
|
|
169
|
+
}),
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
export { createWindowOauth2Service };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './createWindowOauth2Service';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var _tslib = require('../../../../../_virtual/_tslib.cjs');
|
|
7
|
+
var loadAppleId = require('../loadAppleId/loadAppleId.cjs');
|
|
8
|
+
|
|
9
|
+
const connectWithAppleId = (_a) => _tslib.__awaiter(void 0, [_a], void 0, function* ({ clientId, oauthLoginUrl, state, }) {
|
|
10
|
+
yield loadAppleId.loadAppleId();
|
|
11
|
+
// Because the AppleID is loaded from a script tag, there is not type for it
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
AppleID.auth.init({
|
|
15
|
+
clientId,
|
|
16
|
+
redirectURI: oauthLoginUrl.searchParams.get('redirect_uri'),
|
|
17
|
+
scope: 'name email',
|
|
18
|
+
state,
|
|
19
|
+
usePopup: false,
|
|
20
|
+
});
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
22
|
+
// @ts-ignore
|
|
23
|
+
AppleID.auth.signIn();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
exports.connectWithAppleId = connectWithAppleId;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { __awaiter } from '../../../../../_virtual/_tslib.js';
|
|
3
|
+
import { loadAppleId } from '../loadAppleId/loadAppleId.js';
|
|
4
|
+
|
|
5
|
+
const connectWithAppleId = (_a) => __awaiter(void 0, [_a], void 0, function* ({ clientId, oauthLoginUrl, state, }) {
|
|
6
|
+
yield loadAppleId();
|
|
7
|
+
// Because the AppleID is loaded from a script tag, there is not type for it
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
AppleID.auth.init({
|
|
11
|
+
clientId,
|
|
12
|
+
redirectURI: oauthLoginUrl.searchParams.get('redirect_uri'),
|
|
13
|
+
scope: 'name email',
|
|
14
|
+
state,
|
|
15
|
+
usePopup: false,
|
|
16
|
+
});
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
AppleID.auth.signIn();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export { connectWithAppleId };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { connectWithAppleId } from './connectWithAppleId';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { loadAppleId } from './loadAppleId';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
const appleIdScriptSrc = 'https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js';
|
|
7
|
+
const loadAppleId = () => new Promise((resolve, reject) => {
|
|
8
|
+
const script = document.querySelector('script[data-apple-sdk]');
|
|
9
|
+
if (script) {
|
|
10
|
+
// Script already exists, attach event listeners
|
|
11
|
+
if (script.hasAttribute('data-loaded')) {
|
|
12
|
+
resolve();
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
script.addEventListener('load', () => resolve());
|
|
16
|
+
script.addEventListener('error', () => reject(new Error('Failed to load Apple SDK')));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
// If the script does not exist, create and add it
|
|
21
|
+
const script = document.createElement('script');
|
|
22
|
+
script.type = 'text/javascript';
|
|
23
|
+
script.src = appleIdScriptSrc;
|
|
24
|
+
script.setAttribute('data-apple-sdk', 'true');
|
|
25
|
+
script.onload = () => {
|
|
26
|
+
script === null || script === void 0 ? void 0 : script.setAttribute('data-loaded', 'true');
|
|
27
|
+
resolve();
|
|
28
|
+
};
|
|
29
|
+
script.onerror = () => reject(new Error('Failed to load Apple SDK'));
|
|
30
|
+
window.document.head.appendChild(script);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
exports.loadAppleId = loadAppleId;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const loadAppleId: () => Promise<void>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
const appleIdScriptSrc = 'https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js';
|
|
3
|
+
const loadAppleId = () => new Promise((resolve, reject) => {
|
|
4
|
+
const script = document.querySelector('script[data-apple-sdk]');
|
|
5
|
+
if (script) {
|
|
6
|
+
// Script already exists, attach event listeners
|
|
7
|
+
if (script.hasAttribute('data-loaded')) {
|
|
8
|
+
resolve();
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
script.addEventListener('load', () => resolve());
|
|
12
|
+
script.addEventListener('error', () => reject(new Error('Failed to load Apple SDK')));
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
// If the script does not exist, create and add it
|
|
17
|
+
const script = document.createElement('script');
|
|
18
|
+
script.type = 'text/javascript';
|
|
19
|
+
script.src = appleIdScriptSrc;
|
|
20
|
+
script.setAttribute('data-apple-sdk', 'true');
|
|
21
|
+
script.onload = () => {
|
|
22
|
+
script === null || script === void 0 ? void 0 : script.setAttribute('data-loaded', 'true');
|
|
23
|
+
resolve();
|
|
24
|
+
};
|
|
25
|
+
script.onerror = () => reject(new Error('Failed to load Apple SDK'));
|
|
26
|
+
window.document.head.appendChild(script);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export { loadAppleId };
|