Machine to Machine (M2M) Authentication with OAuth 2.0

Machine-to-machine authentication is enabled by default in SaaS deployments running v39.2 and later.

The Hyperscience application integrates a built-in local identity provider that supports machine-to-machine (M2M) communication via the OAuth 2.0 protocol. It supports the following authorization flows:

  • Client Credentials Flow 

    • client_secret_basic (authentication method)

    • client_secret_post

    • client_secret_jwt

    • private_key_jwt

  • JWT Bearer Flow

Setting up the local identity provider (on-premise only)

The local identity provided needs to be configured with the environment's public URL. To do so, enter the URL, including its https:// prefix, as the value for the HS_PUBLIC_URL variable in the ".env" file.

Managing machine credentials

Manage machine credentials in the application at https://{hostname}/users/machine-credentials (Users > Machine Credentials). Both client secrets and public keys are maintained in JWKS format.

M2MAuthentication.png

Making HTTP requests to Hyperscience's API

The process involves two steps:

  1. Clients use their ID and key to get an access token from https://{hostname}/api/v5/local_identity_provider/oauth2/token, which is valid for 10 minutes.

  2. Include the access token in the HTTP header for API requests.

Example code

This sample implementation is provided using Python 3.11.7 and Authlib library version 1.3.2.

""" Sample code for the OAuth 2.0 Client Credentials flow (client_secret_jwt). """

from authlib.integrations.requests_client import OAuth2Session
from authlib.jose import JsonWebKey
from authlib.oauth2.rfc7523 import ClientSecretJWT

client_id = "b77db512-cda5-4bda-a613-3c358ef144ad"
client_secret = JsonWebKey.import_key(
    {
        "kty": "oct",
        "k": "ZldVQnRrWEpVNUJ2NTB1RVlVS2FMeUtySWVJdEx6T2o",
        "alg": "HS256",
        "kid": "d0aa7744-4253-483b-8404-ab2db8b70d6f"
    }
)
token_endpoint = "http://{hostname}/api/v5/local_identity_provider/oauth2/token"


with OAuth2Session(
    client_id,
    client_secret,
    token_endpoint_auth_method=ClientSecretJWT(token_endpoint, alg=client_secret["alg"]),
    token_endpoint=token_endpoint,
    grant_type="client_credentials",
) as session:
    session.headers.update({"HyperscienceLocalIdentityProvider": "1"})

    # Fetch the initial access token. All subsequent access tokens will be
    # automatically fetched by the OAuth 2.0 client as they near expiration.
    session.fetch_token()

    # Make a request to Hyperscience's API
    response = session.get("http://{hostname}/api/v5/version")
    print(f"{response.status_code=} {response.json()=}")