npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@revolut/sso-miniapp-sdk

v0.3.0

Published

Revolut SSO SDK for Mini Apps

Readme

SSO Mini App SDK

PKCE-based SSO client for Revolut mini apps. The SDK redirects to the SSO server with an app-link challenge, receives an auth code via redirect callback, and exposes the PKCE codeVerifier so the backend can exchange the code for tokens.

Table of Contents

Install

npm install @revolut/sso-miniapp-sdk

Instantiate client

import { RevolutSsoClient } from '@revolut/sso-miniapp-sdk'

const ssoClient = new RevolutSsoClient({
  clientId: 'YOUR_CLIENT_ID',
  mode: 'production', // Required. One of: sandbox' | 'production'
  // locale: 'en',          // Optional. SSO UI locale
  // colorScheme: 'auto',   // Optional. 'light' | 'dark' | 'auto'
  // uiBackground: 'blue',  // Optional. ui-kit-supported background for Transparent mode
})

Update options

ssoClient.updateOptions({
  // locale: 'de',
  // colorScheme: 'light',
  // uiBackground: 'blue',
})

clientId and mode are fixed for the lifetime of the client and cannot be updated.

Authenticate with app link

The mini app receives an appLinkId from the host (Revolut mobile app). Calling authWithAppLink generates a PKCE pair, stores the code verifier, and redirects the browser to the SSO challenge URL. After the challenge is verified, SSO redirects back to redirectUri with code and state query parameters.

ssoClient.authWithAppLink({
  appLinkId: 'YOUR_APP_LINK_ID', // Provided by the host mobile app
  redirectUri: 'CALLBACK_URL',
  // replace: false,                            // Optional. Use window.location.replace instead of assign
  // state: 'YOUR_CLIENT_STATE',                // Optional. Carries client-side info through OIDC. See "Passing client-side state".
  // locale: 'en',                              // Optional. Overrides client locale
  // colorScheme: 'light',                      // Optional. Overrides client colorScheme
  // uiBackground: 'blue',                      // Optional. Overrides client uiBackground
  // extraParams: { app_state: 'foo' },         // Optional. Additional query parameters
})

See Redirect callback for handling the response.

Passing client-side state

The optional state parameter lets you carry arbitrary client-side information through the OIDC round-trip. SSO returns the same value as the state query parameter on the redirect callback, so you can recover context (e.g. the page to return to, a feature flag, an in-progress flow id) that wouldn't otherwise survive the full-page redirect.

State uniqueness

If you don't pass state, the SDK generates a random one. When you pass your own, every value must be unique per authentication attempt.

Treat state as untrusted on the way back: anything sensitive must be looked up from your own storage rather than read from the URL.

Size limit

state is stored alongside the 64-char PKCE verifier in localStorage, with a cookie used as a fallback. When the cookie fallback kicks in, the value is percent-encoded and capped at ~4 KB by the browser's per-cookie size limit. Keep state as short as possible (while still unique); for larger payloads, store the data yourself keyed by state.

const returnTo = window.location.pathname + window.location.search
const flowState = `${crypto.randomUUID()}:${btoa(returnTo)}`

ssoClient.authWithAppLink({
  appLinkId: 'YOUR_APP_LINK_ID',
  redirectUri: 'CALLBACK_URL',
  state: flowState,
})

// Later, on the redirect callback page — read `state` off the result, not the URL
// (processRedirectCallback strips it from window.location):
const result = RevolutSsoClient.processRedirectCallback()
if (result?.status === 'success') {
  const [, encodedReturnTo] = result.state.split(':')
  const returnToPath = encodedReturnTo ? atob(encodedReturnTo) : '/'
}

Redirect callback

RevolutSsoClient provides three static methods to read the callback parameters:

  • processRedirectCallback() — calls readRedirectParams() and then clearRedirectParams(). Use this by default.
  • readRedirectParams() — returns code + codeVerifier + state, or error + errorDescription + state?, without modifying the URL.
  • clearRedirectParams() — removes code, state, error, error_description from the URL and deletes the stored codeVerifier for the returned state.

Return value is one of:

  • SuccessResult{ status: 'success', authCode, codeVerifier, state }
  • ErrorResult{ status: 'error', error, errorDescription?, state? }
  • null — no relevant parameters in the URL

state echoes whatever was passed to authWithAppLink (or the SDK-generated random value if none was passed). It's always present on success; on error it's present whenever the SSO server included a state query param on the callback.

import { RevolutSsoClient } from '@revolut/sso-miniapp-sdk'

const result = RevolutSsoClient.processRedirectCallback()

if (result === null) {
  // No callback parameters in the URL
  return
}

if (result.status === 'error') {
  reportError({
    error: result.error,
    description: result.errorDescription,
  })
  return
}

// Exchange code + codeVerifier at your backend for tokens
await fetch('/api/sso/exchange', {
  method: 'POST',
  body: JSON.stringify({
    code: result.authCode,
    codeVerifier: result.codeVerifier,
  }),
})

Possible error values from readRedirectParams

In addition to server-provided OAuth errors (e.g. access_denied) the SDK can return:

  • code_verifier_not_foundcode and state are in the URL, but no stored verifier matches the state (e.g. localStorage / cookies were cleared between redirect and callback).
  • state_not_foundcode is in the URL but state is missing entirely.

Back to top