Skip to content

Authenticate with Kessel SDKs

All Kessel SDKs support the OAuth 2.0 Client Credentials grant for service-to-service authentication. The SDK handles token caching and automatic refresh transparently.

Some SDKs require an optional dependency to use authentication features:

SDKInstallation
Pythonpip install "kessel-sdk[auth]"
RubyAdd gem 'openid_connect' to your Gemfile
JavaInclude the Nimbus OAuth SDK (com.nimbusds:oauth2-oidc-sdk)
Go, TypeScriptIncluded in the core package

Use OIDC Discovery when your OAuth provider publishes a .well-known/openid-configuration endpoint. The SDK fetches the token endpoint URL for you.

# Option 1: Use OIDC discovery to find the token endpoint automatically
discovery = fetch_oidc_discovery(os.getenv("ISSUER_URL"))
credentials = OAuth2ClientCredentials(
client_id=os.getenv("CLIENT_ID"),
client_secret=os.getenv("CLIENT_SECRET"),
token_endpoint=discovery.token_endpoint,
)

Use a direct token URL when your OAuth provider does not support OIDC Discovery, or when you want explicit control over the token endpoint.

# Option 2: Provide the token endpoint URL directly
credentials = OAuth2ClientCredentials(
client_id=os.getenv("CLIENT_ID"),
client_secret=os.getenv("CLIENT_SECRET"),
token_endpoint=os.getenv("TOKEN_ENDPOINT"),
)

The same OAuth2ClientCredentials object works with both services, but is wrapped differently depending on the protocol.

Pass credentials to the ClientBuilder to build an authenticated gRPC client.

stub, channel = (
ClientBuilder(os.getenv("KESSEL_ENDPOINT"))
.oauth2_client_authenticated(credentials)
.build()
)

RBAC REST helpers like fetchRootWorkspace accept an AuthRequest object that injects the Bearer token into each HTTP request. Use oauth2AuthRequest to create one from your credentials.

# Wrap credentials as an HTTP auth adapter for RBAC REST calls
auth = oauth2_auth_request(credentials)
root_workspace = fetch_root_workspace(
rbac_base_endpoint=os.getenv("RBAC_ENDPOINT"),
org_id=os.getenv("ORG_ID"),
auth=auth,
)
print(f"Root workspace: {root_workspace.name} (ID: {root_workspace.id})")

The SDK handles token lifecycle automatically:

  • Token caching: tokens are reused until they approach expiration (within 5 minutes of expiry)
  • Automatic refresh: a new token is fetched before the cached one expires
  • Concurrency safe: concurrent requests share a single in-flight token fetch rather than each triggering a refresh
import os
from kessel.auth import OAuth2ClientCredentials, fetch_oidc_discovery, oauth2_auth_request
from kessel.inventory.v1beta2 import ClientBuilder
from kessel.rbac.v2 import fetch_root_workspace
def main():
# Option 1: Use OIDC discovery to find the token endpoint automatically
discovery = fetch_oidc_discovery(os.getenv("ISSUER_URL"))
credentials = OAuth2ClientCredentials(
client_id=os.getenv("CLIENT_ID"),
client_secret=os.getenv("CLIENT_SECRET"),
token_endpoint=discovery.token_endpoint,
)
# Option 2: Provide the token endpoint URL directly
credentials = OAuth2ClientCredentials(
client_id=os.getenv("CLIENT_ID"),
client_secret=os.getenv("CLIENT_SECRET"),
token_endpoint=os.getenv("TOKEN_ENDPOINT"),
)
stub, channel = (
ClientBuilder(os.getenv("KESSEL_ENDPOINT"))
.oauth2_client_authenticated(credentials)
.build()
)
channel.close()
# Wrap credentials as an HTTP auth adapter for RBAC REST calls
auth = oauth2_auth_request(credentials)
root_workspace = fetch_root_workspace(
rbac_base_endpoint=os.getenv("RBAC_ENDPOINT"),
org_id=os.getenv("ORG_ID"),
auth=auth,
)
print(f"Root workspace: {root_workspace.name} (ID: {root_workspace.id})")
if __name__ == "__main__":
main()