Maru sign-in in your own app
Let people sign in to your own website, web app or backend with their Maru account: register an app, run PKCE sign-in, verify identity on your server and save presets.
Simpler on Maru. If this is a Maru module, you don't need any of this. On Maru the account button, consent, presets and auto-connect come with
FaceModuleNavbar, andmaru dev --sign-inlets you build it offline. See Maru sign-in in a module. It's free to start, and there's no callback, session or secret to manage.
Use this page when your product runs outside Maru and you want people to connect their Maru account to it. Your app sends them to Maru to sign in and approve, and gets back a session it owns.
1. Register your app
Open Creator apps and create an app:
- Name: shown on the consent page ("Sign in to your app").
- Callbacks: the exact HTTPS addresses Maru may return to, such as
https://example.com/auth/maru/callback. Fixed-porthttp://localhostcallbacks are allowed for development. - Permissions: start with identity. Add presets or generation only if you use them.
Copy the generated configuration. It contains public identifiers only, no secret.
2. Sign people in from the browser
import {
createCreatorAppSession,
createCreatorAppAttemptStore,
} from "maruaudio/api"
const session = createCreatorAppSession({
config, // from Creator apps: issuer, clientId, redirectUri, scopes
mode: "browser",
attemptStore: createCreatorAppAttemptStore(config, sessionStorage),
})
// On your "Sign in with Maru" button:
location.assign(await session.beginSignIn())
// On the exact registered callback page:
await session.completeSignIn(location.href)
history.replaceState(null, "", config.redirectUri)
Browser mode keeps tokens in memory only, so a reload signs out. That is
deliberate: tokens are never copied to localStorage or cookies for you.
3. Prefer a server session when you have a backend
With a backend, run the session in server mode. Keep one session per signed-in
browser, store its tokens server-side, and give the browser only your own
HttpOnly, Secure, SameSite=Lax cookie. Never send refresh credentials to
the browser. A server-mode session may also use a client secret from Creator
apps; Maru refuses a secret sent from a browser.
To check who is calling your API, verify the access token online:
import { verifyCreatorAppIdentity } from "maruaudio/api"
const who = await verifyCreatorAppIdentity({ issuer, clientId, accessToken })
// who.subject is stable for this person in your app only.
The subject is not an email or a global account id, and it differs between apps. Decoding a token yourself is not verification.
4. Save presets (optional)
With the presets permissions and a registered module id:
import { createCreatorAppDataClient } from "maruaudio/api"
const app = createCreatorAppDataClient({ config, session })
const presets = await app.listPresets("com.example.my-synth")
await session.signOut() // or signOut({ revokeGrant: true }) to disconnect
What people see
People approve your app once on Maru's consent page and can disconnect it in Connected apps. Apps that only sign in and save presets to an HTTPS callback can offer Connect automatically next time. Localhost callbacks and apps that spend credits always ask.
Related
- Generation from your own server
- Add Maru sign-in to your product: the person's side of the connection.
- Self-hosting overview