API Authentication quickstart
Add secure authentication to your APIs
Learn how to add authentication to your APIs in minutes. This guide shows you how to:
- Register API clients that need to access your services
- Set up OAuth 2.0 authentication using client credentials
- Validate access tokens to ensure only authorized clients can call your APIs
Who is this for? This guide is for developers who want to secure their APIs and control which external systems can access them.
Prerequisites:
- A Scalekit account (sign up here if you don’t have one)
- Basic understanding of REST APIs
- Familiarity with OAuth 2.0 (optional)
npm install @scalekit-sdk/node
pip install scalekit-sdk-python
go get -u github.com/scalekit-inc/scalekit-sdk-go
/* Gradle users - add the following to your dependencies in build file */implementation "com.scalekit:scalekit-sdk-java:1.1.3"
<!-- Maven users - add the following to your `pom.xml` --><dependency> <groupId>com.scalekit</groupId> <artifactId>scalekit-sdk-java</artifactId> <version>1.1.3</version></dependency>
-
Register an API client
Section titled “Register an API client”Before an application can access your API, you need to register it as a client. This creates secure credentials that the app developers will use to authenticate its API requests.
When you register a client, you’ll receive a unique client ID and secret - similar to a username and password for applications. Present it to your API client developers to use in their code.
POST /organizations/{organization_id}/clients # For authentication details, see: http://docs.scalekit.com/apis#description/authenticationcurl -L 'https://<SCALEKIT_ENVIRONMENT_URL>/api/v1/organizations/<ORGANIZATION_ID>/clients' \-H 'Content-Type: application/json' \-H 'Authorization: Bearer <SCALEKIT_ACCESS_TOKEN>' \-d '{"name": "GitHub Actions Deployment Service","description": "Service account for GitHub Actions to deploy applications to production","custom_claims": [{"key": "github_repository","value": "acmecorp/inventory-service"},{"key": "environment","value": "production_us"}],"scopes": ["deploy:applications","read:deployments"],"audience": ["deployment-api.acmecorp.com"],"expiry": 3600}'from scalekit.v1.clients.clients_pb2 import OrganizationClientorg_id = "<SCALEKIT_ORGANIZATION_ID>"api_client = OrganizationClient(name="GitHub Actions Deployment Service",description="Service account for GitHub Actions to deploy applications to production",custom_claims=[{"key": "github_repository","value": "acmecorp/inventory-service"},{"key": "environment","value": "production_us"}],scopes=["deploy:applications", "read:deployments"],audience=["deployment-api.acmecorp.com"],expiry=3600)response = scalekit_client.m2m_client.create_organization_client(organization_id=org_id,m2m_client=api_client)API client registration parameters
Parameter Type Description name
string
A descriptive name for the API client (e.g., “GitHub Actions Deployment Service”) description
string
A detailed explanation of the client’s purpose and usage custom_claims
array
Key-value pairs that provide additional context about the client. Each claim must have a key
andvalue
fieldscopes
array
List of permissions the client needs (e.g., [“deploy:applications”, “read:deployments”]) audience
array
List of API endpoints this client will access (e.g., [“deployment-api.acmecorp.com”]) expiry
number
Token expiration time in seconds. Defaults to 3600 (1 hour) The API response contains the client details, including the
client_id
andclient_secret
.Register an API client API response {"client": {"client_id": "m2morg_68315758685323697","secrets": [{"id": "sks_68315758802764209","create_time": "2025-04-16T06:56:05.360Z","update_time": "2025-04-16T06:56:05.367190455Z","secret_suffix": "UZ0X","status": "ACTIVE","last_used_time": "2025-04-16T06:56:05.360Z"}],"name": "GitHub Actions Deployment Service","description": "Service account for GitHub Actions to deploy applications to production","organization_id": "org_59615193906282635","create_time": "2025-04-16T06:56:05.290Z","update_time": "2025-04-16T06:56:05.292145150Z","scopes": ["deploy:applications","read:deployments"],"audience": ["deployment-api.acmecorp.com"],"custom_claims": [{"key": "github_repository","value": "acmecorp/inventory-service"},{"key": "environment","value": "production_us"}]},"plain_secret": "test_ly8G57h0ErRJSObJI6dShkoaq6bigo11Dxcfa6reKG1kKNVbqBKW4H5Ctmb5UZ0X"} -
Authenticate the API client
Section titled “Authenticate the API client”After registration, the API client authenticates with your Scalekit environment using its
client_id
andclient_secret
(theplain_secret
obtained earlier) to request an access token. This process uses the OAuth 2.0 client credentials grant type.The client sends a POST request to the
/oauth/token
endpoint:POST /oauth/token curl -X POST \"https://<SCALEKIT_ENVIRONMENT_URL>/oauth/token" \-H "Content-Type: application/x-www-form-urlencoded" \-d "grant_type=client_credentials" \-d "client_id=<API_CLIENT_ID>" \-d "client_secret=<API_CLIENT_SECRET>" \client_id = "API_CLIENT_ID"client_secret = "API_CLIENT_SECRET"token_response = scalekit_client.generate_client_token(client_id=client_id,client_secret=client_secret)Upon successful authentication, Scalekit issues a JWT access token.
Access token response {"access_token":"<API_CLIENT_JWT_ACCESS_TOKEN>","token_type":"Bearer","expires_in":86399,// Same scopes that were granted during client registration"scope":"deploy:applications read:deployments"}The client includes this access token in the
Authorization
header of subsequent requests to your API server. -
Validate access tokens in your API server
Section titled “Validate access tokens in your API server”Your API server must validate the incoming JWT access token to ensure the request originates from a trusted API client and that the token is legitimate.
Validate the token in two steps:
-
Retrieve the public key: Fetch the appropriate public key from your Scalekit environment’s JSON Web Key Set (JWKS) endpoint. Use the
kid
(Key ID) from the JWT header to identify the correct key. Cache the key according to standard JWKS practices.import jwksClient from 'jwks-rsa';const client = jwksClient({jwksUri: 'YOUR_JWKS_URI',cache: true});async function getPublicKey(header: any): Promise<string> {return new Promise((resolve, reject) => {client.getSigningKey(header.kid, (err, key) => {if (err) reject(err);else resolve(key.getPublicKey());});});}# This is automatically handled by Scalekit SDKtoken = token_response["<API_CLIENT_JWT_ACCESS_TOKEN>"]claims = scalekit_client.validate_access_token_and_get_claims(token=token) -
Verify the token signature: Use the retrieved public key and a JWT library to verify the token’s signature and claims (like issuer, audience, and expiration).
import jwt from 'jsonwebtoken';async function verifyToken(token: string, publicKey: string) {try {const decoded = jwt.decode(token, { complete: true });const verified = jwt.verify(token, publicKey, {algorithms: ['RS256'],complete: true});return verified.payload;} catch (error) {throw new Error('Token verification failed');}}# Token from the incoming API request's authorization headertoken = token_response["<API_CLIENT_JWT_ACCESS_TOKEN>"]claims = scalekit_client.validate_access_token_and_get_claims(token=token)
Find complete code examples in the Scalekit M2M Gists repository.
If the token verification succeeds, your API server can trust the request’s authenticity and proceed with processing it based on the permissions (scopes) encoded within the token.
-