The 2-tag SSO setup (no backend required)

Load the SDK, link to the provider. Sign users in from a static site without a server or client secret.

· LoginWith team

The simplest possible SSO integration is two HTML tags. A script tag to load the SDK, and a link that points at the provider. No backend, no client secret, no OAuth app registration on your side. Here’s how it works.

The two tags

<script src="https://acme.loginwith.dev/cdn/sdk-latest" defer></script>

<a href="https://google.loginwith.link">Sign in with Google</a>

That’s the whole implementation. Drop those on a landing page or a SPA, and clicking the link signs the user in — PKCE, session storage, callback handling — all handled by the SDK without a byte of code from you.

What the SDK handles

  • PKCE: generates the code verifier, stores it, sends the challenge
  • State parameter: generates, stores, validates on callback
  • Redirect URI: back to your origin, any path you want
  • Token exchange: calls the token endpoint, gets back the ID token + access token
  • Session storage: stores tokens in a way that balances security (no localStorage for refresh tokens) and usability (persists across reloads)
  • JWKS validation: verifies the ID token signature against the provider’s public keys

All of that is boilerplate that otherwise consumes 200-500 lines of frontend code. The two-tag setup replaces it with two tags.

What you do

Once the user is signed in, you can:

// Read the current user
const user = await loginwith.getUser()

// Get an access token for API calls
const token = await loginwith.getAccessToken()

// Attach it to your API calls
fetch('/api/data', {
  headers: { Authorization: `Bearer ${token}` }
})

// Sign out
await loginwith.signOut()

When this works

  • Static sites (Astro, Next.js static export, plain HTML)
  • SPAs without a backend
  • Landing pages with a “try it” button
  • Prototypes and MVPs

When you outgrow it

At some point you’ll want a backend. Common reasons:

  • You need server-side sessions (e.g. for SSR)
  • You need to call third-party APIs with secrets you don’t want in the browser
  • You want to verify tokens server-side for audit logs

At that point, the same SDK flow works — the frontend still handles PKCE and gets the token; your backend validates the token on each API call. No rewrite required.

The philosophical point

Authentication should be the lowest-friction part of shipping a product, not the highest. “Drop in two tags” is the ceiling of how easy it can be. Any more complexity is architecture you’ve chosen, not complexity inherent to auth.

Want auth that just works?

Get started with LoginWith