m2m-cognito is a small Python library for machine-to-machine flows against Amazon Cognito: on the caller side it performs OAuth2 client credentials requests to Cognito’s token endpoint and returns a structured token response; on the API/resource-server side it validates Cognito-issued JWT access tokens with the pool’s JWKS, optional client allowlists, and configurable scope checks. The public surface is two main types—CognitoM2MClient and CognitoAccessTokenValidator—plus result dataclasses and exceptions.
- Python: 3.10 or newer (
requires-python >=3.10). - Dependencies:
pyjwt[crypto]>=2.12.1,requests>=2.33.1.
From PyPI:
pip install m2m-cognitouv add m2m-cognitoThe import package name is m2m_cognito (underscore); the distribution name on PyPI is m2m-cognito (hyphen).
Configure CognitoM2MClient with your Cognito app client’s token URL, client ID, and client secret. Call fetch_token with one or more OAuth2 scopes (string or sequence). On success you get a TokenResponse with access_token, optional expires_in and token_type, and raw (the full parsed JSON for forward compatibility).
from m2m_cognito import CognitoM2MClient
client = CognitoM2MClient(
token_url="https://your-auth-domain.example.com/oauth2/token",
client_id="7a8b9c0d1e2f3g4h5i6j7k8",
client_secret="your-client-secret",
)
response = client.fetch_token(scopes=["api.example.com/read", "api.example.com/write"])
bearer = response.access_tokenBuild a CognitoAccessTokenValidator from the user pool’s AWS region and user pool ID. Optionally restrict allowed client IDs, require scopes with scope_match of "all" (every required scope present) or "any" (at least one overlap), and set audience if your tokens include aud and you want it verified. Pass the raw JWT string (no Bearer prefix) to validate. On success you get ValidatedAccessToken with client_id, scopes (as a frozenset), and full claims.
from m2m_cognito import CognitoAccessTokenValidator
validator = CognitoAccessTokenValidator(
region="us-west-2",
user_pool_id="us-west-2_AbCdEfGhI",
allowed_client_ids={"7a8b9c0d1e2f3g4h5i6j7k8", "another-app-client-id"},
required_scopes={"api.example.com/read"},
scope_match="all",
audience=None, # omit or set to verify JWT aud
)
validated = validator.validate(jwt_string_from_authorization_header)
subject_client = validated.client_idAt the top level, AWS Cognito has a user pool. Within that user pool, are resource servers, corresponding to API servers, and Application clients, which are the systems that will connect to the APIs.
To begin to use Cognito for API authentication and authorization you must first create the required resources:
- User pool
- Resource server within the user pool. The resource server will have:
- A human name (
My API) - An identifier (
my_api) - Custom scopes (or permissions - read, write) these scopes are referred to by joining the resource server identifier with the scope name, ie.
my_api/read
- A human name (
- Application client. These clients will have:
- A client ID
- A client secret
- Allowed scopes
- Resource server within the user pool. The resource server will have:
To connect to a resource server or API, a client will first connect to Cognito using its client id and client secret and obtain a temporary token. By default, this token will last for 1 hour.
This token will be sent as an authentication Bearer token to the server. That server will then validate that token with Cognito. If valid, the response will include the client id, and the valid scopes for the session. The server will then provide the corresponding data to the client.
All library-specific errors subclass M2MCognitoError. Typical cases:
| Exception | When it usually occurs |
|---|---|
M2MCognitoError |
Base type; catch this if you want a single handler for any library error. |
CognitoTokenRequestError |
Token HTTP request failed, non-success status, invalid JSON, missing access_token, OAuth2 error / error_description in the body, or empty scopes passed to fetch_token. Optional attributes: status_code, error_code, error_description, response_body (useful for logging—avoid echoing secrets). |
TokenValidationError |
JWT cannot be verified (signature, issuer, expiry, required claims), wrong token_use, missing client_id, client_id not in allowed_client_ids, or malformed scope claim. Also the base class for scope failures below. |
InsufficientScopeError |
Cryptographically valid token, but required_scopes is non-empty and the token’s scopes do not satisfy scope_match (all vs any). Exposes token_scopes and required_scopes for messaging or metrics. |
Prefer catching the specific types where you branch on behavior; use M2MCognitoError only for broad “Cognito/M2M layer failed” handling.
- Token URL: If you use a Cognito hosted UI domain (custom or Amazon-provided), the client-credentials token endpoint is typically
https://<your-domain>/oauth2/token(same host as the hosted UI, path/oauth2/token). See Using the resource server with the hosted UI and OAuth 2.0 and related Cognito OAuth2 documentation. - Issuer and JWKS: For a user pool in
regionwith iduser_pool_id, Cognito’s issuer ishttps://cognito-idp.<region>.amazonaws.com/<user_pool_id>and the JWKS URL is<issuer>/.well-known/jwks.json.CognitoAccessTokenValidatorbuilds these automatically fromregionanduser_pool_id.