> 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 REST API ## 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-rest-api.md ## Article Content: # Handle Members with a Custom Login Page Using the REST API > **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 REST API. ## Step 1 | Create a frontend login component Create a frontend login/sign-up component for the site or app you are building on the platform of your choice. Ensure that your UI prompts visitors for an email address and password. ## Step 2 | Sign up a new member To register a new member using an email address and password the site visitor provides, call [Register V 2](https://dev.wix.com/docs/api-reference/business-management/headless/authentication/register-v-2.md), specifying the following parameters: - **`loginId.email`**: Registering member's email address. - **`password`**: Registering member's password. - **`[profile]`**: Registering member's [profile](#profile). Include an **`authorization`** header with the temporary visitor access token. Learn how to [generate a temporary visitor access token](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/visitors/handle-visitors-using-the-rest-api.md). ```curl curl --location 'https://www.wixapis.com/_api/iam/authentication/v2/register' \ --header 'authorization: ' \ --header 'content-type: application/json' \ --data '{ "loginId":{ "email": "john@doe.com" }, "password": "verySecurePassword", "profile": { "firstName": "John", "lastName": "Doe", "nickname": "Johnny Boy" } }' ``` > You can also 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-rest-api.md) to the registration process. 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. Register V 2 initiates a new member registration and returns a response containing the state of the registration operation and associated tokens. Its response contains the following: - **`state`**: The current [state](#step-4--handle-login-states) of the registration process. Use this `state` value to determine the next step in the registration process. - **`sessionToken`**: If the `state` value is `'SUCCESS'`, use the `sessionToken` to [get the site members tokens](#generate-member-tokens). - **`stateToken`**: If the `state` value is not `'SUCCESS'`. You will need to use the `stateToken` to continue the registration process. ```json { "state": "SUCCESS", "sessionToken": "MST.eyJraWQiOiJ3cTFCcFlDbyIsImFsZyI6IlJTMjU2In0...", "identity": { "id": "12432ed2-ef8b-6bf3-8f9n-94f3c4d0ef85", "identifiers": [ { "email": "john@doe.com" } ], "revision": "1", "createdDate": "2023-07-19T11:14:08Z", "updatedDate": "2023-07-19T11:14:08Z", "connections": [ { "authenticatorConnection": { "authenticatorConnectionId": "31ddd8fc-ea95-43ac-95c5-902497125b90", "reEnrollmentRequired": false } } ], "identityProfile": { "nickname": "Johnny Boy", "emails": [], "phones": [], "labels": [], "privacyStatus": "UNDEFINED", "customFields": [] }, "metadata": { "tags": [] }, "email": { "address": "john@doe.com", "isVerified": false }, "status": { "name": "ACTIVE", "reasons": [] } } } ``` ## Step 3 | Log in a member To log in an existing member using an email address and password the site visitor provides, call [Login V 2](https://dev.wix.com/docs/api-reference/business-management/headless/authentication/login-v-2.md), specifying the following parameters: - **`loginId.email`**: Member's email address. - **`password`**: Member's password. Include an **`authorization`** header with the temporary visitor access token generated during the prerequisites. ```curl curl --location 'https://www.wixapis.com/_api/iam/authentication/v2/login' \ --header 'authorization: ' \ --header 'content-type: application/json' \ --data '{ "loginId":{ "email": "john@doe.com" }, "password": "verySecurePassword" }' ``` > You can also 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-rest-api.md) to the login process. 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. Login V 2 initiates a member login and returns a response containing the state of the login operation and associated tokens. Its response contains the following: - **`state`**: The current [state](#step-4--handle-login-states) of the login process. Use this `state` value to determine the next step in the login process. - **`sessionToken`**: If the `state` value is `'SUCCESS'`, use the `sessionToken` to [get the site members tokens](#generate-member-tokens). - **`stateToken`**: If the `state` value is not `'SUCCESS'`. You will need to use the `stateToken` to continue the login process. ```json { "state": "SUCCESS", "sessionToken": "MST.eyJraWQiOiJ3cTFCcFlDbyIsImFsZyI6IlJTMjU2In0...", "identity": { "id": "12432ed2-ef8b-6bf3-8f9n-94f3c4d0ef85", "identifiers": [ { "email": "john@doe.com" } ], "revision": "1", "createdDate": "2023-07-19T11:14:08Z", "updatedDate": "2023-07-19T11:14:08Z", "connections": [ { "authenticatorConnection": { "authenticatorConnectionId": "31ddd8fc-ea95-43ac-95c5-902497125b90", "reEnrollmentRequired": false } } ], "identityProfile": { "nickname": "Johnny Boy", "emails": [], "phones": [], "labels": [], "privacyStatus": "UNDEFINED", "customFields": [] }, "metadata": { "tags": [] }, "email": { "address": "john@doe.com", "isVerified": false }, "status": { "name": "ACTIVE", "reasons": [] } } } ``` ## Step 4 | Handle login states Both Login V 2 and Register V 2 return a response containing the state of the login operation. The `state` property of the response object indicates the login status. For example, if the above examples are successful, `state` is `SUCCESS`. Make sure your code handles each of these `state` values: - **`REQUIRE_EMAIL_VERIFICATION`**: Login requires email verification. This occurs when you try to register a new member with an email address belonging to an existing contact. In this case, you need to [verify the email address](#step-5--verify-email-address). - **`REQUIRE_OWNER_APPROVAL`**: After registration, this indicates site owner approval is required to complete registration for the new member. Handle this by informing the visitor that their membership is pending. Whenever the site owner approves their membership, the member can log in. - **`SUCCESS`**: This indicates login was completed successfully. You can now [get the site member's access and refresh tokens](#generate-member-tokens). ## Step 5 | Verify email address If the [`loginState`](#step-4--handle-login-states) property of the object returned by [a call to Register V 2](#step-2--sign-up-a-new-member) is `REQUIRE_EMAIL_VERIFICATION`, an email containing a verification code is sent automatically to the member's email address. To complete the login process, call [Verify During Authentication](https://dev.wix.com/docs/api-reference/business-management/headless/verification/verify-during-authentication.md)specifying the following parameters: - **`code`**: The code received in the verification email. - **`stateToken`**: The state token received in response to calling Register V 2. ```curl curl --location 'https://www.wixapis.com/_api/iam/verification/v1/auth/verify' \ --header 'authorization: ' \ --header 'content-type: application/json' \ --data '{ "code": "123456", "stateToken": "AST.eyJraWQiOiJRUWpMeE1KaCIsImFsZyI6IlJTMjU2In0..." }' ``` Verify During Authentication's response contains the following: - **`state`**: The current [state](#step-4--handle-login-states) of the login process. Use this `state` value to determine the next step in the login process. - **`sessionToken`**: If the `state` value is `'SUCCESS'`, use the `sessionToken` to [get the site members tokens](#generate-member-tokens). - **`stateToken`**: If the `state` value is not `'SUCCESS'`. You will need to use the `stateToken` to continue the login process. ## Step 6 | Get the site member's access and refresh tokens If the [`state`](#step-4--handle-login-states) property of the object returned by [a call to Login V 2](#step-3--log-in-a-member), [a call to Register V 2](#step-2--sign-up-a-new-member), or [a call to Verify During Authentication](#step-5--verify-email-address) is `SUCCESS`, the member has been successfully logged in. In this case, the response object contains a `sessionToken` property. Use the `sessionToken` to call [Create Redirect Session](https://dev.wix.com/docs/api-reference/business-management/headless/redirects/create-redirect-session.md) to get the logged-in member's access and refresh tokens. Before calling Create Redirect Session, you will need to [prepare](#step-7--prepare-for-a-redirect-session) some information to be used in the call. ## Step 7 | Prepare for a redirect session Before you call Create Redirect Session, you need to prepare the following: - The **Client ID** of your OAuth app. You can find this value in 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#). If you haven't created an OAuth app yet, see [Create an OAuth App for Visitors and Members](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/about-authentication.md) to set one up. The client ID isn't a secret and can be used in frontend calls. - A [PKCE code verifier and code challenge](https://www.oauth.com/oauth2-servers/pkce/authorization-request/). These are used to prevent [CSRF attacks](https://en.wikipedia.org/wiki/Cross-site_request_forgery) and authorization code injection attacks. - An [OAuth2 state parameter](https://auth0.com/docs/secure/attack-protection/state-parameters) used to mitigate [CSRF attacks](https://en.wikipedia.org/wiki/Cross-site_request_forgery). ## Step 8 | Get an authorization URL Call [Create Redirect Session](https://dev.wix.com/docs/api-reference/business-management/headless/redirects/create-redirect-session.md) to get an authorization URL for the site member. Specify the following parameters, which include the data you [prepared earlier](#step-7--prepare-for-a-redirect-session): - **`clientId`**: The **Client ID** of your OAuth app, which can be found in your project's [**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). - **`codeChallenge`**: PKCE code challenge string. - **`codeChallengeMethod`**: Use `"S256"`. - **`responseMode`**: Use `"web_message"` for the authorization in an [iframe](#iframe), or `"query"`/`"fragment"` for a [full-page redirect](#full-page-redirect). - **`responseType`**: Use `"code"`. - **`scope`**: Use `"offline_access"`. - **`state`**: A state parameter. - **`sessionToken`**: The session token received from [a call to Login V 2](#step-3--log-in-a-member), [a call to Register V 2](#step-2--sign-up-a-new-member), or [a call to Verify During Authentication](#step-5--verify-email-address). ```curl curl --location 'https://www.wixapis.com/_api/redirects-api/v1/redirect-session' \ --header 'authorization: ' \ --header 'content-type: application/json' \ --data '{ "auth": { "authRequest": { "clientId": "", "codeChallenge": "JNU5gZmEjgVL2eXfgSmUW3S2E202k2rkq4u3M_drdCY", "codeChallengeMethod": "S256", "responseMode": "web_message", "responseType": "code", "scope": "offline_access", "state": "Z4dy7JM2S7n35VnBhdMeOQyXQW7UkE2Q1afdPLL419o", "sessionToken": "MST.eyJraWQiOiJ3cTFCcFlDbyIsImFsZyI6IlJTMjU2In0..." } } }' ``` Create Redirect Session responds with: - **`id`**: Redirect session ID. - **`fullUrl`**: An authorization URL. ```json { "redirectSession": { "id": "83cab021-c3de-47b9-afa2-e93602e38b09", "fullUrl": "https://mysite.com/example/_api/oauth2/authorize?clientId=e345..." } } ``` ## Step 9 | Authorize member Once you have an authorization URL, you can use it to authorize a member before requesting their access and refresh tokens. The authorization can be done either on the frontend (iframe), or on the backend (full-page redirect). The `responseMode` value defines the flow. ### iframe Use this flow when you want a token exchange without navigating away from your UI. The iframe doesn't need to be visible. 1. Open the authorization URL in an [iframe](https://www.w3schools.com/tags/tag_iframe.ASP). 1. Listen for a `postMessage` from the iframe. It will include a `state` parameter and a `code`. 1. Check that the `state` value is the same as the state value you passed when [getting the authorization URL](#step-8--get-an-authorization-url). 1. Use the `code` to [generate member tokens](#generate-member-tokens). ### Full-page redirect Use this flow when you want the token exchange to happen through a full-page redirect. 1. Redirect the browser to the authorization URL. 1. Wix redirects back to your callback URL with `state` and `code` included in the URL, based on your `responseMode` value: - `query`: in the URL query string (server-side). - `fragment`: in the URL fragment (client-side). 1. Check that the `state` value is the same as the state value you passed when [getting the authorization URL](#step-8--get-an-authorization-url). 1. Use the `code` to [generate member tokens](#generate-member-tokens). ### Generate member tokens After performing authorization, you have a `code` that you can use to generate access and refresh tokens for the logged-in member. Generate new member tokens using [Create Access Token](https://dev.wix.com/docs/api-reference/app-management/oauth-2/create-access-token.md). When calling Create Access Token, specify the following parameters: - **`clientId`**: The **Client ID** of your OAuth app, which can be found in your project's [**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). - **`grantType`**: Set as `"authorization_code"` to get member tokens with an authorization code. - **`code`**: The code you [received in the authorization](#step-9--authorize-member). - **`codeVerifier`**: The code verifier you [prepared for the redirect session](#step-7--prepare-for-a-redirect-session). ```curl curl --location 'https://www.wixapis.com/oauth2/token' \ --header 'content-type: application/json' \ --data '{ "clientId": "", "grantType": "authorization_code", "code": "OLI79QEL", "codeVerifier": "bRGwKp1zdrSY_3A_GRvK2JI9Iq2MykDV5NjXk3tcQn4" }' ``` Create Access Token responds with: - **`access_token`**: An access token used to authorize API calls. - **`expires_in`**: The number of seconds before the access token expires. Access tokens expire after 4 hours (14,400 seconds). - **`refresh_token`**: A refresh token used to get a new access token. ```json { "access_token": "OauthNG.JWS.eyJraWQiOi1JzdUpwSCIsImFsZyI6IkhTMjU2In0...", "token_type": "Bearer", "expires_in": 14400, "refresh_token": "JWS.eyJraWQiOiJ1SEJzdUpwSCIsImFsZyI6IkhTMjU2In0..." } ``` Once you have tokens, you can use them to make [authenticated calls to APIs](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/oauth/make-rest-api-calls-using-oauth.md) on behalf of the current member. ## Step 10 | Send a password-reset email To enable a member to reset their password, call [Send Recovery Email](https://dev.wix.com/docs/api-reference/business-management/headless/recovery/send-recovery-email.md), specifying the following parameters: - **`email`**: Email address to send the recovery email to. - **`redirect.url`**: The full URL to redirect the member to after they change their password. The `redirect.url` 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). - **`redirect.clientId`**: The **Client ID** of your OAuth app, which can be found in your project's [**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). ```curl curl --location 'https://www.wixapis.com/_api/iam/recovery/v1/send-email' \ --header 'content-type: application/json' \ --header 'authorization: ' \ --data '{ "email": "john@doe.com", "redirect": { "url": "https://mtsite.vercel.app", "clientId": "" } }' ``` Send Recovery Email responds with an empty response on success. ## Logging out a member To log a site member out, take the following steps: 1. Get the member's logout URL Use Create Redirect Session to get a logout URL for the site member specifying the following parameters: - **`clientId`**: The **Client ID** of your OAuth app, which can be found in your project's [**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). - **`postFlowUrl`**: Where the member will be redirected after logging out. ```curl curl --location 'https://www.wixapis.com/_api/redirects-api/v1/redirect-session' \ --header 'content-type: application/json' \ --header 'authorization: ' \ --data '{ "logout": { "clientId": "" }, "callbacks": { "postFlowUrl": "https://mysite.com/" } }' ``` 2. Redirect to the logout URL Redirect the browser to the returned `fullUrl` to log the site member out. The browser is automatically redirected back to the `postFlowUrl` that you specified when calling Create Redirect Session. ## Profile The profile object contains the following properties: | Name | Type | Description | | :---------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------ | | `firstName` | string | First name. | | `lastName` | string | Last name. | | `nickname` | string | Nickname. | | `picture` | string | Picture. | | `labels` | string[] | Labels. | | `language` | string | Language. | | `privacyStatus` | string | One of: `'UNDEFINED'`, `'PUBLIC'`, `'PRIVATE'` | | `customFields` | object | Custom fields as an object where the keys are the field name and the values are the field values. | | `secondaryEmails` | object[] | Secondary email address objects, each with `email` and `tag` fields, where tag is one of: `UNTAGGED`, `MAIN`, `HOME`, or `WORK`. | | `phonesV2` | object[] | Phone number objects, each with `countryCode`, `phone`, and `tag` fields, where tag is one of: `UNTAGGED`, `MAIN`, `HOME`, or `WORK`. | | `addresses` | object[] | Physical address objects, each with `address` and `tag` fields, where tag is one of: `UNTAGGED`, `MAIN`, `HOME`, or `WORK`. | | `company` | string | Company name. | | `position` | string | Position. | | `birthdate` | string | Birth date.| ## See also - [Handle Visitors](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/visitors/handle-visitors-using-the-rest-api.md) - [Handle Members with a Wix Login Page](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/members/wix-login-page/wix-managed-login-using-the-rest-api.md)