OIDC Authentication
Creddy implements OpenID Connect (OIDC), allowing agents to authenticate using standard OAuth 2.0 flows. This enables federation with AWS, GCP, and other services that support OIDC identity providers.
Overview
┌─────────────────────────────────────────────────────────────────┐
│ CREDDY SERVER │
│ (your-server:8400) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ /.well-known/openid-configuration ← OIDC Discovery │
│ /.well-known/jwks.json ← Public keys (for verify) │
│ /oauth/token ← Get JWT access token │
│ /v1/credentials/{backend} ← Get ephemeral credentials │
│ │
└─────────────────────────────────────────────────────────────────┘
▲
│
┌───────────────┴───────────────┐
│ │
┌────────┴────────┐ ┌────────┴────────┐
│ AI Agent │ │ AWS / GCP │
│ (your bot) │ │ (federation) │
│ │ │ │
│ Uses tokens to │ │ Trusts Creddy │
│ get credentials │ │ as identity │
└─────────────────┘ │ provider │
└─────────────────┘Enable OIDC
Start the server with an issuer URL:
creddy server --oidc-issuer https://creddy.example.comThe issuer URL must be:
- HTTPS — Required by OIDC spec
- Reachable — Agents and federated services (AWS/GCP) need to fetch JWKS
Need TLS? See Server Setup → TLS & OIDC for Tailscale Funnel, Caddy, nginx, and cloud LB options.
Credential Types
When you create an agent, Creddy generates two sets of credentials:
| Type | Format | Use Case |
|---|---|---|
| Vend Token | ckr_xxx... | Simple auth, direct API access |
| OIDC Credentials | client_id + client_secret | Standard OAuth, federation |
creddy agent create my-agent --can githubOutput:
{
"name": "my-agent",
"token": "ckr_abc123...", // Vend token
"oidc": {
"client_id": "agent_f8e7d6", // OIDC
"client_secret": "cks_xyz789..."
}
}Authentication Flows
OIDC Flow (Recommended)
Step 1: Get Access Token
curl -X POST https://creddy.example.com/oauth/token \
-d "grant_type=client_credentials" \
-d "client_id=agent_f8e7d6" \
-d "client_secret=cks_xyz789" \
-d "scope=openid github"Response:
{
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjEyMzQ1In0...",
"token_type": "Bearer",
"expires_in": 3600,
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjEyMzQ1In0...",
"scope": "openid github"
}Step 2: Use Access Token
# Get ephemeral GitHub token
curl https://creddy.example.com/v1/credentials/github?ttl=10m \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."
# Check agent status
curl https://creddy.example.com/v1/status \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Vend Flow
Skip the OAuth exchange — use the vend token directly:
curl https://creddy.example.com/v1/credentials/github?ttl=10m \
-H "Authorization: Bearer ckr_abc123..."Both flows work on all endpoints. OIDC is preferred for:
- Federation (AWS, GCP trust relationships)
- Short-lived tokens (1 hour vs permanent)
- Audit trails (JWT contains identity claims)
Token Contents
Access Token
A JWT containing:
{
"iss": "https://creddy.example.com",
"sub": "agent-uuid",
"exp": 1709740800,
"iat": 1709737200,
"agent_id": "agent-uuid",
"agent_name": "my-agent",
"scopes": ["github:owner/repo"],
"client_id": "agent_f8e7d6"
}ID Token
Same as access token, plus:
{
"auth_time": 1709737200,
"aud": ["https://creddy.example.com"]
}OIDC Endpoints
Discovery
curl https://creddy.example.com/.well-known/openid-configurationReturns standard OIDC metadata including endpoints, supported algorithms, and claims.
JWKS
curl https://creddy.example.com/.well-known/jwks.jsonReturns public keys for verifying token signatures. Keys are RS256.
Token
curl -X POST https://creddy.example.com/oauth/token \
-d "grant_type=client_credentials" \
-d "client_id=..." \
-d "client_secret=..."UserInfo
curl https://creddy.example.com/oauth/userinfo \
-H "Authorization: Bearer <access_token>"Returns agent identity claims.
AWS Federation
Creddy can act as an OIDC identity provider for AWS IAM:
1. Create OIDC Provider in AWS
aws iam create-open-id-connect-provider \
--url https://creddy.example.com \
--client-id-list https://creddy.example.com \
--thumbprint-list <certificate-thumbprint>2. Create IAM Role with Trust Policy
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::ACCOUNT:oidc-provider/creddy.example.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"creddy.example.com:sub": "agent-uuid"
}
}
}]
}3. Agent Assumes Role
# Get Creddy ID token
TOKEN=$(curl -s -X POST https://creddy.example.com/oauth/token \
-d "grant_type=client_credentials" \
-d "client_id=$CLIENT_ID" \
-d "client_secret=$CLIENT_SECRET" \
| jq -r .id_token)
# Assume AWS role
aws sts assume-role-with-web-identity \
--role-arn arn:aws:iam::ACCOUNT:role/CredddyAgentRole \
--role-session-name my-agent \
--web-identity-token "$TOKEN"No static AWS credentials needed!
Key Rotation
OIDC signing keys can be rotated without downtime:
# View current keys
curl https://creddy.example.com/.well-known/jwks.json | jq '.keys[].kid'
# Rotate (admin)
creddy admin keys rotateOld keys remain in JWKS during a grace period for token validation.
Verifying Tokens
To verify Creddy tokens in your own service:
Go:
import "github.com/getcreddy/creddy/verify"
verifier := verify.New("https://creddy.example.com")
claims, err := verifier.Verify(ctx, token)
if err != nil {
// Invalid token
}
fmt.Println("Agent:", claims.AgentName)Manual (any language):
- Fetch
/.well-known/jwks.json - Extract
kidfrom JWT header - Find matching key in JWKS
- Verify RS256 signature
- Validate
iss,exp,audclaims
Comparison
| Feature | Vend (ckr_) | OIDC |
|---|---|---|
| Token lifetime | Permanent | 1 hour (configurable) |
| Format | Opaque string | JWT with claims |
| AWS/GCP federation | ❌ | ✅ |
| Self-describing | ❌ | ✅ (claims in token) |
| Revocation | Delete agent | Keys rotate, tokens expire |
Use OIDC for production. Use vend tokens for quick testing or simple setups.