Documentation Index

Fetch the complete documentation index at: https://help.hyperscience.ai/llms.txt

Use this file to discover all available pages before exploring further.

Machine to Machine (M2M) Authentication with OAuth 2.0

Prev Next

Machine-to-machine authentication is required for SaaS deployments of all versions and strongly recommended for on-premise deployments of Hyperscience v40 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.

Custom CA certificate bundles

In v42.3.6 and later, you can use a custom CA (certificate authority) certificate bundle to acquire tokens for authentication against the URL listed in HS_PUBLIC_URL. To use a custom certificate bundle, enter it as the value for the HS_PUBLIC_URL_CA_BUNDLE 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

Permissions and access to restricted flows

API calls made with M2M access tokens are given the permissions of the API User Permission Group. If a flow's access is restricted to specific permission groups, and the API User group is not one of them, M2M requests to that flow's endpoints return a 403 Forbidden response — even when the credentials and token are valid.

To allow M2M access to a restricted flow:

  1. In the application, go to Users > Permission Groups, and find the API User permission group.

  2. Scroll to the bottom of the group's settings, and grant the API User group access to the restricted flow.

    • Repeat step 2 for each restricted flow that needs to be accessed via the API.

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.

For more information, see our API documentation.

Add API User permission group to a restricted flow

If your API calls return 403 Forbidden for a restricted flow, add the API User permission group to that flow's restriction. See Permissions and access to restricted flows above.

Example code

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

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

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

client_id = "b77db512-cda5-4bda-a613-3c358ef144ad"
client_secret = {
    "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"],
        headers={"kid": client_secret["kid"]},
    ),
    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()=}")