RFC 8693 Token Exchange Provider
Exchanges ID tokens for OAuth2 access tokens with RFC 8693 token exchange, sending the identity token as the subject_token, and refreshes them before expiration.
Package pkg/rfc8693. Snippets assume the common setup; Channel Behavior explains the result channel.
import ( "go.riptides.io/tokenex/pkg/credential" "go.riptides.io/tokenex/pkg/rfc8693")
provider, err := rfc8693.NewCredentialsProvider(ctx, logr.Discard())if err != nil { log.Fatalf("new provider: %v", err)}
credCh, err := provider.GetCredentials(ctx, "https://auth.example.com/oauth2/token", idTokenProvider, rfc8693.WithAudience("https://api.example.com"), rfc8693.WithScopes([]string{"api.read"}),)if err != nil { log.Fatalf("get credentials: %v", err)}
for cred := range credCh { if cred.Err != nil { log.Printf("token error: %v", cred.Err) break } tok := cred.Credential.(*credential.Oauth2Creds) log.Printf("got access token, expires %s", tok.Expiry)}The request body is JSON. The subject token type defaults to urn:ietf:params:oauth:token-type:jwt (WithSubjectTokenType changes it). WithActorTokenProvider adds an actor token for delegation, and WithRequestedTokenType and WithAdditionalFields cover endpoint-specific parameters.
OpenAI Workload Identity Federation
Section titled “OpenAI Workload Identity Federation”rfc8693.GetOpenAICredentials exchanges the identity token at OpenAI’s token endpoint (https://auth.openai.com/oauth/token), using the same request shape as the openai-go workload identity support. ClientID is optional.
credCh, err := rfc8693.GetOpenAICredentials(ctx, logr.Discard(), idTokenProvider, rfc8693.OpenAIWIFConfig{ IdentityProviderID: "...", ServiceAccountID: "...",})Related: Supplying short-lived OpenAI API keys to AI agents with Riptides.