> Portal Navigation: > > - Append `.md` to any URL under `https://dev.wix.com/docs/` to get its markdown version. > - Pages are either content pages (article or reference text) or menu pages (a list of links to child pages). > - To get a menu page, truncate any URL to a parent path and append `.md` (e.g. `https://dev.wix.com/docs/sdk.md`, `https://dev.wix.com/docs/sdk/core-modules.md`). > - Top-level index of all portals: https://dev.wix.com/docs/llms.txt > - Full concatenated docs: https://dev.wix.com/docs/llms-full.txt ## Resource: Custom Login Using the JS SDK ## Article: Handle Members with Custom Login ## Article Link: https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/members/custom-login-page/custom-login/custom-login-using-the-js-sdk.md ## Article Content: # Handle Members with a Custom Login Page Using the JS SDK > **Note:** This article is only relevant for [self-managed headless projects](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/about-self-managed-headless.md). This article explains how to implement a [custom login page](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/members/custom-login-page/about-custom-login-pages.md) using the JavaScript SDK. You'll learn how to: - Set up a Wix client for authentication. - Check if a visitor is already logged in. - Sign up and log in members. - Exchange session tokens for access and refresh tokens. - Handle failed authentication states. - Refresh access tokens. - Log out members. ## Step 1 | Set up a Wix client To authenticate and interact with Wix APIs, create a [Wix client](https://dev.wix.com/docs/sdk/core-modules/sdk/wix-client.md) in your code. Install and import the [Members API](https://dev.wix.com/docs/api-reference/crm/members-contacts/members/member-management/members/introduction.md) to create and manage a site's members. You can also import other APIs as needed and pass to your client. ```js import { createClient, OAuthStrategy } from '@wix/sdk'; import { members } from '@wix/members'; const myWixClient = createClient({ modules: { members }, auth: OAuthStrategy({ clientId: '', }) }); ``` Replace `` with your OAuth app's **Client ID** from your [Headless Settings](https://www.wix.com/my-account/site-selector/?buttonText=Select%20Site&title=Select%20a%20Site&autoSelectOnSingleSite=true&actionUrl=https:%2F%2Fwww.wix.com%2Fdashboard%2F%7B%7BmetaSiteId%7D%7D%2Foauth-apps-settings). ## Step 2 | Check if the visitor is already logged in Before showing a login form, check if the current visitor is already logged in: ```js const isLoggedIn = myWixClient.auth.loggedIn(); if (isLoggedIn) { const { member } = await myWixClient.members.getCurrentMember(); console.log('Logged in as:', member.email); } else { showLoginForm(); } ``` If logged in, you can immediately make authenticated API calls. Otherwise, send them to your sign-up or login form. ## Step 3 | Sign up and log in members Create custom forms in your app with fields for email and password. You can design these forms to match your branding exactly. Your page should be able to: * Sign up a new member * Log in an existing member
**Tip:** You can add [reCAPTCHA protection](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/members/custom-login-page/re-captcha/implement-re-captcha-using-the-js-sdk.md) to your custom login flows to help prevent fraud and abuse. Make sure to also [enable reCAPTCHA](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/members/re-captcha/enable-re-captcha-for-member-login.md) in your project settings.
### Sign up a new member To sign up a new member, use the [`register()`](https://dev.wix.com/docs/sdk/core-modules/sdk/oauth-strategy.md) method with the email and password provided by the visitor: ```js let response = await myWixClient.auth.register({ email: "", password: "", }); ``` If `response.loginState` is `SUCCESS`, [exchange the session token for access and refresh tokens](#step-4--exchange-the-session-token-for-access-and-refresh-tokens). Otherwise, [handle failed authentication states](#step-5--handle-failed-authentication-states). ### Log in an existing member To log in an existing member, use the [`login()`](https://dev.wix.com/docs/sdk/core-modules/sdk/oauth-strategy.md) method with the email and password provided by the visitor: ```js let response = await myWixClient.auth.login({ email: "", password: "", }); ``` If `response.loginState` is `SUCCESS`, [exchange the session token for access and refresh tokens](#step-4--exchange-the-session-token-for-access-and-refresh-tokens). Otherwise, [handle failed authentication states](#step-5--handle-failed-authentication-states). ## Step 4 | Exchange the session token for access and refresh tokens When authentication is successful, you need to exchange the session token for access and refresh tokens. This process is the same whether you're signing up a new member or logging in an existing member. To exchange the session token for access and refresh tokens, call [`getMemberTokensForDirectLogin()`](https://dev.wix.com/docs/sdk/core-modules/sdk/oauth-strategy.md), and then set the returned member tokens on your client: ```js if (response.loginState === 'SUCCESS') { const tokens = await myWixClient.auth.getMemberTokensForDirectLogin(response.data.sessionToken); myWixClient.auth.setTokens(tokens); } ```
**Tip:** After setting tokens, you can use `myWixClient.members.getCurrentMember()` to fetch the member's info.
## Step 5 | Handle failed authentication states When a sign-up or login attempt fails, the `login()` and `register()` methods return an object with a `loginState` property. Your code should handle each possible state to provide a smooth user experience. The possible values include: - `SUCCESS`: Authentication was successful. - `FAILURE`: Authentication unsuccessful due to one of the following reasons, as indicated by the `errorCode`: - `invalidEmail`: The email address provided is invalid. Your code should present an error. - `invalidPassword`: The password provided is invalid. Your code should present an error. - `emailAlreadyExists`: The visitor attempted to sign up as a new member using an email address belonging to an existing member. Your code should present an error. - `resetPassword`: The member needs to reset their password. Your code needs to [send a password reset email](#send-a-password-reset-email). - `EMAIL_VERIFICATION_REQUIRED`: Authentication requires email verification. Your code needs to [process email verification](#process-email-verification). - `OWNER_APPROVAL_REQUIRED`: The site owner needs to approve registration for the new member. Your code should present a notice to inform the visitor that their membership is pending. Once their membership is approved, the member can log in. ### Send a password reset email Call the [`sendPasswordResetEmail()`](https://dev.wix.com/docs/sdk/core-modules/sdk/oauth-strategy.md) method to send a password reset email to a member. The method takes the member's email address and a URL to send the member to after they successfully change their password. ```js await myWixClient.auth.sendPasswordResetEmail( email, redirectUri ); ``` The `redirectUri` must be an [allowed authorization redirect URI](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/members/add-allowed-authorization-redirect-uris.md). When the member clicks the reset link in their email, they're taken to a Wix-managed password reset page. After successfully setting a new password, Wix redirects them to your specified URL. For example, the following code sends a password reset email to `john_doe@email.com`, and once the member resets their password on the Wix-managed page, Wix redirects the member back to your page at `http://www.my-site.com/password_changed`. ```js await myWixClient.auth.sendPasswordResetEmail( "john_doe@email.com", "http://www.my-site.com/password_changed", ); ``` ### Process email verification If the `loginState` is `EMAIL_VERIFICATION_REQUIRED`, Wix sends an email with a verification code to the member. You need to create a form or prompt to collect this verification code from the member, and then use the [`processVerification()`](https://dev.wix.com/docs/sdk/core-modules/sdk/oauth-strategy.md) method to complete the verification: ```js const response = await myWixClient.auth.processVerification({ verificationCode: verificationCode }); ``` If `response.loginState` is `SUCCESS`, [exchange the session token for access and refresh tokens](#step-4--exchange-the-session-token-for-access-and-refresh-tokens). ## Step 6 | Refresh access tokens Access tokens expire after a short time for security reasons. When this happens, you can use a refresh token to request a new access token without asking the member to log in again. Your API layer should handle this automatically. Set up your logic to detect when an access token has expired, use the refresh token to get a new one, and then retry the original request. ```js const storedRefreshToken = JSON.parse(Cookies.get(WIX_REFRESH_TOKEN) || 'null'); const myWixClient = createClient({ modules: { members }, auth: OAuthStrategy({ clientId: '', tokens: { refreshToken: storedRefreshToken, accessToken: { value: '', expiresAt: 0 } } }) }); try { const newTokens = await myWixClient.auth.refreshTokens(storedRefreshToken); myWixClient.auth.setTokens(newTokens); Cookies.set(WIX_REFRESH_TOKEN, JSON.stringify(newTokens.refreshToken), { expires: 14 }); } catch (error) { window.location.href = '/login'; } ```
**Tip:** Don't expose refresh tokens to the browser unnecessarily. For best security, handle token refresh on the server when possible.
## Logging out a member To log a member out: 1. Get the logout URL from your Wix client: ```js const { logoutUrl } = await myWixClient.auth.logout(window.location.href); ``` 2. Redirect the member to the logout URL: ```js window.location.href = logoutUrl; ``` This logs the member out and redirects them back to your app. ## Troubleshooting If you encounter issues with custom login, make sure that: - You're using the correct client ID from your [Headless Settings](https://www.wix.com/my-account/site-selector/?buttonText=Select%20Site&title=Select%20a%20Site&autoSelectOnSingleSite=true&actionUrl=https:%2F%2Fwww.wix.com%2Fdashboard%2F%7B%7BmetaSiteId%7D%7D%2Foauth-apps-settings). - The `redirectUri` parameter in `sendPasswordResetEmail()` matches one of your [allowed authorization redirect URIs](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/members/add-allowed-authorization-redirect-uris.md). - If you're having token-related errors during testing, clear browser cookies and try again. - You're using a single shared client instance throughout your app (not creating new instances in components).