Skip to content

Application types

When you register an application, you pick one of five types. The type determines what credentials the platform issues, what OAuth flow it expects, and which fields are relevant.

TypeWhat it isHas a client_secret?Browser-driven?
SPABrowser-only app (React, Vue, etc.)NoYes
Server-sideWeb app with a backend that holds session stateYesYes (callback to backend)
NativeMobile / desktop appNoYes (system browser)
M2M (Machine-to-machine)Backend service calling other backendsYesNo
SAMLService Provider for SAML 2.0 SSOn/a (certificate-based)Yes (POST-binding)

Your app runs entirely in the browser. React, Vue, Svelte, plain JS. Sign-in is browser-redirect to the IntelliAuth tenant; the user comes back to a callback route in your SPA; the SDK exchanges the code for tokens.

  • OAuth flow — authorization code + PKCE.
  • Credentialsclient_id only. No secret (browsers can't keep secrets).
  • Redirect URIs — required. Where the browser comes back.
  • Allowed origins — required for CORS.
  • Refresh tokens — by default, kept in memory + an HttpOnly cookie. Can be moved to localStorage if you accept the XSS risk.

If your stack has a backend that holds the OAuth tokens server-side, use Server-side instead, even if your frontend is React.

A web app where a backend (Node, Go, Python, Ruby) holds the OAuth tokens. The browser just gets a session cookie; tokens never reach the browser.

  • OAuth flow — authorization code, with or without PKCE (PKCE recommended).
  • Credentialsclient_id + client_secret.
  • Redirect URIs — required. Usually a route on the backend (https://app.cymmetri.com/auth/callback).
  • Refresh tokens — stored server-side; the browser never sees them.

This is the safest default for any app with a backend. Use it unless you have a specific reason for SPA.

Mobile (iOS / Android) or desktop apps. The user signs in via the system browser (not an in-app webview), then is bounced back to the app via a custom URI scheme or loopback HTTP listener.

  • OAuth flow — authorization code + PKCE.
  • Credentialsclient_id only. No secret (an app's binary can be decompiled).
  • Redirect URIs — required. Custom scheme (com.cymmetri.banking://callback) or loopback (http://127.0.0.1/callback).
  • Refresh tokens — stored in the platform's secure storage (iOS Keychain, Android Keystore, OS keyring on desktop).

If your "native" app is actually a Capacitor / Cordova / Electron wrapper around a browser SPA, it's still Native — the OAuth shape is the native pattern.

A backend service calling another backend. No human is signing in.

  • OAuth flow — client credentials.
  • Credentialsclient_id + client_secret.
  • Redirect URIs — not applicable.
  • Audience — required. The API the M2M tokens will be used against.
  • Allowed scopes — required. The list of capabilities this service is permitted to request.
  • Refresh tokens — not issued. Get a fresh access token each time the cache expires.

Use M2M for: nightly batch jobs, cron tasks, internal microservices, anything that runs without a user in the loop. Don't use M2M for "the backend of a user-facing web app" — that's Server-side.

A Service Provider for SAML 2.0. Your application accepts SAMLResponse posts from an external IdP (Okta, Entra, etc.) and signs the user in based on the assertion.

  • Protocol — SAML 2.0 (not OAuth).
  • Credentials — certificate-based. Your tenant issues an SP certificate; the IdP issues a separate certificate; you exchange.
  • Settings — entity ID, ACS URL, attribute mapping, JIT provisioning toggle.
  • Tokens — IntelliAuth issues its own session + access token after SAML completes; downstream from there it's OAuth-shaped.

If your application is OAuth/OIDC and just happens to be hosted somewhere that also has SAML, pick SPA / Server-side / Native. SAML is for the case where the SAML protocol itself is the protocol.

  • Browser + no backend → SPA
  • Browser + backend → Server-side
  • Mobile or desktop app → Native
  • Service-to-service, no human → M2M
  • "Our IT team's SSO requires SAML" → SAML

You can change every other field on the application later. Type is the lone exception. Picking right the first time pays back across the application's life.