@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
- Instantiate client
- Update options
- Authenticate with app link
- Passing client-side state
- Redirect callback
Install
npm install @revolut/sso-miniapp-sdkInstantiate 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()— callsreadRedirectParams()and thenclearRedirectParams(). Use this by default.readRedirectParams()— returnscode+codeVerifier+state, orerror+errorDescription+state?, without modifying the URL.clearRedirectParams()— removescode,state,error,error_descriptionfrom the URL and deletes the storedcodeVerifierfor the returnedstate.
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_found—codeandstateare in the URL, but no stored verifier matches thestate(e.g. localStorage / cookies were cleared between redirect and callback).state_not_found—codeis in the URL butstateis missing entirely.
