Build Custom Login and Signup Pages with the Astro Integration

When you build with Wix's Astro integration, you can create your own login and signup forms and submit them to the integration's built-in authentication endpoints. You design the pages and display messages to members. Wix verifies their credentials, and the integration handles OAuth, exchanges tokens, and manages the authenticated session.

This article explains how to log in existing members, sign up new members, verify email addresses, add social login, and add reCAPTCHA protection. You don't need to create a Wix client or implement token storage and refresh for these flows.

Notes:

Step 1 | Set up your site

Make sure your project uses Wix's Astro integration with its built-in authentication routes enabled.

Custom login and signup forms need pages on your site to send the browser to after each attempt. Each form specifies these pages in its returnToUrl and failureUrl fields. After successful authentication, the browser goes to the returnToUrl page. After an unsuccessful attempt, it goes to the failureUrl page, which displays the outcome. These must be pages that exist on your site.

The examples in this article use the following pages. Replace them with your own page paths.

  • /login: Displays the login form and the outcome of an unsuccessful login.
  • /signup: Displays the signup form and the outcome of an unsuccessful signup.
  • /verify-email: Displays the email verification form and the outcome of an unsuccessful verification.
  • /account: The page members go to after they log in or sign up.

In your custom forms, you'll specify these pages as local paths on your site, such as /account. The endpoints accept only local paths on the same origin as the request.

Once your pages are set up, add your callback URL and success destinations to your allowed redirect URIs. In your project's Headless Settings, open your OAuth app's Settings and go to URLs > Allowed authorization redirect URIs. Add the full callback URL and the full URL of each page you use as a returnToUrl destination. Each URL must match exactly. For example, for a site at https://example.com that returns members to /account, add:

  • https://example.com/api/auth/callback
  • https://example.com/account

Pages you use only as a failureUrl don't need to be allowlisted. Wix-managed headless adds many relevant redirect URIs during setup, so check the existing entries and add any missing URLs. For more details, see Allow Redirect URIs and Domains.

Step 2 | Build a login form

Add a form that sends the member's email and password to POST /api/auth/login:

Copy

The browser submits this form natively, posting it directly to the endpoint without JavaScript and following the redirects in the response. A native form submission must include failureUrl. To submit forms with JavaScript instead, see Submit forms with JavaScript.

When credentials are accepted, the endpoint redirects the browser to Wix authorization. The browser then returns through /api/auth/callback, where the integration saves the member session and redirects to returnToUrl. If you omit returnToUrl, the destination is /. From then on, Wix SDK calls run as the signed-in member.

Before displaying a login or signup form, check whether the visitor is already signed in using the integration's contextual authentication strategy's loggedIn() method. Show signed-in members their account and a logout option instead. The endpoints reject credential submissions from an existing member session with ALREADY_LOGGED_IN.

Step 3 | Build a signup form

Add a form that sends a new member's email and password to POST /api/auth/signup:

Copy

Successful signup follows the same authorization and callback flow as login. Depending on your site's settings, a member may need to verify their email address or wait for owner approval before they can sign in.

Note: The signup endpoint supports email and password registration. It doesn't support additional profile fields.

Step 4 | Handle authentication outcomes

For native form submissions, unsuccessful authentication redirects the browser to the form's specified failureUrl. The endpoint adds loginState and, when available, errorCode as query parameters. Service errors and already signed-in sessions use an error parameter instead. Your page must read these parameters and display the appropriate message.

Your page should handle the following outcomes:

OutcomeWhat your page should do
loginState=FAILURE with errorCode=invalidCredentialsAsk the member to check their login email and password.
loginState=FAILURE with errorCode=invalidEmail or invalidPasswordAsk the member to correct their registration details.
loginState=FAILURE with errorCode=unknownDisplay a fallback message that asks the member to check their details and try again. Signup returns this code for some invalid registration details, such as an invalid password.
loginState=FAILURE with errorCode=emailAlreadyExistsOffer a link to your login page.
loginState=EMAIL_VERIFICATION_REQUIREDShow the email verification form.
loginState=OWNER_APPROVAL_REQUIREDExplain that the site owner must approve the membership before the member can log in.
loginState=SILENT_CAPTCHA_REQUIRED or USER_CAPTCHA_REQUIREDObtain the required reCAPTCHA token and let the visitor retry.
loginState=FAILURE with errorCode=missingCaptchaToken or invalidCaptchaTokenObtain a fresh reCAPTCHA token before retrying.
loginState=FAILURE with errorCode=resetPasswordOffer password recovery. This outcome doesn't send a reset email automatically.
error=ALREADY_LOGGED_INOffer the member their account and a logout option. Don't sign them out automatically.
error=AUTH_SERVICE_ERROR or INTERNAL_ERRORDisplay a service-error message. After a signup error, also offer login because the account may already have been created.
Any other outcomeDisplay a fallback message and a way to return to login.

Notes:

  • Verification, approval, and CAPTCHA-required outcomes don't establish a member session.
  • Don't automatically repeat signup after a service error. Registration may have created the account before the authorization redirect failed.
  • If a native submission doesn't include failureUrl, or if returnToUrl or failureUrl isn't a local path on the same origin as the request, the endpoint returns an INVALID_REQUEST error directly instead of redirecting to the failure page.

Step 5 | Verify an email address

Wix requires email verification in some cases, for example when a new member signs up with an email address that already belongs to a contact on your site. When it does, login or signup returns EMAIL_VERIFICATION_REQUIRED, and Wix automatically emails the member a verification code. You can't know in advance which members need to verify, so add a form that collects the code and submits it to POST /api/auth/verify-email:

Copy

