Implement machine-to-machine authentication with WorkOS Connect.
Machine-to-machine (M2M) applications are designed for use-cases where clients are other services, such as one of your customer’s applications. M2M applications use the underlying client_credentials
flow for authentication.
M2M access tokens will contain an org_id
claim which represents the third-party you are granting access to via the M2M application.
M2M applications can only be configured as third-party.
M2M applications are commonly used to provide API access credentials to customers or partners, allowing them to programmatically access your APIs and integrate your services into their applications. They’re also ideal for partner integrations that run server-to-server without user interaction, where you need to track and control access on a per-organization basis.
Machine-to-machine applications can use the client_credentials
grant type with the Token Endpoint to obtain an access_token
to authenticate calls to your API.
const params = new URLSearchParams({ grant_type: 'client_credentials', client_id: process.env.M2M_APP_CLIENT_ID, client_secret: process.env.M2M_APP_CLIENT_SECRET, scope: 'openid profile email', }); const response = fetch('https://<subdomain>.authkit.app/oauth2/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: params, }).then((response) => response.json()); const accessToken = response.access_token;
M2M applications are always associated with a specific Organization, which represents the customer or partner. Since machine-to-machine applications are associated with a particular organization, issued access tokens contain an org_id
claim that your application’s API can use to control access.
This association provides several benefits:
org_id
claim that identifies which organization the client is acting on behalf oforg_id
to ensure clients only access resources they’re authorized forYour application can verify the tokens sent by external M2M applications for the purpose of authenticating requests using the JWKS for your environment. The process is similar to validating the access token JWT provided by an AuthKit login.
import { jwtVerify, createRemoteJWKSet } from 'jose'; const JWKS = createRemoteJWKSet(new URL('https://<subdomain>.authkit.app/oauth2/jwks')); const bearerTokenMiddleware = async (req, res, next) => { const authHeader = req.headers.authorization; const token = authHeader?.match(/^Bearer (.+)$/)?.[1]; if (!token) { return res.status(401).json({ error: 'No token provided' }); } try { const { payload } = await jwtVerify(token, JWKS, { issuer: 'https://<subdomain>.authkit.app', audience: 'client_123456789', }); req.organization = await findOrganizationById(payload.org_id); next(); } catch (err) { return res.status(401).json({ error: 'Invalid token' }); } }; // Example protected route app.get('/api/protected', bearerTokenMiddleware, (req, res) => { res.json({ data: 'Protected resource', organization: req.organization }); });
In addition to fast stateless verification, you can use the Token Introspection API to synchronously check whether a token is still valid.
M2M applications use the client_id
and client_secret
from a credential to authenticate to the Connect APIs using the client credentials flow.
While not displayed to users (since M2M apps don’t have user interaction), the name and description help you manage and identify different M2M applications in your dashboard.