Skip to content

Javascript - Integrate your frontend

Minimal example

The following example will display a different message for logged-in users vs logged out. We'll go into more detail about how it works and show more advanced examples down below.

import {createClient} from "@propelauth/javascript";

const client = createClient({
    authUrl: "YOUR_AUTH_URL", //(1)
    enableBackgroundTokenRefresh: true, //(2)
});

client.getAuthenticationInfoOrNull().then(authInfo => {
    const element = document.getElementById("text")
    if (authInfo) {
          element.innerText = "You are logged in as " + authInfo.user.email //(3)
    } else {
          element.innerText = "You are not logged in"
    }
});
  1. Your auth URL can be found in your PropelAuth dashboard. You will have a different URL for your test and production environment, so you may want to store it in an ENV variable.
  2. PropelAuth uses short-lived tokens for security reasons. Enabling this feature will automatically refresh those tokens in the background. See technical details for more info.
  3. User contains other metadata like userId

Technical details

When a user logs in via your hosted pages, a secure, http-only cookie is created. This cookie allows PropelAuth to identify logged-in users. In production, we require you use a custom domain to avoid third-party cookie issues for your users. Browsers like Safari will block cookies across domains, which is why we include custom domains even in our free plan.

Afterwards, your frontend can make a request to PropelAuth to determine if the current user is logged in and get their information.

auth overview

On top of user information, your frontend will get an access token for that user. These tokens are JWTs, which we've written about here.

Later on, when your frontend makes requests to your backend, it will include an access token, which your backend can validate and determine whose token it is. This validation is done entirely on your backend and doesn't need to make any requests to PropelAuth.

The access token is short-lived, and our libraries will refresh the token both periodically and when the user switches to your tab or reconnects to the internet.

Configure

Go to your PropelAuth project and click Frontend Integration in the sidebar. You will see:

  • Auth URL - This is where your authentication pages are hosted, and you will need this for the setup step.

  • Test Environment - This is where you test. If you are running your code locally, use localhost and provide the port you test on. If you are using tool like Webflow, select Webflow and enter your subdomain.

  • Login Redirect Path - After a user logs in, they will be redirected here.
  • Logout Redirect Path - After a user logs out, they will be redirected here.

Install

In your application, install the @propelauth/javascript library.

$ npm install --save @propelauth/javascript
$ yarn add @propelauth/javascript

and then you can import it

import {createClient} from "@propelauth/javascript"

Alternatively, you can use a CDN:

<script src="https://www.unpkg.com/@propelauth/javascript@2.0.0/dist/javascript.min.js" 
        integrity="sha384-CnMW/GT96q1vxl3xq1fIbUrmXpDIsXVtY+/FpJW+rMSCgjlOWpbVfs5G0dg2bMN5" 
        crossorigin="anonymous"></script>

then a global PropelAuth object will be created, and you can call createClient from it:

<script>
  PropelAuth.createClient({...});
</script>

createClient

Creates an authentication client which manages your access token, fetches user information, and provides other useful authentication functions.

The client also refreshes auth information when a user switches focus to your tab or reconnects (if they were offline).

const authClient = createClient({
    authUrl: "https://auth.yourdomain.com", // (1)
    enableBackgroundTokenRefresh: true, // (2)
})
  1. The base URL where your authentication pages are hosted. You can find this under the Frontend Integration section for your project.
  2. If true, periodically refresh the access token in the background. This helps ensure you always have a valid token ready to go. Default true.

AuthenticationInfo and User metadata

There are a few key types that this library uses, here are their signatures:

type AuthenticationInfo = { 
    // An access token for the current logged in user
    accessToken: string,
    // When the access token will no longer be valid, in seconds.
    expiresAtSeconds: number,
    // A collection of functions for managing organization membership information for the current user
    orgHelper: OrgHelper
    // A collection of functions for checking roles (RBAC) and permissions for the current user
    accessHelper: AccessHelper
    // For all organizations the current user is a member of,
    //   this provides a mapping from their ids to metadata about them
    // You should prefer orgHelper and accessHelper to orgIdToOrgMemberInfo.
    orgIdToOrgMemberInfo?: OrgIdToOrgMemberInfo,

    // Metadata about the current logged in user
    user: User,
}

