Quick Start Guide

Descope makes it extremely easy for you to enable a variety of user authentication mechanisms in your applications. The most straightforward, most flexible and recommended way of integrating Descope into your application is using Descope flows.

There are two other integration approaches and you can compare and contrast them with our recommended approach here. This quick start guide will walk you through the steps to integrate descope into your application using Descope flows.

The video below covers a quick overview on the process of integrating Descope with your application.

Initial Setup

The first step is to login to the Descope console with any of the supported authentication methods and get your project ID. After logging in to the console, you will notice that we have fetched your project details (top-right corner) on the docs page. The project id will be used in the steps below. You can also find your project id at Settings>Project.

If this is your first time logging in to the Descope console, you should consider completing the "Getting Started" wizard to set up the default flows. Descope comes with default flows for sign-up, sign-in, step-up, and other common scenarios. You can leave the flows as they are or customize them to meet your application specific needs. We recommend exploring customization at a later stage.

Integrate your frontend

After setting up your flows in the Descope console service, the next step is to integrate the Descope client SDKs into your application. Descope supports many SDKs for popular frontend frameworks. Below are the steps to integrate Descope SDK in your application.

Install SDK

You can install the Descope React SDK as described below.

ReactNextJSHTML/WebJS
npm i --save @descope/react-sdk
npm i --save @descope/react-sdk
<!-- Not applicable for HTML -->

Import SDK

Next step is to import the Descope React SDK using the sample code below.

ReactNextJSHTML/WebJS
import { AuthProvider, useDescope, useSession, useUser } from '@descope/react-sdk'
import { Descope } from '@descope/react-sdk'
// Other flows can be imported as follows. Descope import will let you run any flow with flow id.
// import { SignInFlow, SignUpFlow, SignUpOrInFlow } from '@descope/react-sdk'
import dynamic from "next/dynamic";
import { AuthProvider, useDescope, useSession, useUser } from '@descope/react-sdk'
// Other flows can be imported as follows. Descope import will let you run any flow with flow id.
// import { SignInFlow, SignUpFlow, SignUpOrInFlow } from '@descope/react-sdk'

// Descope component interacts with browser API and should render only in CSR
const DescopeWC = dynamic(
  async () => {
    const { Descope } = await import("@descope/react-sdk");
    return (props: React.ComponentProps<typeof Descope>) => (
      <Descope {...props} />
    );
  },
  {
    ssr: false,
  }
);
<head>
  <script src="https://unpkg.com/@descope/web-component@latest/dist/index.js"></script>
</head>

Start Sign-in flow

At this point, your application is integrated with Descope, and the next step is to trigger Descope Flow. The flow will fetch and display the first login or sign-up screen. As the user interacts with these screens, the flows continue and will eventually authenticate the user. After successful authentication (flow ends), the client SDK will store JWT in your browser local storage and cookies, and the cookie will be sent to your application server automatically with every request.

ReactNextJSHTML/WebJS
// Wrap your application with the Descope AuthProvider
const AppRoot = () => {
    return (
        <AuthProvider
            projectId='__ProjectID__'
            //  baseUrl="<URL>" // you can also configure the baseUrl ex: https://auth.company.com  - this is useful when you utilize CNAME within your Descope project.
        >
         <App />
        </AuthProvider>
    )
}

// Embed flow react component in your app
// Callbacks:
//    onSuccess: called after successful sign-in. Receives event "e" with details.
//      event: {
//        detail: {
//           sessionJwt: string, refreshJwt: string, user: UserResponse, firstSeen: boolean,
//        }
//      }
//    onError: called if the flow fails. Receives event "e" with details.
//      event: {
//         detail: {
//            message: string;
//          	code: string; // descope error id code (NOT to be confused with http code)
//            }
//         }
// Hook:
//  Use the useDescope, useSession and useUser hooks in your components in order to get authentication state, user details and utilities


const App = () => {
    // isAuthenticated: boolean - is the user authenticated?
    // isSessionLoading: boolean - Use this for showing loading screens while objects are being loaded
    const { isAuthenticated, isSessionLoading } = useSession()

    // user: user object with all the user details such as email, name etc.
    // isUserLoading: boolean - Use this for showing loading screens while objects are being loaded
    const { user, isUserLoading } = useUser()

    // logout - call logout to logout the user (deletes all session state)
    const { logout } = useDescope()

    return (
        {...}
        {
          (isSessionLoading || isUserLoading) && <p>Loading...</p>
        }

        { isAuthenticated &&
            (
              <>
                <p>Hello ${user.name}</p>
                <div>My Private Component</div>
                <button onClick={logout}>Logout</button>
              </>
            )
        }

        { !isAuthenticated &&
          (
            <Descope
              flowId="sign-up-or-in" // If you wish to use another flow, flow-id is shown in the console
              onSuccess = {(e) => console.log(e.detail.user)}
              onError={(e) => console.log('Could not log in!')}
              theme="light" // "light" or "dark", default is "light"
              //    debug=boolean // Shows a debug widget if true. Can be true or false, default is false.
              //    tenant="<tenantId>" // Which tenant the auth flow will sign the user into
            />
          )
        }
    )
}
// Wrap your application with the Descope AuthProvider
const AppRoot = () => {
    return (
        <AuthProvider
            projectId='__ProjectID__'
            //  baseUrl="<URL>" // you can also configure the baseUrl ex: https://auth.company.com  - this is useful when you utilize CNAME within your Descope project.
        >
         <App />
        </AuthProvider>
    )
}

