OAuth 2.0
OAuth Authentication
Secure delegated access for your applications. Support for Authorization Code with PKCE, Client Credentials, and Device Authorization flows.
PKCE required
Token rotation
Granular scopes
Supported Flows
Authorization Code + PKCE
RecommendedSPAs, Mobile apps, CLI tools
high security
Client Credentials
Server-to-server, Machine accounts
high security
Device Authorization
Smart TVs, IoT devices
medium security
Available Scopes
| Scope | Description | Permissions |
|---|---|---|
valuate:read | Read valuation results | Get valuationsList history |
valuate:write | Create valuations | Create valuationsBatch processing |
webhooks:manage | Manage webhooks | Create webhooksDelete webhooks |
organization:read | Read org info | View membersView settings |
organization:admin | Admin organization | Invite membersChange settings |
billing:read | View billing | View invoicesView usage |
Implementation Guide
Step 1-2: Generate PKCE & Authorize
// Step 1: Generate PKCE challenge
import crypto from 'crypto';
function generateCodeVerifier() {
return crypto.randomBytes(32).toString('base64url');
}
function generateCodeChallenge(verifier: string) {
return crypto
.createHash('sha256')
.update(verifier)
.digest('base64url');
}
const codeVerifier = generateCodeVerifier();
const codeChallenge = generateCodeChallenge(codeVerifier);
// Step 2: Redirect to authorization
const authUrl = new URL('https://auth.justkalm.com/authorize');
authUrl.searchParams.set('client_id', 'YOUR_CLIENT_ID');
authUrl.searchParams.set('redirect_uri', 'https://yourapp.com/callback');
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('scope', 'valuate:read valuate:write');
authUrl.searchParams.set('code_challenge', codeChallenge);
authUrl.searchParams.set('code_challenge_method', 'S256');
authUrl.searchParams.set('state', crypto.randomBytes(16).toString('hex'));
// Redirect user to authUrl.toString()Step 3: Exchange Code for Tokens
// Step 3: Exchange code for tokens
const response = await fetch('https://auth.justkalm.com/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
client_id: 'YOUR_CLIENT_ID',
code: authorizationCode, // From callback URL
redirect_uri: 'https://yourapp.com/callback',
code_verifier: codeVerifier, // From step 1
}),
});
const tokens = await response.json();
// {
// access_token: "eyJhbGci...",
// refresh_token: "dGhpcyBpcyBh...",
// token_type: "Bearer",
// expires_in: 3600,
// scope: "valuate:read valuate:write"
// }Refresh Tokens
// Refresh expired access tokens
const response = await fetch('https://auth.justkalm.com/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'refresh_token',
client_id: 'YOUR_CLIENT_ID',
refresh_token: storedRefreshToken,
}),
});
const newTokens = await response.json();
// Store the new access_token and refresh_tokenSecurity Best Practices
Always Use PKCE
PKCE is required for all public clients (SPAs, mobile apps). It prevents authorization code interception attacks.
Validate State Parameter
Always verify the state parameter matches to prevent CSRF attacks. Generate cryptographically random state values.
Secure Token Storage
Store tokens securely. Use httpOnly cookies or secure storage. Never expose tokens in URLs or localStorage in production.
Minimal Scopes
Request only the scopes you need. Users can see requested permissions and are more likely to approve minimal access.
Create OAuth Application
Register your application to get client credentials.