Skip to content

Authenticate customer apps

Use Scalekit to implement OAuth for customer apps. Issue tokens and validate API requests with JWKS

This guide explains how you enable API authentication for your customers’ applications using Scalekit’s OAuth 2.0 client credentials flow. When your customers build applications that need to access your API, they use client credentials registered through your Scalekit environment to obtain access tokens. Your API validates these tokens to authorize their requests using JWKS.

How your customers’ applications authenticate with your API

Section titled “How your customers’ applications authenticate with your API”

Your Scalekit environment functions as an OAuth 2.0 Authorization Server. Your customers’ applications authenticate using the client credentials flow, exchanging their registered client ID and secret for access tokens that authorize API requests to your platform.

Your customers’ applications securely store the credentials you issued to them in environment variables. This example shows how their applications would store these credentials:

Environment variables in customer's application
YOURAPP_ENVIRONMENT_URL="<YOURAPP_SCALEKIT_ENVIRONMENT_URL>"
YOURAPP_CLIENT_ID="<YOURAPP_CLIENT_ID>"
YOURAPP_CLIENT_SECRET="<YOURAPP_CLIENT_SECRET>"

These credentials are obtained when you register an API client for your customer (see the quickstart guide for client registration).

Your customers’ applications obtain access tokens from your Scalekit authorization server before making API requests. They send their credentials to your token endpoint:

Token endpoint
https://<YOURAPP_SCALEKIT_ENVIRONMENT_URL>/oauth/token

Here’s how your customers’ applications request access tokens:

Terminal window
curl -X POST \
"https://<YOURAPP_SCALEKIT_ENVIRONMENT_URL>/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=<YOURAPP_CLIENT_ID>" \
-d "client_secret=<YOURAPP_CLIENT_SECRET>" \
-d "scope=openid profile email"

Your authorization server returns a JSON response containing the access token:

Token response
{
"access_token": "<YOURAPP_ACCESS_TOKEN>",
"token_type": "Bearer",
"expires_in": 86399,
"scope": "openid"
}
FieldDescription
access_tokenToken for authenticating API requests
token_typeAlways “Bearer” for this flow
expires_inToken validity period in seconds (typically 24 hours)
scopeAuthorized scopes for this token

After obtaining an access token, your customers’ applications include it in the Authorization header when making requests to your API:

Customer's application making an API request
curl --request GET "https://<your-api-endpoint>" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <YOURAPP_ACCESS_TOKEN>"

Your API server must validate access tokens before processing requests. Scalekit uses JSON Web Tokens (JWTs) signed with RSA keys, which you validate using the JSON Web Key Set (JWKS) endpoint.

Your application should fetch the public keys from the JWKS endpoint:

JWKS endpoint
https://<YOURAPP_ENVIRONMENT_URL>/keys
JWKS response
{
"keys": [
{
"use": "sig",
"kty": "RSA",
"kid": "snk_58327480989122566",
"alg": "RS256",
"n": "wUaqIj3pIE_zfGN9u4GySZs862F-0Kl-..",
"e": "AQAB"
}
]
}

When your API receives a request with a JWT, follow these steps:

  1. Extract the token from the Authorization header
  2. Fetch the JWKS from the endpoint
  3. Use the public key from JWKS to verify the token’s signature
  4. Validate the token’s claims (issuer, audience, expiration)

This example shows how to fetch JWKS data:

Fetch JWKS with cURL
curl -s "https://<YOURAPP_ENVIRONMENT_URL>/keys" | jq
Express.js
const express = require('express');
const jwt = require('jsonwebtoken');
const jwksClient = require('jwks-rsa');
const app = express();
// Initialize JWKS client to validate tokens from customer applications
// This fetches public keys from your Scalekit environment
const client = jwksClient({
jwksUri: `https://<YOURAPP_ENVIRONMENT_URL>/keys`
});
// Function to get signing key for token verification
function getKey(header, callback) {
client.getSigningKey(header.kid, function(err, key) {
if (err) return callback(err);
const signingKey = key.publicKey || key.rsaPublicKey;
callback(null, signingKey);
});
}
// Middleware to validate JWT from customer's API client application
function validateJwt(req, res, next) {
// Extract token sent by customer's application
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({ error: 'Missing authorization token' });
}
const token = authHeader.split(' ')[1];
// Verify the token signature using JWKS
jwt.verify(token, getKey, {
algorithms: ['RS256']
}, (err, decoded) => {
if (err) {
return res.status(401).json({ error: 'Invalid token', details: err.message });
}
// Token is valid - add decoded claims to request
req.user = decoded;
next();
});
}
// Apply validation middleware to your API routes
app.use('/api', validateJwt);
// Example protected API endpoint
app.get('/api/data', (req, res) => {
res.json({
message: 'Customer application authenticated successfully',
userId: req.user.sub
});
});
app.listen(3000, () => {
console.log('API server running on port 3000');
});

The Python SDK includes built-in methods for token validation (validate_access_token_and_get_claims). For Node.js, Go, and Java, you can use standard JWT libraries with the JWKS endpoint as shown in the examples above. Native SDK support for token validation is coming soon to these SDKs.