// Embed flow react component in your app
// Callbacks:
//    onSuccess: called after successful sign-in. Receives event "e" with details.
//      event: {
//        detail: {
//           sessionJwt: string, refreshJwt: string, user: UserResponse, firstSeen: boolean,
//        }
//      }
//    onError: called if the flow fails. Receives event "e" with details.
//      event: {
//         detail: {
//            message: string;
//          	code: string; // descope error id code (NOT to be confused with http code)
//            }
//         }
// Hook:
//  Use the useDescope, useSession and useUser hooks in your components in order to get authentication state, user details and utilities


const App = () => {
    // isAuthenticated: boolean - is the user authenticated?
    // isSessionLoading: boolean - Use this for showing loading screens while objects are being loaded
    const { isAuthenticated, isSessionLoading } = useSession()

    // user: user object with all the user details such as email, name etc.
    // isUserLoading: boolean - Use this for showing loading screens while objects are being loaded
    const { user, isUserLoading } = useUser()

    // logout - call logout to logout the user (deletes all session state)
    const { logout } = useDescope()

    return (
        {...}
        {
          (isSessionLoading || isUserLoading) && <p>Loading...</p>
        }

        { isAuthenticated &&
            (
              <>
                <p>Hello ${user.name}</p>
                <div>My Private Component</div>
                <button onClick={logout}>Logout</div>
              </>
            )
        }

        { !isAuthenticated &&
          (
            <DescopeWC
              flowId="sign-up-or-in" // If you wish to use another flow, flow-id is shown in the console
              onSuccess = {(e) => console.log(e.detail.user)}
              onError={(e) => console.log('Could not log in!')}
              theme="light" // "light" or "dark", default is "light"
              //    debug=boolean // Shows a debug widget if true. Can be true or false, default is false.
              //    tenant="<tenantId>" // Which tenant the auth flow will sign the user into
            />
          )
        }
    )
}
<!DOCTYPE html>
<head>
  <script src="https://unpkg.com/@descope/web-component@latest/dist/index.js"></script>
  <script src="https://unpkg.com/@descope/web-js-sdk@latest/dist/index.umd.js"></script>
</head>
<html>
  <body>
    <h1>Log In With Descope Flows</h1>
    <p id="container"></p>

    <descope-wc project-id="__ProjectID__" flow-id="sign-up-or-in"></descope-wc>


    <script>
      const sdk = Descope({ projectId: projectId, persistTokens: true, autoRefresh: true });

      const sessionToken = sdk.getSessionToken()
      var notValidToken
      if (sessionToken) {
          notValidToken = sdk.isJwtExpired(sessionToken)
      }
      if (!sessionToken || notValidToken) {
          var container = document.getElementById('container');
          container.innerHTML = '<descope-wc project-id="' + projectId+ '" flow-id="sign-up-or-in"></descope-wc>';
          <!-- ex Flow IDs: "sign-in", "sign-up", "sign-up-or-in", see full list Descope flows page -->
          <!-- base-url="<URL>" // base-url can also be configured ex: https://auth.company.com  - this is useful when you utilize CNAME within your Descope project. -->
          <!-- theme="<option>" // options are "light", "dark", or "os". OS will auto select light or dark based on OS theme settings. Default is light theme.-->
          <!-- debug=boolean // options are true or false. Default is false. Shows a debug widget when true -->
          <!-- persistTokens=boolean //Use persistTokens option in order to add existing tokens in outgoing requests (if they exists) -->
          <!-- autoRefresh=boolean //Use auto refresh option in order to automatically refresh sessions once they expire if the refreshToken is not expired -->

          const wcElement = document.getElementsByTagName('descope-wc')[0];
          const onSuccess = (e) => {
            console.log(e.detail.user),
            sdk.refresh(),
            window.location.replace("./loggedIn?userId=" + encodeURIComponent(e.detail.user.loginIds))
          };
          const onError = (err) => console.log(err);

          wcElement.addEventListener('success', onSuccess);
          wcElement.addEventListener('error', onError);
      }
    </script>
  </body>
</html>

Session Validation

The final step of completing the authentication with Descope is to validate the user session. Descope provides rich session management capabilities, including configurable session timeouts and logout functions. You can find the details and sample code for session validation here.



left parenthesis
Checkpoint: Your application is now integrated with Descope. Please test with sign-up or sign-in use case.
right parenthesis


Customize

Now that you have the end-to-end application working, you can choose to customize a few different areas of Descope, including adding your brand and style as well as configuring custom user authentication journeys. We recommend you start by customizing your user-facing screens, such as signup and login. In addition, customize some system properties such as session timeout, cookie settings, custom domain setup, etc. These are important to ensure you have the right balance between the security of your applications and the end-user experience. Here are more details about available customizations.


Customize


Would you like to explore other ways to integrate Descope?