Skip to content

Commit d3c8302

Browse files
committed
Auth Refactor (#3779)
### TL;DR Improved the in-app wallet sign-in speed by refactoring OAuth path handling to make it more generic and efficient. ### What changed? - Standardized the OAuth path handling to make it more generic and reusable across multiple providers. - Updated `getLoginPath` to `getSocialAuthLoginPath` for OAuth providers like Google, Facebook, Apple, and Discord. - Improved login speed and reduced redundancy by streamlining the OAuth path logic. - Removed outdated and redundant code related to individual OAuth provider handling. ### How to test? 1. Test the sign-in process using various OAuth providers such as Google, Facebook, Apple, and Discord. 2. Ensure the redirection and sign-in speed are improved. 3. Verify that the in-app wallet sign-in works seamlessly without any errors. ### Why make this change? The changes were necessary to optimize and standardize the OAuth sign-in process, improving the overall user experience. The previous implementation had redundant code for individual providers, which was refactored to be more efficient and easier to maintain. --- <!-- start pr-codex --> --- ## PR-Codex overview This PR improves in-app wallet sign-in speed by updating authentication strategies and paths. ### Detailed summary - Updated OAuth authentication strategy to `SocialAuthOption` - Improved login path retrieval for social authentication providers - Refactored Discord-specific authentication to generic OAuth approach > The following files were skipped due to too many changes: `packages/thirdweb/src/wallets/in-app/native/auth/native-auth.ts` > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent a9a3f0f commit d3c8302

File tree

11 files changed

+95
-135
lines changed

11 files changed

+95
-135
lines changed

.changeset/famous-bats-talk.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
Improved in-app wallet sign-in speed

apps/dashboard/package.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,16 @@
166166
"tw-components",
167167
"contract-ui"
168168
],
169-
"exclude": ["node_modules", "types", "tw-components"],
169+
"exclude": [
170+
"node_modules",
171+
"types",
172+
"tw-components"
173+
],
170174
"entrypoints": []
171175
},
172-
"browserslist": ["defaults", "unreleased versions", "not UCAndroid > 0"]
176+
"browserslist": [
177+
"defaults",
178+
"unreleased versions",
179+
"not UCAndroid > 0"
180+
]
173181
}

packages/thirdweb/src/react/web/wallets/shared/openOauthSignInWindow.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ThirdwebClient } from "../../../../client/client.js";
2-
import { getDiscordLoginPath } from "../../../../wallets/in-app/core/authentication/getLoginPath.js";
2+
import { getSocialAuthLoginPath } from "../../../../wallets/in-app/core/authentication/getLoginPath.js";
33
import type { InAppWalletSocialAuth } from "../../../../wallets/in-app/core/wallet/types.js";
44
import type { Ecosystem } from "../../../../wallets/in-app/web/types.js";
55
import type { Theme } from "../../../core/design-system/index.js";
@@ -30,8 +30,11 @@ function getOauthLoginPath(
3030
ecosystem?: Ecosystem,
3131
) {
3232
switch (authOption) {
33+
case "apple":
34+
case "facebook":
35+
case "google":
3336
case "discord":
34-
return getDiscordLoginPath(client, ecosystem);
37+
return getSocialAuthLoginPath(authOption, client, ecosystem);
3538
default:
3639
return "";
3740
}

packages/thirdweb/src/wallets/in-app/core/authentication/getLoginPath.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import type { ThirdwebClient } from "../../../../client/client.js";
22
import { getThirdwebBaseUrl } from "../../../../utils/domains.js";
3+
import type { SocialAuthOption } from "../../../../wallets/types.js";
34
import type { Ecosystem } from "../../web/types.js";
45

5-
// TODO: make this generic for all auth providers
6-
export const getDiscordLoginPath = (
6+
export const getSocialAuthLoginPath = (
7+
authOption: SocialAuthOption,
78
client: ThirdwebClient,
89
ecosystem?: Ecosystem,
910
) => {
10-
const baseUrl = `${getThirdwebBaseUrl("inAppWallet")}/api/2024-05-05/login/discord?clientId=${client.clientId}`;
11+
const baseUrl = `${getThirdwebBaseUrl("inAppWallet")}/api/2024-05-05/login/${authOption}?clientId=${client.clientId}`;
1112
if (ecosystem?.partnerId) {
1213
return `${baseUrl}&ecosystemId=${ecosystem.id}&ecosystemPartnerId=${ecosystem.partnerId}`;
1314
}

packages/thirdweb/src/wallets/in-app/core/authentication/type.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export enum AuthProvider {
6565
}
6666

6767
export type OauthOption = {
68-
provider: AuthProvider;
68+
strategy: SocialAuthOption;
6969
redirectUrl: string;
7070
};
7171

@@ -207,13 +207,3 @@ export type GetUser =
207207
export type GetAuthenticatedUserParams = {
208208
client: ThirdwebClient;
209209
};
210-
211-
export const oauthStrategyToAuthProvider: Record<
212-
SocialAuthOption,
213-
AuthProvider
214-
> = {
215-
google: AuthProvider.GOOGLE,
216-
facebook: AuthProvider.FACEBOOK,
217-
apple: AuthProvider.APPLE,
218-
discord: AuthProvider.DISCORD,
219-
};

packages/thirdweb/src/wallets/in-app/native/auth/native-auth.ts

Lines changed: 10 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { CognitoUser } from "amazon-cognito-identity-js";
33
import { Auth } from "aws-amplify";
44
import * as WebBrowser from "expo-web-browser";
55
import type { ThirdwebClient } from "../../../../client/client.js";
6-
import { getDiscordLoginPath } from "../../core/authentication/getLoginPath.js";
6+
import { getSocialAuthLoginPath } from "../../core/authentication/getLoginPath.js";
77
import {
88
AuthProvider,
99
type AuthStoredTokenWithCookieReturnType,
@@ -30,10 +30,8 @@ import {
3030
preAuth,
3131
} from "../helpers/auth/middleware.js";
3232
import {
33-
DOMAIN_URL_2023,
3433
ROUTE_AUTH_ENDPOINT_CALLBACK,
3534
ROUTE_AUTH_JWT_CALLBACK,
36-
ROUTE_HEADLESS_OAUTH_LOGIN,
3735
} from "../helpers/constants.js";
3836
import { createErrorMessage } from "../helpers/errors.js";
3937
import { isDeviceSharePresentForUser } from "../helpers/storage/local.js";
@@ -207,48 +205,14 @@ export async function validateEmailOTP(options: {
207205
}
208206

209207
export async function socialLogin(
210-
oauthOptions: OauthOption,
208+
auth: OauthOption,
211209
client: ThirdwebClient,
212210
): Promise<AuthStoredTokenWithCookieReturnType> {
213-
const encodedProvider = encodeURIComponent(oauthOptions.provider);
214-
const headlessLoginLinkWithParams = `${ROUTE_HEADLESS_OAUTH_LOGIN}?authProvider=${encodedProvider}&baseUrl=${encodeURIComponent(
215-
DOMAIN_URL_2023,
216-
)}&platform=${encodeURIComponent("mobile")}`;
211+
const loginUrl = `${getSocialAuthLoginPath(auth.strategy, client)}&redirectUrl=${encodeURIComponent(auth.redirectUrl)}`;
217212

218-
const resp = await fetch(headlessLoginLinkWithParams, {
219-
headers: {
220-
...getSessionHeaders(),
221-
},
222-
});
223-
224-
if (!resp.ok) {
225-
const error = await resp.json();
226-
throw new Error(`Error getting headless sign in link: ${error.message}`);
227-
}
228-
229-
const json = await resp.json();
230-
231-
const { platformLoginLink } = json;
232-
233-
// Temporary fork for discord until we migrate all methods to the new auth flow
234-
const loginUrl = (() => {
235-
if (oauthOptions.provider === AuthProvider.DISCORD) {
236-
return `${getDiscordLoginPath(client)}&redirectUrl=${encodeURIComponent(
237-
oauthOptions.redirectUrl,
238-
)}`;
239-
} else {
240-
return `${platformLoginLink}?developerClientId=${encodeURIComponent(
241-
client.clientId,
242-
)}&platform=${encodeURIComponent("mobile")}&redirectUrl=${encodeURIComponent(
243-
oauthOptions.redirectUrl,
244-
)}&authOption=${encodedProvider}`;
245-
}
246-
})();
247-
248-
// TODO platform specific code should be extracted out
249213
const result = await WebBrowser.openAuthSessionAsync(
250214
loginUrl,
251-
oauthOptions.redirectUrl,
215+
auth.redirectUrl,
252216
{
253217
preferEphemeralSession: false,
254218
showTitle: false,
@@ -262,19 +226,18 @@ export async function socialLogin(
262226
}
263227

264228
if (result.type !== "success") {
265-
throw new Error(`Can't sign in with ${oauthOptions.provider}: ${result}`);
229+
throw new Error(`Can't sign in with ${auth.strategy}: ${result}`);
266230
}
267231

268-
const decodedUrl = decodeURIComponent(result.url);
232+
const resultURL = new URL(result.url);
233+
const authResult = resultURL.searchParams.get("authResult");
234+
const error = resultURL.searchParams.get("error");
269235

270-
const parts = decodedUrl.split("?authResult=");
271-
if (parts.length < 2) {
272-
// assume error
273-
const error = decodedUrl.split("?error=")?.[1];
236+
// assume error
237+
if (error) {
274238
throw new Error(`Something went wrong: ${error}`);
275239
}
276240

277-
const authResult = parts[1];
278241
if (!authResult) {
279242
throw new Error("No auth result found");
280243
}

packages/thirdweb/src/wallets/in-app/native/helpers/auth/middleware.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@ import {
1111
setWallerUserDetails,
1212
} from "../storage/local.js";
1313
import { setUpNewUserWallet } from "../wallet/creation.js";
14-
import {
15-
getCognitoRecoveryPasswordV1,
16-
getCognitoRecoveryPasswordV2,
17-
} from "../wallet/recoveryCode.js";
14+
import { getCognitoRecoveryPasswordV2 } from "../wallet/recoveryCode.js";
1815
import { setUpShareForNewDevice } from "../wallet/retrieval.js";
1916

2017
export async function preAuth(args: {
@@ -154,11 +151,7 @@ async function getRecoveryCode(
154151
return recoveryCode;
155152
} else {
156153
try {
157-
// temporary fork for discord until we migrate all methods to the new auth flow
158-
const code = await (storedToken.authProvider === AuthProvider.DISCORD
159-
? getCognitoRecoveryPasswordV2(client)
160-
: getCognitoRecoveryPasswordV1(client));
161-
return code;
154+
return await getCognitoRecoveryPasswordV2(client);
162155
} catch (e) {
163156
throw new Error("Something went wrong getting cognito recovery code");
164157
}

packages/thirdweb/src/wallets/in-app/native/native-connector.ts

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
type PreAuthArgsType,
1010
type SendEmailOtpReturnType,
1111
UserWalletStatus,
12-
oauthStrategyToAuthProvider,
1312
} from "../core/authentication/type.js";
1413
import type { InAppConnector } from "../core/interfaces/connector.js";
1514
import {
@@ -114,9 +113,8 @@ export class InAppNativeConnector implements InAppConnector {
114113
const ExpoLinking = require("expo-linking");
115114
const redirectUrl =
116115
params.redirectUrl || (ExpoLinking.createURL("") as string);
117-
const oauthProvider = oauthStrategyToAuthProvider[strategy];
118116
return this.socialLogin({
119-
provider: oauthProvider,
117+
strategy,
120118
redirectUrl,
121119
});
122120
}
@@ -181,14 +179,9 @@ export class InAppNativeConnector implements InAppConnector {
181179
return deleteActiveAccount({ client: this.options.client });
182180
}
183181

184-
private async socialLogin(
185-
oauthOption: OauthOption,
186-
): Promise<AuthLoginReturnType> {
182+
private async socialLogin(auth: OauthOption): Promise<AuthLoginReturnType> {
187183
try {
188-
const { storedToken } = await socialLogin(
189-
oauthOption,
190-
this.options.client,
191-
);
184+
const { storedToken } = await socialLogin(auth, this.options.client);
192185
const account = await this.getAccount();
193186
return {
194187
user: {
@@ -199,17 +192,11 @@ export class InAppNativeConnector implements InAppConnector {
199192
},
200193
};
201194
} catch (error) {
202-
console.error(
203-
`Error while signing in with: ${oauthOption.provider}. ${error}`,
204-
);
195+
console.error(`Error while signing in with: ${auth}. ${error}`);
205196
if (error instanceof Error) {
206-
throw new Error(
207-
`Error signing in with ${oauthOption.provider}: ${error.message}`,
208-
);
197+
throw new Error(`Error signing in with ${auth}: ${error.message}`);
209198
}
210-
throw new Error(
211-
`An unknown error occurred signing in with ${oauthOption.provider}`,
212-
);
199+
throw new Error(`An unknown error occurred signing in with ${auth}`);
213200
}
214201
}
215202

packages/thirdweb/src/wallets/in-app/web/lib/auth/discord.ts renamed to packages/thirdweb/src/wallets/in-app/web/lib/auth/oauth.ts

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,62 @@
11
import type { ThirdwebClient } from "../../../../../client/client.js";
22
import { getThirdwebBaseUrl } from "../../../../../utils/domains.js";
33
import type { AuthStoredTokenWithCookieReturnType } from "../../../../../wallets/in-app/core/authentication/type.js";
4-
import { getDiscordLoginPath } from "../../../core/authentication/getLoginPath.js";
4+
import type { SocialAuthOption } from "../../../../../wallets/types.js";
55
import type { Ecosystem } from "../../types.js";
66
import { DEFAULT_POP_UP_SIZE } from "./constants.js";
7-
import { closeWindow } from "./utils.js";
87

9-
export async function loginWithDiscord(options: {
8+
const closeWindow = ({
9+
isWindowOpenedByFn,
10+
win,
11+
closeOpenedWindow,
12+
}: {
13+
win?: Window | null;
14+
isWindowOpenedByFn: boolean;
15+
closeOpenedWindow?: (openedWindow: Window) => void;
16+
}) => {
17+
if (isWindowOpenedByFn) {
18+
win?.close();
19+
} else {
20+
if (win && closeOpenedWindow) {
21+
closeOpenedWindow(win);
22+
} else if (win) {
23+
win.close();
24+
}
25+
}
26+
};
27+
28+
export const getSocialAuthLoginPath = (
29+
authOption: SocialAuthOption,
30+
client: ThirdwebClient,
31+
ecosystem?: Ecosystem,
32+
) => {
33+
const baseUrl = `${getThirdwebBaseUrl("inAppWallet")}/api/2024-05-05/login/${authOption}?clientId=${client.clientId}`;
34+
if (ecosystem?.partnerId) {
35+
return `${baseUrl}&ecosystemId=${ecosystem.id}&ecosystemPartnerId=${ecosystem.partnerId}`;
36+
}
37+
if (ecosystem) {
38+
return `${baseUrl}&ecosystemId=${ecosystem.id}`;
39+
}
40+
return baseUrl;
41+
};
42+
43+
export const loginWithOauth = async (options: {
44+
authOption: SocialAuthOption;
1045
client: ThirdwebClient;
1146
ecosystem?: Ecosystem;
1247
openedWindow?: Window | null | undefined;
1348
closeOpenedWindow?: ((openedWindow: Window) => void) | undefined;
14-
}): Promise<AuthStoredTokenWithCookieReturnType> {
49+
}): Promise<AuthStoredTokenWithCookieReturnType> => {
1550
let win = options.openedWindow;
1651
let isWindowOpenedByFn = false;
1752
if (!win) {
1853
win = window.open(
19-
getDiscordLoginPath(options.client, options.ecosystem),
20-
"Login to discord",
54+
getSocialAuthLoginPath(
55+
options.authOption,
56+
options.client,
57+
options.ecosystem,
58+
),
59+
`Login to ${options.authOption}`,
2160
DEFAULT_POP_UP_SIZE,
2261
);
2362
isWindowOpenedByFn = true;
@@ -30,9 +69,6 @@ export async function loginWithDiscord(options: {
3069
(resolve, reject) => {
3170
// detect when the user closes the login window
3271
const pollTimer = window.setInterval(async () => {
33-
if (!win) {
34-
return;
35-
}
3672
if (win.closed) {
3773
clearInterval(pollTimer);
3874
window.removeEventListener("message", messageListener);
@@ -89,4 +125,4 @@ export async function loginWithDiscord(options: {
89125
},
90126
);
91127
return result;
92-
}
128+
};

packages/thirdweb/src/wallets/in-app/web/lib/auth/utils.ts

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)