Skip to content

Remix SSO library

Statista 4 apps can use this JS library/package to authenticate Statista users.

Handling logged-in and logged-out users, requiring login for specific actions, or toggling UI elements based on a user’s login state or account type is simpler than it sounds.

This functionality is provided the "@cpe-orga/remix-sso library/package", which is pre-installed with the Remix Stack. It is mocked in your local environment to ensure a seamless developer experience right from the start.

If you provide an endpoint that's not called by frontend (i.e. a server-to-server call), you can use the getUserInfo(accessToken, getConfig(..) function and need to retrieve the accessToken from the remix app that's making the request (e.g. passed in via Authorization header).

Remix Server

The following code shows how to use requireAuth, optionalAuth, and getUser in a Remix loader function. These can only be used in endpoints that are called from the browser since they might return a redirect response. Don't use them in server-to-server calls!.

import { optionalAuth, requireAuth, getUser } from "@cpe-orga/remix-sso/server";

// one remix loader function
export function loader(request) {
  return await optionalAuth(request, async () => {
    const user = getUser();
    if (user) {
      // do something with the user ...
    } else {
      // user is not logged-in
    }
  });
}

// another remix loader function
export function loader(request) {
  // if the user is not logged in this call does redirect the application
  // to the login page
  return await requireAuth(request, async () => {
    const user = getUser();
    // do something with the user ...

    // load additional information about the user
    const userInfo = await user.fetchUserInfo();
  });
}

// another remix loader function
export function loader(request) {
  if (/* force token refresh is required */) {
    return await refreshToken(request, (url) => {
      // update your callback url here... e.g.
      url.searchParams.delete('refresh');
      return url;
    });
  }
}

Server-to-Server Authentication in Protected Environments

Services in our non-production environments (stage or PR feature environments) need to go through an extra layer of authentication so that they are protected from the general internet. For server-to-server calls in these environments, this extra authentication is handled using the X-Stage-Authorization header. When the environment variable ENABLE_APP_AUTHENTICATION_IN_PROTECTED_ENV is set, the library automatically adds the X-Stage-Authorization header to outgoing requests when required, using the dev-env-authenticator authToken() to retrieve a valid token. This mechanism ensures that the Okta authentication used in these environments can be passed without interference.

The ENABLE_APP_AUTHENTICATION_IN_PROTECTED_ENV variable is set automatically in stage and feature environments by remix-tools since version @pit-shared/remix-tools@7.9.1. If you use a different setup, make sure to set this variable accordingly, e.g., by setting it in as environment variable in your GitHub environment.

The AWS account your app is running in must be in the allowed account list for Okta authentication to make this work, see Enable Okta authentication for your AWS account

Client

import { LoginForm, useSso } from "@cpe-orga/remix-sso";

// ... in some react component
const Component = () => {
  const { isLoggedIn } = useSso();
  const location = useLocation();

  return (
    <LoginForm location={location}>
      <button type="submit">{isLoggedIn ? "Logout" : "Login"}</button>
    </LoginForm>
  );
};

Server API

function getUser(options?: { required: true }): User;
function getUser(options?: { required: false }): User | undefined;

function isLoggedIn(request: Request): Promise<boolean>;

function optionalAuth<T extends Response>(
  request: Request,
  action: () => Promise<T>
): Promise<T>;
function requireAuth<T extends Response>(
  request: Request,
  action: () => Promise<T>
): Promise<T>;

Client API

LoginForm

React component to create a from targeting login and logout.

<LoginForm location={location}>
  <button type="submit">Login</button>
</LoginForm>

Props

  • location - Object implementing the ReactRouter (or browser) location API.

WelcomeMessage

React component to greet the logged in user.

<WelcomeMessage />

SsoContextProvider

React component to create a SSO Context for the render tree.

<SsoContextProvider isLoggedIn={false}>{children}</SsoContextProvider>

Props

  • isLoggedIn - Boolean flag if the user is logged in or not. This should be taken from the server. It allows to render the correct state on the server and on the client.

useSso

Hook to return the login data to a calling component. It returns the login state as well as the user object.

Mock Server

A request handler which fakes a sso login context following the required statista sso flow and setting cookies for the user.