Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rcd-id

Python client library for the RCD Identity OIDC provider.

Handle the full OAuth 2.0 / OpenID Connect lifecycle programmatically -authorization URL generation, PKCE, code exchange, RS256 JWT verification, refresh token rotation, and automatic token management.

Installation

pip install git+https://github.com/RedCokeDevelopment/rcdid.py.git

Quick Start

You can directly send LLM.txt to your LLM for a quick overview of the library and build your application fast.

Alternatively, you can follow the examples below:

Confidential Client (with client_secret)

from rcd_id import RCDIdentityClient

client = RCDIdentityClient(
    issuer="https://auth.rcd.network",
    client_id="rcd_your_client_id",
    client_secret="your-client-secret",
)

# 1. Build authorization URL (user visits in browser)
req = client.authorization_url(
    redirect_uri="http://localhost:8080/callback",
    scope="openid email profile",
)

# 2. After callback with ?code=..., exchange for tokens
tokens = client.exchange_code(
    code="authorization-code-from-callback",
    redirect_uri="http://localhost:8080/callback",
)

# 3. Use the access token
user = client.userinfo(access_token=tokens.access_token)
print(user.email)  # user@example.com

# 4. Refresh when needed
new_tokens = client.refresh_token()
print(new_tokens.access_token)  # new access token
print(new_tokens.refresh_token)  # rotated refresh token

Public Client with PKCE

from rcd_id import RCDIdentityClient

client = RCDIdentityClient(
    issuer="https://auth.rcd.network",
    client_id="rcd_your_public_client",
    client_auth_method="none",
    use_pkce=True,
    redirect_uri="http://localhost:8080/callback",
)

req = client.authorization_url()
print(f"Visit: {req.url}")
print(f"Save code_verifier: {req.code_verifier}")

# In your callback handler:
tokens = client.exchange_code(
    code="authorization-code",
    code_verifier=req.code_verifier,
)

Automatic Token Refresh

client.set_tokens(tokens)

# This auto-refreshes if the access token is expired:
user = client.userinfo()  # no token arg needed

# Or get a valid token explicitly:
valid_token = client.get_valid_token()

Refresh Token Rotation

RCD Identity rotates refresh tokens. Each refresh_token() call invalidates the old token. Use the on_token_refresh callback to persist new tokens:

def save_tokens(tokens):
    db.execute(
        "UPDATE clients SET refresh_token = ? WHERE client_id = ?",
        [tokens.refresh_token, "my-client"],
    )

client = RCDIdentityClient(
    issuer="https://auth.rcd.network",
    client_id="rcd_abc",
    client_secret="secret",
    on_token_refresh=save_tokens,
)

Async Usage

from rcd_id import AsyncRCDIdentityClient

async with AsyncRCDIdentityClient(
    issuer="https://auth.rcd.network",
    client_id="rcd_abc",
    client_secret="secret",
    redirect_uri="http://localhost:8080/callback",
) as client:
    tokens = await client.exchange_code(code="...")
    user = await client.userinfo()

API Reference

RCDIdentityClient

Method Description
discover() Fetch and cache OIDC discovery document
authorization_url(...) Build the authorization URL with PKCE support
exchange_code(code, ...) Exchange authorization code for tokens
refresh_token(...) Refresh access token (handles rotation)
verify_access_token(token) Verify RS256 JWT against JWKS
verify_id_token(token, nonce) Verify ID token and optionally check nonce
userinfo(access_token) Fetch the UserInfo endpoint
set_tokens(tokens) Store tokens for managed mode
get_valid_token() Return valid token, auto-refreshing if expired
clear_tokens() Clear stored tokens

TokenSet

Field Type Description
access_token str The access token
token_type str Always "Bearer"
expires_in int Access token TTL (seconds)
refresh_token str|None Refresh token (rotated)
refresh_token_expires_in int|None Refresh token TTL
scope str|None Granted scopes
id_token str|None ID token (JWT)
is_expired(leeway=30) bool Check if token is expired

Exceptions

Exception Description
ConfigurationError Invalid client configuration
DiscoveryError Failed to fetch/parse OIDC discovery
TokenError Token endpoint error (carries .error, .error_description)
TokenVerificationError JWT verification failed
InvalidTokenError Token expired or unavailable
UserInfoError Userinfo endpoint error
SessionError State/nonce mismatch

Client Authentication

Configure via client_auth_method:

Method Description
client_secret_basic (default) Authorization: Basic <base64(client_id:secret)>
client_secret_post Secret in POST body
none Public client (requires use_pkce=True)

Development

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest tests/

# Type check
mypy rcd_id/

# Lint
ruff check rcd_id/ tests/

About

Auth.rcd.network SSO login python wrapper API

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages