Skip to content

Commit

Permalink
final requests
Browse files Browse the repository at this point in the history
  • Loading branch information
moe-dev committed Dec 16, 2024
1 parent f121e75 commit b453f76
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 46 deletions.
13 changes: 13 additions & 0 deletions examples/react-components/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,16 @@ $ pnpm run dev
```

This command will run a NextJS app on port 3000. If you navigate to http://localhost:3000 in your browser, the example app using auth components should be ready to use!

### 4/ Using ngrok for OAuth

To enable OAuth flows like Google, Facebook, or Apple on your local environment, you’ll need to use [ngrok](https://ngrok.com) to expose your localhost server to the internet. This is necessary because OIDC providers require a publicly accessible redirect URI during the authentication process.

#### Steps:

1. **Install ngrok**: Follow the [ngrok installation guide](https://ngrok.com/download) to install ngrok on your machine.
2. **Run ngrok**: Start ngrok and point it to port 3000 (the port your app runs on):

```bash
$ ngrok http 3000
```
4 changes: 2 additions & 2 deletions examples/react-components/src/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export default function Dashboard() {
const suborgs = await getVerifiedSuborgs({
filterType: "EMAIL",
filterValue: emailInput,
}); //TODO change to get verified suborgs
});
if (suborgs && suborgs!.organizationIds.length > 0) {
toast.error("Email is already connected to another account");
return;
Expand Down Expand Up @@ -148,7 +148,7 @@ export default function Dashboard() {
const suborgs = await getVerifiedSuborgs({
filterType: "PHONE_NUMBER",
filterValue: phoneInput,
}); //TODO change to get verified suborgs
});
if (suborgs && suborgs!.organizationIds.length > 0) {
toast.error("Phone Number is already connected to another account");
return;
Expand Down
47 changes: 24 additions & 23 deletions packages/sdk-react/src/components/auth/Auth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
import OtpVerification from "./OtpVerification";
import { useTurnkey } from "../../hooks/use-turnkey";
import { getVerifiedSuborgs } from "../../actions/getVerifiedSuborgs";
import { AUTH_ERRORS, passkeyIcon, passkeyIconError } from "./constants";
import { authErrors, passkeyIcon, passkeyIconError } from "./constants";

enum OtpStep {
Email = "otpEmail",
Sms = "otpSms",
enum OtpType {
Email = "OTP_TYPE_EMAIL",
Sms = "OTP_TYPE_SMS",
}

enum FilterType {
Email = "EMAIL",
PhoneNumber = "PHONE_NUMBER",
Expand Down Expand Up @@ -61,10 +62,10 @@ const Auth: React.FC<AuthProps> = ({
const [passkeyCreated, setPasskeyCreated] = useState(false);

const handleResendCode = async () => {
if (step === OtpStep.Email) {
await handleOtpLogin(FilterType.Email, email, "OTP_TYPE_EMAIL");
} else if (step === OtpStep.Sms) {
await handleOtpLogin(FilterType.PhoneNumber, phone, "OTP_TYPE_SMS");
if (step === OtpType.Email) {
await handleOtpLogin(FilterType.Email, email, OtpType.Email);
} else if (step === OtpType.Sms) {
await handleOtpLogin(FilterType.PhoneNumber, phone, OtpType.Sms);
}
};

Expand Down Expand Up @@ -109,13 +110,13 @@ const Auth: React.FC<AuthProps> = ({
!getVerifiedSuborgsResponse ||
!getVerifiedSuborgsResponse.organizationIds
) {
onError(AUTH_ERRORS.SUBORG.FETCH_FAILED);
onError(authErrors.suborg.fetchFailed);
}
suborgId = getVerifiedSuborgsResponse?.organizationIds[0];
} else {
const getSuborgsResponse = await getSuborgs({ filterType, filterValue });
if (!getSuborgsResponse || !getSuborgsResponse.organizationIds) {
onError(AUTH_ERRORS.SUBORG.FETCH_FAILED);
onError(authErrors.suborg.fetchFailed);
}
suborgId = getSuborgsResponse?.organizationIds[0];
}
Expand All @@ -128,7 +129,7 @@ const Auth: React.FC<AuthProps> = ({

const createSuborgResponse = await createSuborg(createSuborgData);
if (!createSuborgResponse || !createSuborgResponse.subOrganizationId) {
onError(AUTH_ERRORS.SUBORG.CREATE_FAILED);
onError(authErrors.suborg.createFailed);
}
suborgId = createSuborgResponse?.subOrganizationId!;
}
Expand Down Expand Up @@ -176,10 +177,10 @@ const Auth: React.FC<AuthProps> = ({
if (response?.subOrganizationId) {
setPasskeyCreated(true);
} else {
AUTH_ERRORS.PASSKEY.CREATE_FAILED;
authErrors.passkey.createFailed;
}
} else {
AUTH_ERRORS.PASSKEY.CREATE_FAILED;
authErrors.passkey.createFailed;
}
}

Expand All @@ -190,10 +191,10 @@ const Auth: React.FC<AuthProps> = ({
if (sessionResponse?.credentialBundle) {
await handleAuthSuccess(sessionResponse.credentialBundle);
} else {
setPasskeySignupError(AUTH_ERRORS.PASSKEY.LOGIN_FAILED);
setPasskeySignupError(authErrors.passkey.loginFailed);
}
} catch {
setPasskeySignupError(AUTH_ERRORS.PASSKEY.TIMEOUT_OR_NOT_ALLOWED);
setPasskeySignupError(authErrors.passkey.timeoutOrNotAllowed);
}
};

Expand All @@ -207,10 +208,10 @@ const Auth: React.FC<AuthProps> = ({
if (sessionResponse?.credentialBundle) {
await handleAuthSuccess(sessionResponse.credentialBundle);
} else {
AUTH_ERRORS.PASSKEY.LOGIN_FAILED;
authErrors.passkey.loginFailed;
}
} catch (error) {
onError(AUTH_ERRORS.PASSKEY.LOGIN_FAILED);
onError(authErrors.passkey.loginFailed);
}
};

Expand All @@ -229,9 +230,9 @@ const Auth: React.FC<AuthProps> = ({
if (initAuthResponse && initAuthResponse.otpId) {
setSuborgId(suborgId);
setOtpId(initAuthResponse?.otpId!);
setStep(type === FilterType.Email ? OtpStep.Email : OtpStep.Sms);
setStep(otpType);
} else {
onError(AUTH_ERRORS.OTP.SEND_FAILED);
onError(authErrors.otp.sendFailed);
}
};

Expand All @@ -252,7 +253,7 @@ const Auth: React.FC<AuthProps> = ({
if (oauthResponse && oauthResponse.credentialBundle) {
await handleAuthSuccess(oauthResponse!.credentialBundle);
} else {
onError(AUTH_ERRORS.OAUTH.LOGIN_FAILED);
onError(authErrors.oauth.loginFailed);
}
};

Expand Down Expand Up @@ -367,7 +368,7 @@ const Auth: React.FC<AuthProps> = ({
className={styles.authButton}
type="button"
onClick={() =>
handleOtpLogin(FilterType.Email, email, "OTP_TYPE_EMAIL")
handleOtpLogin(FilterType.Email, email, OtpType.Email)
}
disabled={!isValidEmail(email)}
>
Expand Down Expand Up @@ -405,7 +406,7 @@ const Auth: React.FC<AuthProps> = ({
className={styles.authButton}
type="button"
onClick={() =>
handleOtpLogin(FilterType.PhoneNumber, phone, "OTP_TYPE_SMS")
handleOtpLogin(FilterType.PhoneNumber, phone, OtpType.Sms)
}
disabled={!isValidPhone(phone)}
>
Expand Down Expand Up @@ -543,7 +544,7 @@ const Auth: React.FC<AuthProps> = ({
{otpId && (
<OtpVerification
type={step}
contact={step === OtpStep.Email ? email : phone}
contact={step === OtpType.Email ? email : phone}
suborgId={suborgId}
otpId={otpId!}
authIframeClient={authIframeClient!}
Expand Down
4 changes: 2 additions & 2 deletions packages/sdk-react/src/components/auth/OtpVerification.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import EmailIcon from "@mui/icons-material/Email";
import SmsIcon from "@mui/icons-material/Sms";
import { CircularProgress } from "@mui/material";

const resendTimer = 15000;
const resendTimerMs = 15000;
interface OtpVerificationProps {
type: string;
contact: string;
Expand Down Expand Up @@ -69,7 +69,7 @@ const OtpVerification: React.FC<OtpVerificationProps> = ({

setTimeout(() => {
setResendText("Resend code");
}, resendTimer);
}, resendTimerMs);
} catch {
setOtpError("Failed to resend the code. Please try again.");
}
Expand Down
34 changes: 15 additions & 19 deletions packages/sdk-react/src/components/auth/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,32 @@ export const FACEBOOK_GRAPH_URL =
"https://graph.facebook.com/v11.0/oauth/access_token";
export const popupWidth = 500;
export const popupHeight = 600;
export const AUTH_ERRORS = {

export const authErrors = {
// Passkey-related errors
PASSKEY: {
CREATE_FAILED: "Passkey not created. Please try again.",
LOGIN_FAILED: "Failed to login with passkey. Please try again.",
TIMEOUT_OR_NOT_ALLOWED:
passkey: {
createFailed: "Passkey not created. Please try again.",
loginFailed: "Failed to login with passkey. Please try again.",
timeoutOrNotAllowed:
"The operation either timed out or was not allowed. Please try again.",
},

// OTP-related errors
OTP: {
SEND_FAILED: "Failed to send OTP",
INVALID_EMAIL: "Invalid email address.",
INVALID_PHONE: "Invalid phone number.",
otp: {
sendFailed: "Failed to send OTP",
invalidEmail: "Invalid email address.",
invalidPhone: "Invalid phone number.",
},

// OAuth-related errors
OAUTH: {
LOGIN_FAILED: "Failed to login with OIDC provider",
oauth: {
loginFailed: "Failed to login with OIDC provider",
},

// Sub-organization-related errors
SUBORG: {
FETCH_FAILED: "Failed to fetch account",
CREATE_FAILED: "Failed to create account",
},

// General errors
GENERAL: {
UNEXPECTED: "An unexpected error occurred. Please try again.",
suborg: {
fetchFailed: "Failed to fetch account",
createFailed: "Failed to create account.",
},
};

Expand Down

0 comments on commit b453f76

Please sign in to comment.