Skip to content
Last updated

Frontegg's built-in authentication methods

This guide will discuss the various capabilities within the Frontegg client-side SDKs that handle authentication. All the methods that are discussed below can be found under the @frontegg folder in your node_modules. Frontegg has two main login implementation options:

  • Hosted Login
  • Embedded Login

While the Frontegg Hosted Login relies on OAuth2 authentication protocol, the embedded login relies directly on Frontegg APIs for authentication. The methods for each of these login types differ. Both methods rely on fe_refresh cookie that is stores in the browser to check whether a user is authenticated or not.

LoginWithRedirect

useLoginWithRedirect() is a react hook that is designed for Frontegg's hosted login and checks whether the user is authenticated by sending a request to /silent route with the fe_refresh cookie (if exists). In case disableSilentRefresh is passed as true, the authentication will be handled through /authorize route, per the OIDC protocol.

If a user is not authenticated, they will be automatically redirected to[your-frontegg-domain]/oauth/account/login for authentication. In order to avoid auto-redirect, please use loadUserOnFirstLoad.

useLoginWithRedirectV2

useLoginWithRedirectV2() is the extended version of useLoginWithRedirect for Frontegg's hosted login. Like the original hook, it returns an async function that starts the hosted login flow. Both versions run the same silent-authorize-first flow: they attempt a silent authorize before anything else, and generate the PKCE code_challenge, nonce, and state only if that silent check fails and a redirect actually happens (in useLoginWithRedirect the underlying call is refreshOrRequestHostedLoginAuthorize). Migrating to V2 does not add PKCE, state, or the silent round trip, because V1 already performs all of them.

What V2 adds is a different call shape and a few options. Instead of a flat additionalParams argument it accepts a single payload object, and that object exposes shouldRedirectToLogin, firstTime, and loginDirectAction alongside additionalParams. The most common reason to reach for it is loginDirectAction, which opens the hosted login box directly on a specific action, such as the sign-up tab.

The hook is exported from @frontegg/react and returns an async function:

import { useLoginWithRedirectV2 } from '@frontegg/react';

const loginWithRedirect = useLoginWithRedirectV2();

// loginWithRedirect signature:
// (payload?: {
//   additionalParams?: Record<string, string>;
//   shouldRedirectToLogin?: boolean;
//   firstTime?: boolean;
//   loginDirectAction?: LoginDirectAction;
// }) => Promise<void>

The payload options are:

  • additionalParams (Record<string, string>): extra query parameters that are merged into the /oauth/authorize request, alongside the SDK-managed response_type, client_id, scope, redirect_uri, code_challenge, and nonce.
  • shouldRedirectToLogin (boolean): controls what happens when the silent session check finds no active session. Set it to true to redirect the user to the hosted login box. When it is omitted or false, the hook stops loading and returns without redirecting, so you can render your own unauthenticated state.
  • firstTime (boolean): when set, refreshOrRequestHostedLoginAuthorizeV2 sets isLoading: true first, and if the active URI is exactly /oauth/callback (the isOauthCallbackRoute check is a strict equality) it returns immediately, skipping both the silent authorize and the redirect. Off the callback route the flag has no effect beyond the loading state. This is the flag the SDK bootstrap passes internally alongside loadUserOnFirstLoad, so application code rarely needs to set it.
  • loginDirectAction (LoginDirectAction): opens the hosted login box directly on a specific action. See below.

The LoginDirectAction type is:

interface LoginDirectAction {
  type: 'direct' | 'signup' | 'social-login' | 'custom-social-login';
  data: any;
  additionalQueryParams?: Record<string, string>;
}

Under the hood the SDK base64-encodes the loginDirectAction object and passes it to the hosted login as the login_direct_action parameter. The meaning of data depends on the action type (from createLoginActionComponent and validateLoginAction in useLoginHint.tsx):

typeMeaning of data
signupUnused. validateLoginAction returns true before data is read, so the sign-up action never touches it.
directAn allowlisted absolute URL string (see the allowlist note below).
social-loginA provider name, for example google.
custom-social-loginThe custom social provider id.

The additionalQueryParams interface field is read narrowly. Today the only value consumed is prompt: 'consent' on a social-login action, so it is best kept out of the main call.

To send the user straight to the sign-up tab of the hosted login box, use the purpose-built signup action, which takes no data:

import { useLoginWithRedirectV2 } from '@frontegg/react';

const loginWithRedirect = useLoginWithRedirectV2();

const goToSignUp = () => {
  loginWithRedirect({
    shouldRedirectToLogin: true,
    loginDirectAction: { type: 'signup' },
  });
};

