ServiceAccount
A ServiceAccount resource provisions OAuth2 client credentials for machine-to-machine (M2M) authentication. Unlike an OidcClient, a ServiceAccount has no redirect URIs, no login flow, and no consent screen — it exclusively uses the client_credentials grant type.
When you create a ServiceAccount, the operator automatically generates a client_id and client_secret and projects them into a Kubernetes Secret in the same namespace. Your workloads can mount or reference this Secret to authenticate against the Nauthera token endpoint without any human interaction.
Example
apiVersion: auth.nauthera.io/v1alpha1
kind: ServiceAccount
metadata:
name: payment-service
namespace: payments-prod
spec:
displayName: "Payment Processing Service"
scopes:
- "api:payments"
- "api:ledger:read"
tokenSettings:
accessTokenTTL: 5mApply it:
kubectl apply -f serviceaccount-payment.yamlThe operator creates a Secret with the credentials:
kubectl get secret payment-service-sa-credentials -n payments-prod -o yamlSpec Reference
spec.displayName
Type: string | Optional
A human-readable name for this service account. Used in audit logs and the admin UI. If omitted, the resource name is used.
spec:
displayName: "Payment Processing Service"spec.scopes
Type: []string | Required
The OAuth2 scopes this service account is permitted to request. The applicable ClusterAuthPolicy and/or namespace-scoped AuthPolicy may further restrict which scopes are actually granted.
spec:
scopes:
- "api:payments"
- "api:ledger:read"Note: The
openidscope is not typically needed for service accounts since there is no user context. However, it can be included if ID tokens are required for downstream systems.
spec.tokenSettings
Type: object | Optional
Override token lifetimes for this service account. These settings are clamped by the applicable policy's enforcement floors — a ServiceAccount cannot exceed the maximum TTL set by the cluster-wide policy.
spec:
tokenSettings:
accessTokenTTL: 5m| Field | Default | Description |
|---|---|---|
accessTokenTTL | Inherited from policy | Lifetime of access tokens issued to this service account |
spec.claims
Type: map[string]string | Optional
Static claims to include in tokens issued to this service account. These are merged with any claimMappings from the applicable policy. Static claims take precedence over policy mappings for the same claim name.
spec:
claims:
"https://myapp.example.com/service": "payment-processor"
"https://myapp.example.com/tier": "critical"spec.credentialsSecretName
Type: string | Optional
The name of the Secret the operator creates with the generated credentials. Defaults to {metadata.name}-sa-credentials.
spec:
credentialsSecretName: payment-service-oauth-secretspec.configMapName
Type: string | Optional
The name of the ConfigMap the operator creates with the token endpoint and issuer configuration. Defaults to {metadata.name}-sa-config.
spec:
configMapName: payment-service-oauth-configspec.credentialRotation
Type: object | Optional
Controls automatic rotation of the service account's client secret.
spec:
credentialRotation:
enabled: true
intervalDays: 90
gracePeriodHours: 24| Field | Default | Description |
|---|---|---|
enabled | false | Enable automatic credential rotation |
intervalDays | 90 | Days between rotations |
gracePeriodHours | 24 | Hours during which both the old and new secrets are valid, allowing rolling restarts |
During the grace period, both the old and new client_secret values are accepted at the token endpoint. The Secret is updated with the new credentials, and workloads that mount the Secret via a projected volume will pick up the new credentials automatically.
Provisioned Resources
When you create a ServiceAccount, the operator provisions two resources in the same namespace: a Secret with sensitive credentials and a ConfigMap with non-sensitive endpoint configuration. Together they contain everything a workload needs to request tokens — no hardcoded URLs required.
The operator sets owner references on both — deleting the ServiceAccount also deletes the Secret and ConfigMap.
Secret
Contains the sensitive credentials only:
apiVersion: v1
kind: Secret
metadata:
name: payment-service-sa-credentials
namespace: payments-prod
ownerReferences:
- apiVersion: auth.nauthera.io/v1alpha1
kind: ServiceAccount
name: payment-service
type: Opaque
data:
client_id: <base64>
client_secret: <base64>ConfigMap
Contains the token endpoint, issuer URL, and other non-sensitive metadata. Workloads use this to discover where to request tokens without fetching the OIDC discovery document at startup.
apiVersion: v1
kind: ConfigMap
metadata:
name: payment-service-sa-config
namespace: payments-prod
ownerReferences:
- apiVersion: auth.nauthera.io/v1alpha1
kind: ServiceAccount
name: payment-service
data:
issuer_url: "https://auth.example.com"
token_endpoint: "https://auth.example.com/oauth2/token"
jwks_uri: "https://auth.example.com/.well-known/jwks.json"
client_id: "sa-a1b2c3d4-e5f6-7890-abcd-ef1234567890"
scopes: "api:payments api:ledger:read"Using the Resources in a Pod
Mount both the Secret and ConfigMap for a complete setup with zero hardcoded values:
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-worker
namespace: payments-prod
spec:
template:
spec:
containers:
- name: worker
image: myregistry/payment-worker:latest
envFrom:
# Non-sensitive config (token endpoint, issuer, scopes)
- configMapRef:
name: payment-service-sa-config
# Sensitive credentials (client_id, client_secret)
- secretRef:
name: payment-service-sa-credentialsOr mount selectively:
env:
- name: OAUTH_TOKEN_ENDPOINT
valueFrom:
configMapKeyRef:
name: payment-service-sa-config
key: token_endpoint
- name: OAUTH_CLIENT_ID
valueFrom:
secretKeyRef:
name: payment-service-sa-credentials
key: client_id
- name: OAUTH_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: payment-service-sa-credentials
key: client_secretYour application then requests tokens using the standard OAuth2 client credentials flow:
curl -s -X POST "$OAUTH_TOKEN_ENDPOINT" \
-u "$OAUTH_CLIENT_ID:$OAUTH_CLIENT_SECRET" \
-d "grant_type=client_credentials" \
-d "scope=api:payments api:ledger:read"Status
status:
clientId: "sa-a1b2c3d4-e5f6-7890-abcd-ef1234567890"
ready: true
phase: Active
lastCredentialRotation: "2026-01-15T03:00:00Z"
nextCredentialRotation: "2026-04-15T03:00:00Z"
conditions:
- type: Ready
status: "True"
reason: ServiceAccountRegistered
lastTransitionTime: "2026-01-01T00:00:00Z"
- type: CredentialsProvisioned
status: "True"
reason: SecretCreated
lastTransitionTime: "2026-01-01T00:00:00Z"
- type: ConfigProvisioned
status: "True"
reason: ConfigMapCreated
lastTransitionTime: "2026-01-01T00:00:00Z"Conditions
| Condition | Description |
|---|---|
Ready | The service account is registered with the operator and operational |
CredentialsProvisioned | The credentials Secret has been created in the namespace |
ConfigProvisioned | The endpoint configuration ConfigMap has been created in the namespace |
ServiceAccount vs OidcClient
| ServiceAccount | OidcClient | |
|---|---|---|
| Use case | Service-to-service / machine-to-machine | User-facing applications |
| Grant types | client_credentials only | authorization_code, refresh_token, client_credentials, token exchange |
| Redirect URIs | Not applicable | Required |
| Login flow | None — tokens are issued directly | User authenticates via login page |
| Consent screen | Not applicable | Configurable |
| PKCE | Not applicable | Configurable |
| Credential rotation | Built-in automatic rotation | Manual (re-create the OidcClient) |
Use a ServiceAccount when a workload needs to authenticate itself — not a human. Use an OidcClient when users need to log in.
Multi-Environment Pattern
Like OidcClient, create one ServiceAccount per environment namespace:
# payments-dev namespace
apiVersion: auth.nauthera.io/v1alpha1
kind: ServiceAccount
metadata:
name: payment-service
namespace: payments-dev
spec:
scopes: ["api:payments"]
tokenSettings:
accessTokenTTL: 1h # Longer TTL for dev
---
# payments-prod namespace
apiVersion: auth.nauthera.io/v1alpha1
kind: ServiceAccount
metadata:
name: payment-service
namespace: payments-prod
spec:
scopes: ["api:payments"]
tokenSettings:
accessTokenTTL: 5m # Short TTL for prod
credentialRotation:
enabled: true
intervalDays: 30Related Resources
- OidcClient — For user-facing applications with login flows.
- AuthPolicy — Policies governing scope restrictions and token settings.
- Endpoints — Token endpoint reference for the client credentials grant.
- Quick Start — End-to-end example including client credentials flow.