Overview
Official Base IdP SDKs for every supported language and runtime. One mental model, one API shape across all of them.
Base IdP ships first-class SDKs for every language Square products use. They all do the same thing in roughly the same shape: read config from env, resolve the rest from the client registration, cache public keys, and expose a verify function that returns a typed principal.
Picking the right SDK is mostly a question of picking the right language for the part of your stack you are integrating. The shape of the API will feel familiar regardless.
Pick your language
TypeScript
Browser, React, Next.js, SvelteKit, Vite, Node, NestJS, Express.
Go
Verifier and net/http middleware for backends and gateways.
Rust
Offline PASETO verification for services and gateways.
Flutter / Dart
Mobile PKCE login for iOS and Android.
Swift / SwiftUI
Native PKCE login for iOS, iPadOS, macOS, and visionOS.
Laravel / PHP
Confidential server integration for PHP applications.
The shape every SDK shares
If you have used one SDK you can read the others almost immediately. The mental model is identical.
Config from env
Every SDK has a "build config from environment" helper. You do not construct the config object by hand.
const client = new BaseIdPServerClient({
clientId: process.env.BASE_IDP_CLIENT_ID,
});client := baseidp.MustNew(baseidp.ConfigFromEnv())let client = Client::new(Config::from_env()?)?;final config = BaseIdpConfig.fromEnvironment();Authorize / login
For frontends: build the authorize URL or open the system browser.
await auth.loginWithRedirect();final session = await auth.login();Verify
For backends: hand in a token, get a principal.
const principal = await client.verifyAccessToken(token);principal, err := client.VerifyAccessToken(ctx, token, baseidp.VerifyOptions{})let principal = client.verify_access_token(token, VerifyOptions::default()).await?;That is the whole API surface for most integrations. Login on the frontend, verify on the backend.
Which SDK runs the login
The login lives on the side that runs the browser or the system webview. For mobile, that is the device — Flutter and Dart SDKs handle it. For an SPA, that is the browser — the TypeScript browser SDK. For a server-rendered web app, that is the server — the TypeScript Next.js or server adapter.
The backend SDK does not run the login on its own. It verifies tokens. The two SDKs do different jobs, which is why most apps end up using two.
This is exactly how Google, Firebase, Auth0, Clerk, and Supabase all ship — two SDKs per app, one per side. If you end up needing two languages, that is your architecture choice (a Flutter app talking to a Go backend), not a Base IdP imposition.
Versioning
All SDKs follow semver. The major versions track Base IdP's API compatibility. The current major is 1.x and is the only supported track.
npm install base-idp@^1
cargo add base-idp@^1
go get github.com/squareexp/base-idp/sdk/go
flutter pub add base_idp
composer require squareexp/base-idp:^1Breaking changes are rare and always announced in the changelog before they ship. Minor releases add features. Patch releases fix bugs.