How this works

Northwind Gym is a static website with no server. It uses the Unidy JavaScript SDK for every step below. The full guide is in the Unidy developer guide.

  1. Register the website

    In your business Unidy, open Developers and register the website. Choose In the browser, add https://test.unidy.com/callback.html as the redirect address, and tick the details it may ask for. Unidy gives you a client id; a website in the browser never gets a secret.

  2. Configure the SDK

    js/config.js holds the three settings. main.js starts the SDK with them.

    // js/config.js
    export default {
      clientId: 'YOUR_CLIENT_ID',
      redirectUri: `${location.origin}/callback.html`,
      issuer: 'https://id.unidy.com',
    };
    
    // js/main.js
    import * as Unidy from '@unidy/js';
    import config from './config.js';
    
    const unidy = Unidy.init({ ...config, scopes: ['profile', 'email'] });
  3. Sign up and log in: the button

    Both offer the same button. Unidy shows the person what the website asks for, with Allow, Allow once and Deny.

    unidy.button(document.getElementById('sign-up-button'), {
      kind: 'continue',
      scopes: ['profile', 'email'],
    });
  4. Back from Unidy: callback.html

    The SDK checks the state, exchanges the code with the PKCE verifier, and checks the ID token's signature, issuer, audience, expiry and nonce. The private identifier sub is the same every time this person comes to this website, so it is the member's key.

    try {
      const { user, kind } = await unidy.handleRedirect();
      const { isNew } = members.welcome(user.sub, user);
      flash.set(isNew ? 'Welcome, your membership is created.' : 'Welcome back.');
      location.assign('members.html');
    } catch (error) {
      if (error.code === 'access_denied') {
        flash.set('You chose Deny, so Unidy shared nothing with Northwind Gym.');
      }
    }
  5. Link your Unidy: fill the details

    The members page asks for more details. link() adds offline_access, so with Allow the website may read them again later.

    unidy.button(document.getElementById('link-button'), {
      kind: 'link',
      scopes: ['profile', 'email', 'phone', 'address', 'birthdate'],
    });
    
    // on callback.html, when kind is 'link'
    members.fromUnidy(user.sub, user);
  6. Get the latest from Unidy

    details() reads /api/v1/me and renews the access token when it has expired. After Allow once, or when the person disconnected the website in their Unidy, it fails with not_linked.

    try {
      const changed = members.fromUnidy(user.sub, await unidy.details());
    } catch (error) {
      if (error.code === 'not_linked') members.setLinked(user.sub, false);
    }
  7. Sign out

    The SDK forgets the tokens and revokes the refresh token at Unidy. The member stays in the gym's list.

    await unidy.signOut();

The members list lives in this browser's localStorage, keyed by sub. A real website keeps it in its own database.