Quickstart
Register an application and complete your first sign in.
1. Register your application
Create an application in Account settings, Developers tab. An Amped.Bio account is required. You will get a
client_id, and a client_secret shown only once.
Rules for redirect URIs:
Webapplications requirehttpsredirect URIs.Nativeapplications may usehttp://localhost:<port>/...while developing.
2. Add the sign in button
Send the user to the authorization endpoint. Generate and store a state and a PKCE verifier first.
// Base64url without padding (RFC 7636)
function base64UrlEncode(bytes) {
let binary = "";
for (const byte of new Uint8Array(bytes)) binary += String.fromCharCode(byte);
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
// 32 random bytes give a 43 character verifier
const verifier = base64UrlEncode(crypto.getRandomValues(new Uint8Array(32)));
const challenge = base64UrlEncode(
await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier))
);
const state = base64UrlEncode(crypto.getRandomValues(new Uint8Array(16)));
sessionStorage.setItem("pkce_verifier", verifier);
sessionStorage.setItem("oauth_state", state);
const params = new URLSearchParams({
client_id: "YOUR_CLIENT_ID",
redirect_uri: "https://your-app.example.com/callback",
response_type: "code",
scope: "openid profile email",
state,
code_challenge: challenge,
code_challenge_method: "S256",
});
window.location.href = `https://auth.amped.bio/oauth2/authorize?${params}`;The user signs in and, unless you are a trusted first party client, sees a consent screen listing the scopes you asked for.
3. Exchange the code
Back on your redirect_uri, compare state with the value you stored, then exchange code at the token
endpoint.
const callback = new URLSearchParams(window.location.search);
if (callback.get("state") !== sessionStorage.getItem("oauth_state")) {
throw new Error("State does not match. Start the sign in again.");
}
const code = callback.get("code");
const codeVerifier = sessionStorage.getItem("pkce_verifier");curl -sS https://auth.amped.bio/oauth2/token \
-H "content-type: application/x-www-form-urlencoded" \
-d grant_type=authorization_code \
-d code=CODE_FROM_CALLBACK \
-d redirect_uri=https://your-app.example.com/callback \
-d client_id=YOUR_CLIENT_ID \
-d client_secret=YOUR_CLIENT_SECRET \
-d code_verifier=YOUR_PKCE_VERIFIERThe response contains an access_token (valid for 15 minutes), an id_token when openid was requested,
and a refresh_token when offline_access was requested.
4. Read the user profile
curl -sS https://auth.amped.bio/oauth2/userinfo \
-H "authorization: Bearer ACCESS_TOKEN"{
"sub": "42",
"name": "Ada Lovelace",
"given_name": "Ada",
"family_name": "Lovelace",
"picture": "https://cdn.amped.bio/ada.png",
"wallet": "0x7a3f00000000000000000000000000000000c91e",
"email": "ada@example.com",
"email_verified": true
}5. Refresh when the access token expires
curl -sS https://auth.amped.bio/oauth2/token \
-H "content-type: application/x-www-form-urlencoded" \
-d grant_type=refresh_token \
-d refresh_token=YOUR_REFRESH_TOKEN \
-d client_id=YOUR_CLIENT_ID \
-d client_secret=YOUR_CLIENT_SECRETRefresh tokens rotate: store the new one from every response.
Using Better Auth
If your application already uses Better Auth (opens in a new tab), add us as a social provider:
import { betterAuth } from "better-auth";
export const auth = betterAuth({
plugins: [],
socialProviders: {
"amped-bio": {
clientId: process.env.AMPED_CLIENT_ID!,
clientSecret: process.env.AMPED_CLIENT_SECRET!,
authorizationEndpoint: "https://auth.amped.bio/oauth2/authorize",
tokenEndpoint: "https://auth.amped.bio/oauth2/token",
userInfoEndpoint: "https://auth.amped.bio/oauth2/userinfo",
scopes: ["openid", "profile", "email"],
},
},
});See Integrations for framework specific snippets.