EAuth docs

EAuth

JavaScript SDK

Two packages. The core does the protocol and depends on nothing; the React package is a thin bridge to component state.

npm install @elchi/eauth-react

React

import {
  EAuthProvider, SignedIn, SignedOut, SignInButton, useEAuth,
} from "@elchi/eauth-react";

export default function App() {
  return (
    <EAuthProvider clientId="eauth_pub_..." redirectUri={location.origin + "/"}>
      <SignedOut><SignInButton /></SignedOut>
      <SignedIn><Profile /></SignedIn>
    </EAuthProvider>
  );
}

function Profile() {
  const { user, signOut } = useEAuth();
  return (
    <>
      <p>Hello {user.name}</p>
      <button onClick={() => signOut()}>Sign out</button>
    </>
  );
}

That is the whole integration. The provider handles the redirect on load, verifies the response, and keeps the session refreshed.

Calling your own API

const { getAccessToken } = useEAuth();

const response = await fetch("/api/orders", {
  headers: { Authorization: `Bearer ${await getAccessToken()}` },
});

getAccessToken refreshes when the current token is close to expiring, so you never have to check yourself.

Without a framework

import { EAuth } from "@elchi/eauth";

const auth = new EAuth({
  clientId: "eauth_pub_...",
  redirectUri: location.origin + "/",
});

// Safe on every load: returns null when the URL carries no response.
const user = await auth.handleRedirect() ?? auth.getUser();

if (!user) await auth.signIn();

What the SDK does that a tutorial would not

No client secret anywhere. A browser cannot keep one. If you want to pass one, the client is registered as the wrong type.

Tokens in memory by default. A token in localStorage is readable by any script on the page, so one cross-site scripting bug in any dependency hands over the session. The default keeps tokens in a closure and signs the user in again silently after a reload. storage: "local" is available once you have accepted that trade.

state, nonce and iss are all verified, and a mismatch throws rather than warns. These are the three checks integrations most often skip. The iss check is RFC 9207 and is what stops a mix-up attack when your application talks to more than one provider.

One refresh at a time. Concurrent callers share a single refresh. Without that, five components mounting at once each start their own, and because refresh tokens rotate, four of them present a token that has already been rotated. The server correctly reads that as a stolen token and revokes the whole chain, signing your user out for no reason.

Errors

Everything throws EAuthError with a code you can branch on.

Code Meaning
state_mismatch The response did not come from a sign-in started in this browser
issuer_mismatch The response or token came from a different server
nonce_mismatch The ID token belongs to a different sign-in
no_pending_request The redirect was opened in a different tab
pkce_unsupported The server does not advertise S256

Self-hosting

Pass issuer pointing at your own deployment. Everything else is discovered from /.well-known/openid-configuration, so no other URL is hardcoded.

3 min read · Elchi Studios, Zug · Terms