// Metadata about the current logged in user
type User = {
    userId: string

    email: string
    emailConfirmed: boolean,

    hasPassword: boolean,

    username?: string
    firstName?: string,
    lastName?: string,
    pictureUrl?: string,

    locked: boolean,
    enabled: boolean,
    mfaEnabled: boolean,

    createdAt: number,
    lastActiveAt: number,

    legacyUserId?: string
}

Organizations, Roles, and Authorization

Here are more types that you can find in the AuthenticationInfo object

type OrgHelper = {
    // returns all orgs that the user is a member of
    getOrgs: () => OrgMemberInfo[],
    // returns all org ids that the user is a member of
    getOrgIds: () => string[],
    // returns org information for a given orgId
    getOrg: (orgId: string) => OrgMemberInfo | undefined,
    // returns org information for a given org by name
    getOrgByName: (orgName: string) => OrgMemberInfo | undefined,
}

type AccessHelper = {
    isRole: (orgId: string, role: string) => boolean
    isAtLeastRole: (orgId: string, role: string) => boolean
    hasPermission: (orgId: string, permission: string) => boolean
    hasAllPermissions: (orgId: string, permissions: string[]) => boolean
}

type OrgMemberInfo = {
    orgId: string,
    orgName: string,
    urlSafeOrgName: string
    // The role of the user within this organization
    userAssignedRole: string
    userPermissions: string[]
}

Get current user information

authClient.getAuthenticationInfoOrNull(forceRefresh?: boolean): Promise<AuthenticationInfo | null>

If the user is logged in, this method returns authentication information about them, including their access token, user metadata, and, for B2B applications, organization information. See AuthenticationInfo schema for the full schema. Otherwise, this method returns null.

The promise will generally resolve immediately, without making an external request, unless our current access token is stale in which case it will fetch a new one.

If forceRefresh is true, this method will always fetch a new token. The default is false.

Example Usage

You can see a full list of method on the client in our reference. Here's an example which creates signup/login/logout buttons that change based on whether the user is logged in or not.

<div id="display-when-logged-out">
    <button id="signup">Sign Up</button>
    <button id="login">Login</button>
</div>
<div id="display-when-logged-in">
    <button id="account">Account</button>
    <button id="logout">Logout</button>
</div>

<script>
    const client = PropelAuth.createClient({
        authUrl: "https://auth.yourdomain.com", // Change me
        enableBackgroundTokenRefresh: true,
    });

    document.getElementById("signup").onclick = client.redirectToSignupPage;
    document.getElementById("login").onclick = client.redirectToLoginPage;
    document.getElementById("account").onclick = client.redirectToAccountPage;
    document.getElementById("logout").onclick = client.logout;

    client.addLoggedInChangeObserver((isLoggedIn) => {
        if (isLoggedIn) {
            document.getElementById("display-when-logged-in").style.display = "revert";
            document.getElementById("display-when-logged-out").style.display = "none";
        } else {
            document.getElementById("display-when-logged-in").style.display = "none";
            document.getElementById("display-when-logged-out").style.display = "revert";
        }
    });
</script>

You can test by going to your Auth URL and signing up. After logging in, you will see the Account and Logout buttons.

Troubleshooting

If you have any issues seeing the logged-in user, check the FAQ.

Making an authenticated HTTP request

There are a lot of ways to make HTTP requests in Javascript. You could use the Fetch API, XMLHttpRequest, or a library like axios.

Whichever you choose, to make an authenticated request on behalf of your user, you'll need to provide an access token. Access tokens are available from getAuthenticationInfoOrNull. You provide it in the request in the Authorization header, like so:

Authorization: Bearer YOUR_ACCESS_TOKEN

With the Fetch API, this looks like:

function whoAmI(accessToken) {
    return fetch("/whoami", {
        method: "GET",
        headers: {
            "Authorization": `Bearer ${accessToken}`,
        }
    })
}

Next Steps

Done with your frontend? Next you can integrate your backend.