When a login or signup requires email verification, the integration saves the pending verification state and original returnToUrl in an HttpOnly cookie. The verification form doesn't submit a state token or another returnToUrl. On success, the browser follows the authorization and callback flow and returns to the destination requested during login or signup.

Verification must happen in the same browser and on the same origin, with cookies enabled. The pending cookie lasts 15 minutes, though Wix may expire the challenge earlier. Only 1 pending flow is supported per browser. A new valid login or signup submission replaces the previous flow.

The failureUrl page specified by the verification form must handle these outcomes in addition to the authentication outcomes above:

OutcomeWhat your page should do
loginState=EMAIL_VERIFICATION_REQUIREDLet the member submit another code.
error=VERIFICATION_FAILEDAsk the member to check the code or restart login. This error can also mean the Wix challenge expired.
error=VERIFICATION_STATE_EXPIREDAsk the member to restart login because the pending state is missing, invalid, or expired.
loginState=OWNER_APPROVAL_REQUIREDExplain that membership is pending owner approval.
error=AUTH_SERVICE_ERROROffer retry or a return to login. If verification succeeded before the authorization step failed, the member needs to log in again.

If the verification service rejects a code or returns an error, the integration retains the pending verification state for retry. The verification endpoint can't send a new code. To get a new code, the member must restart login or signup.

Add social login

To let members sign in with Google or Facebook, add a link to /api/auth/login with the idp query parameter. You can place these links alongside your custom email and password inputs:

Copy

Clicking a link sends the member to the selected provider's sign-in page. After authentication, the integration handles the callback, establishes the member session, and redirects to returnToUrl. Use a local path for returnToUrl; if you omit it, the member returns to /.

Social login uses a browser navigation to GET /api/auth/login. No JavaScript handler or credential submission is needed. The supported idp values are google and facebook; omitting idp opens the Wix login page instead.

Submit forms with JavaScript

You can also submit login, signup, and verification forms with fetch. Set Accept: application/json to receive a JSON outcome instead of a redirect. Without this header, requests default to redirect responses, which don't navigate the page when made through fetch.

For example, this script submits the form to its existing action, completes successful authentication, and sends members to your verification page when needed.

The script targets a form with a data-auth-form attribute and uses an element with the ID auth-message to display different messages:

Copy

This example uses a generic failure message. In your UI, you can use loginState, errorCode, and error to show messages and take the actions needed to handle authentication and email verification outcomes.

You can submit JSON instead of FormData by setting Content-Type: application/json and using JSON.stringify() for the body. The endpoints support JSON, URL-encoded, and multipart request bodies. In JSON response mode, failureUrl is optional. A SUCCESS response contains a redirectUrl; explicitly navigate to it to complete authentication.

Add reCAPTCHA protection

You can add reCAPTCHA support to custom login and signup forms. In this case, your page is responsible for running the challenge, handling CAPTCHA-required outcomes, and obtaining a fresh token before retrying a rejected submission. The login and signup endpoints don't render CAPTCHA or generate tokens.

Enable reCAPTCHA in your member login settings, then add reCAPTCHA Enterprise to your custom login and signup UI. Use Wix's visible or invisible site key as described in Add reCAPTCHA to a Custom Login Page (JS SDK).

Follow that guide to render the challenge and obtain tokens. When you submit a login or signup form to the Astro endpoints, include the token in the form or JSON body instead of calling the SDK's login or registration method directly. Use the field that matches your reCAPTCHA mode:

ModeForm or JSON field
Visible reCAPTCHArecaptchaToken
Invisible reCAPTCHAinvisibleRecaptchaToken

For a native form, add a hidden field for the token:

Copy

The field is empty when the page loads. Before the form submits, set its value to the token returned by your reCAPTCHA component. For example, in the component's success callback:

Copy

The JavaScript example in the previous section for submitting a form includes named hidden fields automatically through FormData. For a JSON submission, include the token directly in the body:

Copy

For invisible reCAPTCHA, use invisibleRecaptchaToken instead.

Note: When using the Astro login and signup endpoints, pass the reCAPTCHA tokens as top-level fields. Don't nest them under captchaTokens as you would if you were calling the SDK directly.

Password recovery

There is no built-in password-reset route for these custom login and signup forms. For a "Forgot password?" action or a resetPassword outcome, use the SDK's sendPasswordResetEmail method from the browser. The redirectUri must be an absolute URL registered in the OAuth client's allowed authorization redirect URIs.

The member follows the email link to a Wix-hosted password-reset page and returns to your specified URL after changing their password. See the password-reset instructions for the SDK call. After the member resets their password, continue using the Astro endpoints for login and signup.

Log out

Submit a browser navigation request to POST /api/auth/logout:

Copy

You must use a native form submission for logout. The logout flow redirects through Wix, so calling it with fetch or an XHR library fails and leaves the member logged in. If you omit returnToUrl, the browser returns to /.

Troubleshooting

  • A JavaScript submission doesn't sign the member in: Set Accept: application/json and navigate to the successful response's redirectUrl. The callback must complete before API calls run as the member.
  • A submission returns ALREADY_LOGGED_IN: The browser already has a member session, possibly started in another tab. Offer the account page or explicit logout; don't automatically switch accounts.
  • Verification state is missing or expired: Restart login in the same browser and origin, with cookies enabled.
  • A request returns INVALID_REQUEST, FORBIDDEN, or UNSUPPORTED_MEDIA_TYPE: Check required fields, use a supported body format, and submit from the same origin. Redirect destinations must stay on that origin, and forms must not send duplicate fields.
  • A request returns an empty 406 response: The Accept header must allow text/html or application/json.
  • Signup fails after registration: Offer login. The member's account may already exist even if the authorization redirect couldn't be prepared.

See also

Last updated: 19 October 2026

Did this help?