Authenticate M2M clients
This guide explains how your application can validate API requests from Machine-2-Machine (M2M) clients using Scalekit’s M2M authentication system. This guide explains the authentication flow, from obtaining access tokens to validating requests using JSON Web Key Sets (JWKS).
How M2M clients authenticate with your API
Section titled “How M2M clients authenticate with your API”Every Scalekit environment functions as an Authorization Server. M2M clients authenticate using client credentials with this server.
Storing client credentials
Section titled “Storing client credentials”M2M clients must securely store their credentials in environment variables:
YOURAPP_ENVIRONMENT_URL="<YOURAPP_SCALEKIT_ENVIRONMENT_URL>"YOURAPP_CLIENT_ID="<YOURAPP_CLIENT_ID>"YOURAPP_CLIENT_SECRET="<YOURAPP_CLIENT_SECRET>"
Obtaining access tokens
Section titled “Obtaining access tokens”To authenticate API requests, clients must first obtain an access token from your authorization server using the Token endpoint:
https://<YOURAPP_SCALEKIT_ENVIRONMENT_URL>/oauth/token
The client sends their credentials to this endpoint:
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
env_url = os.environ['YOURAPP_SCALEKIT_ENVIRONMENT_URL']
def get_m2m_access_token(): """Request an access token for M2M client authentication.""" 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_token
The 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 the access token, clients include it in the Authorization header of their API requests:
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" | jq
const express = require('express');const jwt = require('jsonwebtoken');const jwksClient = require('jwks-rsa');const app = express();
// Initialize JWKS clientconst client = jwksClient({ jwksUri: `https://<YOURAPP_ENVIRONMENT_URL>/keys`});
// Function to get signing keyfunction 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 JWTfunction validateJwt(req, res, next) { // Extract token from header 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 token jwt.verify(token, getKey, { algorithms: ['RS256'] }, (err, decoded) => { if (err) { return res.status(401).json({ error: 'Invalid token', details: err.message }); }
// Add decoded token to request object req.user = decoded; next(); });}
// Apply middleware to protected routesapp.use('/api', validateJwt);
// Example protected routeapp.get('/api/data', (req, res) => { res.json({ message: 'Authenticated successfully', userId: req.user.sub });});
app.listen(3000, () => { console.log('Server running on port 3000');});
# Validate token and get claims using Scalekit SDKclaims = scalekit_client.validate_access_token_and_get_claims( token="<M2M_CLIENT_ACCESS_TOKEN>" )
SDK support status
Section titled “SDK support status”Our Python SDK currently includes support for M2M authentication. The support to verify tokens is coming soon to Node, Java, and Go SDKs.