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.
Storing client credentials
Section titled “Storing client credentials”Your customers’ applications securely store the credentials you issued to them in environment variables. This example shows how their applications would store these credentials:
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).
Obtaining access tokens
Section titled “Obtaining access tokens”Your customers’ applications obtain access tokens from your Scalekit authorization server before making API requests. They send their credentials to your token endpoint:
https://<YOURAPP_SCALEKIT_ENVIRONMENT_URL>/oauth/tokenHere’s how your customers’ applications request access tokens:
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"import osimport jsonimport requests
# Customer's application configurationenv_url = os.environ['YOURAPP_SCALEKIT_ENVIRONMENT_URL']
def get_m2m_access_token(): """ Customer's application requests an access token using client credentials. This token will be used to authenticate API requests to your platform. """ headers = {"Content-Type": "application/x-www-form-urlencoded"} params = { "grant_type": "client_credentials", "client_id": os.environ['YOURAPP_SCALEKIT_CLIENT_ID'], "client_secret": os.environ['YOURAPP_SCALEKIT_CLIENT_SECRET'], "scope": "openid profile email" }
response = requests.post( url=f"{env_url}/oauth/token", headers=headers, data=params, verify=True )
access_token = response.json().get('access_token') return access_tokenYour authorization server returns a JSON response containing the access token:
{ "access_token": "<YOURAPP_ACCESS_TOKEN>", "token_type": "Bearer", "expires_in": 86399, "scope": "openid"}| Field | Description |
|---|---|
access_token | Token for authenticating API requests |
token_type | Always “Bearer” for this flow |
expires_in | Token validity period in seconds (typically 24 hours) |
scope | Authorized scopes for this token |
Using access tokens
Section titled “Using access tokens”After obtaining an access token, your customers’ applications include it in the Authorization header when making requests to your API:
curl --request GET "https://<your-api-endpoint>" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer <YOURAPP_ACCESS_TOKEN>"Validating access tokens
Section titled “Validating access tokens”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.
Retrieving JWKS
Section titled “Retrieving JWKS”Your application should fetch the public keys from the JWKS endpoint:
https://<YOURAPP_ENVIRONMENT_URL>/keys{ "keys": [ { "use": "sig", "kty": "RSA", "kid": "snk_58327480989122566", "alg": "RS256", "n": "wUaqIj3pIE_zfGN9u4GySZs862F-0Kl-..", "e": "AQAB" } ]}Token validation process
Section titled “Token validation process”When your API receives a request with a JWT, follow these steps:
- Extract the token from the Authorization header
- Fetch the JWKS from the endpoint
- Use the public key from JWKS to verify the token’s signature
- Validate the token’s claims (issuer, audience, expiration)
This example shows how to fetch JWKS data:
curl -s "https://<YOURAPP_ENVIRONMENT_URL>/keys" | jqconst 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 environmentconst client = jwksClient({ jwksUri: `https://<YOURAPP_ENVIRONMENT_URL>/keys`});
// Function to get signing key for token verificationfunction 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 applicationfunction 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 routesapp.use('/api', validateJwt);
// Example protected API endpointapp.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');});9 collapsed lines
from scalekit import ScalekitClientimport os
# Initialize Scalekit SDK to validate tokens from customer applicationsscalekit_client = ScalekitClient( env_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"), client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"))
def validate_api_request(request): """ Validate access token from customer's API client application. Your API uses this to authorize requests from customer applications. """ # Extract token sent by customer's application auth_header = request.headers.get('Authorization') if not auth_header or not auth_header.startswith('Bearer '): return None, "Missing authorization token"
token = auth_header.split(' ')[1]
try: # Validate token and extract claims using Scalekit SDK claims = scalekit_client.validate_access_token_and_get_claims( token=token )
# Token is valid - return claims for authorization logic return claims, None except Exception as e: return None, f"Invalid token: {str(e)}"
# Example: Use in your Flask API endpoint@app.route('/api/data', methods=['GET'])def get_data(): claims, error = validate_api_request(request)
if error: return {"error": error}, 401
# Customer application is authenticated return { "message": "Customer application authenticated successfully", "userId": claims.get("sub") }SDK support status
Section titled “SDK support status”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.