validateLoginAction returns true for signup before it inspects data, and the action redirects to calculatedBasename + signUpUrl from useAuthRoutes(). That means it automatically respects a customized routes.signUpUrl and the shadow-DOM basename. Prefer this over a direct action pointing at a hardcoded /oauth/account/sign-up path, which breaks for any tenant that overrode signUpUrl. Use the direct type for its actual purpose: opening an allowlisted social or custom-social authorize URL, not the sign-up tab.

direct URLs are checked against an allowlist

The data of a direct action is not a free-form URL. It is validated as a security allowlist that prevents the login box from being driven as an open redirect. A direct URL is accepted only if it matches one of:

  • the theme's loginBox.login.directLoginActionConfig.allowList (operators startWith, endWith, contains, equals),
  • a known social-login authorize URL from socialLoginUrlMapper, or
  • a prefix derived from the SDK's configured baseUrl: ${baseUrl}/oauth/, ${baseUrl}/identity/resources/auth/v2/user/sso/default/, or ${baseUrl}/frontegg/identity/resources/auth/v2/user/sso/default/.

Being absolute is necessary but not sufficient. An absolute URL on a different host (for example https://[some-other-host]/oauth/account/sign-up) is rejected exactly like a relative path. When a direct URL is rejected, the box logs the reason to the console, strips login_direct_action from the URL via history.replaceState, and falls back to the default tab.

When a direct action appears to do nothing

Two conditions in useLoginHint.tsx explain most actions that seem to be ignored:

  • The login box ignores login_direct_action entirely unless the landing pathname matches routes.loginUrl or routes.signUpUrl.
  • useLoginHint returns {} and does nothing while isLoading || isAuthenticated is true. So for a user who already has a valid session, the silent authorize succeeds, the hook resolves without navigating anywhere, and a Sign-up button wired to this snippet appears to do nothing.

To force the hosted login screen for a user who still holds a valid session, pass additionalParams: { prompt: 'login' }. This is the supported way to skip the silent check and always show the box. login_direct_action survives this path: it is injected into additionalParams before the additionalParams?.['prompt'] === 'login' check in refreshOrRequestHostedLoginAuthorizeV2, so your direct action still applies. The trade-off is that you always show the box and never reuse an existing session.

You can also open the hosted sign-up page with a plain link or navigation to [your-frontegg-domain]/oauth/account/sign-up. The difference is coordination, not OAuth state:

  • Plain /oauth/account/sign-up link. Simple to add, but a raw navigation to the hosted page never starts an authorize request, so there is no PKCE verifier or state to lose. The practical consequences are that nothing coordinates the return trip back into your app, and an existing session is not checked first.
  • useLoginWithRedirectV2 with a signup action. Opens the same sign-up tab through the SDK, so the return trip is coordinated and an existing session is checked by the silent authorize before the box is shown. Use it whenever the sign-up entry point is part of your app's authenticated flow.

FRONTEGG_AFTER_AUTH_REDIRECT_URL

This variable is supported in all client-side SDKs. The below example showcases how to pull query params or user's original route or query params. This data can be then used for redirecting a user to the original route they've tried to access, or if you use UTM, you can send these to your marketing platform.

  useEffect(() => {
    if (!isAuthenticated && !isLoading) {
      console.log( window.location.search.toString())
      window.localStorage.setItem('FRONTEGG_AFTER_AUTH_REDIRECT_URL', `/${window.location.search.toString()}`)
      loginWithRedirect();
    }
  }, [isAuthenticated, loginWithRedirect]);

UseAuth

This is a react hook that is designed to check whether the user is authenticated and allows to pull the user's data if they are. Unlike UseAuthUser, this hook, does not handle redirects OOTB.

UseAuthUser

This is a react hook that is designed for Frontegg's embedded login and checks whether the user is authenticated by sending a request to /refresh route with the fe_refresh cookie (if exists). If the cookie exists and valid, the user will get automatically logged in. If the cookie is does not exist or is expired, the user will get redirected automatically to the embedded login box on /account/login.

UseAuthUserOrNull

This is a react hook that is designed to check whether the user is authenticated and allows to pull the user's data if they are. Unlike UseAuthUser, and similar to UseAuth, this hook, does not handle redirects OOTB.

requestAuthorize

This method is designed to force a hard refresh of the page and user's token. The request will handle either a refresh for embedded or for a hosted login, depending on what is being passed for hostedLoginBox to the application.

logout

This method is designed for Frontegg's embedded login. It will delete the active fe_refresh cookie in the browser and the user will get logged out. Note that if you're using Frontegg's hosted login, you should explicitly call:

${baseUrl}/oauth/logout?post_logout_redirect_uri=${window.location} as described in the hosted login guides.


Usage

See below the examples of how these methods can be imported and used in your application. For details, please refer to the integration guides.


import {
  useAuth,
  useAuthUser,
  useAuthOrNull,
  useAuthActions,
} from '@frontegg/react'

const { requestAuthorize } = useAuthActions()
const { user, isAuthenticated, isLoading } = useAuth()