Skip to content

PQAuth/pqauth-client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pqauth-client

OAuth 2.0 client SDK for Go applications connecting to a PQAuth authorization server. Handles token acquisition, automatic refresh, PKCE code generation, and server discovery — so you can focus on your application logic.

Features

  • All major grant types — Authorization Code (PKCE), Client Credentials, Refresh Token, Device Authorization (RFC 8628), JWT Bearer (RFC 7523)
  • Automatic token refresh — transparent refresh before expiry
  • Server discovery — populates all endpoints automatically from RFC 8414 / OIDC Discovery metadata
  • Thread-safe — safe to share a single PQAuthClient across goroutines
  • Standard PKCE — S256 by default; plain supported
  • Advanced flows — PAR (RFC 9126), Token Introspection (RFC 7662), Token Revocation (RFC 7009)

Installation

go get github.com/PQAuth/pqauth-client

Quick start

Machine-to-machine (Client Credentials)

package main

import (
    "context"
    "fmt"
    "log"

    pqclient "github.com/PQAuth/pqauth-client"
)

func main() {
    ctx := context.Background()

    client, err := pqclient.NewWithDiscovery(ctx,
        "https://auth.example.com",
        "my-service",
        pqclient.WithClientSecret("my-secret"),
        pqclient.WithDefaultScopes("api:read", "api:write"),
    )
    if err != nil {
        log.Fatal(err)
    }

    tokenSet, err := client.ClientCredentials(ctx)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println("Access token:", tokenSet.AccessToken)
    fmt.Println("Expires at:", tokenSet.ExpiresAt)
}

Authorization Code flow (browser/SPA backend)

// Step 1 — generate the authorization URL
authURL, codeVerifier, err := client.AuthorizationCodeStart(
    ctx,
    "https://app.example.com/callback",
    pqclient.WithCallScopes("openid", "profile"),
)
// Redirect the user to authURL

// Step 2 — exchange the code after the redirect
tokenSet, err := client.AuthorizationCodeExchange(
    ctx,
    code,          // from query parameter
    codeVerifier,  // saved from step 1
    "https://app.example.com/callback",
)

Get a token with automatic refresh

// Token() returns the current token and refreshes it transparently if it is close to expiry.
tokenSet, err := client.Token(ctx)

Device Authorization flow (CLI / TV apps)

tokenSet, err := client.DeviceAuthorizationFlow(ctx,
    pqclient.WithCallScopes("openid", "profile"),
)
// The SDK handles polling internally until the user completes the flow.

Configuration

Constructor

// Recommended: auto-discover endpoints from the server's metadata document
client, err := pqclient.NewWithDiscovery(ctx, serverURL, clientID, opts...)

// Manual: specify each endpoint directly
client, err := pqclient.New(
    pqclient.WithServerURL("https://auth.example.com"),
    pqclient.WithClientID("my-app"),
    pqclient.WithClientSecret("secret"),
    pqclient.WithTokenEndpoint("https://auth.example.com/oauth/token"),
)

Options

// Client identity
pqclient.WithClientID("my-app")
pqclient.WithClientSecret("secret")
pqclient.WithClientAuthMethod("client_secret_basic")  // or "client_secret_post", "private_key_jwt"

// Default scopes used when no per-call scopes are provided
pqclient.WithDefaultScopes("openid", "profile", "api:read")

// Automatic token refresh
pqclient.WithAutoRefresh(true)
pqclient.WithRefreshThreshold(30 * time.Second)  // refresh when less than 30s remain

// HTTP transport
pqclient.WithHTTPClient(myHTTPClient)
pqclient.WithRequestTimeout(10 * time.Second)
pqclient.WithMaxRetries(3)
pqclient.WithRetryBackoff(500 * time.Millisecond)

// JWT Bearer assertions (RFC 7523)
pqclient.WithAssertionLifetime(5 * time.Minute)

// Device flow polling
pqclient.WithDevicePollInterval(5 * time.Second)

// Endpoint overrides (when not using discovery)
pqclient.WithTokenEndpoint("...")
pqclient.WithDeviceEndpoint("...")
pqclient.WithIntrospectionEndpoint("...")
pqclient.WithRevocationEndpoint("...")
pqclient.WithUserInfoEndpoint("...")
pqclient.WithPAREndpoint("...")

Per-call options

Override defaults for individual requests:

tokenSet, err := client.ClientCredentials(ctx,
    pqclient.WithCallScopes("reports:read"),
)

authURL, verifier, err := client.AuthorizationCodeStart(ctx, redirectURI,
    pqclient.WithCallScopes("openid", "profile", "billing:read"),
)

tokenSet, err := client.JWTBearerGrant(ctx,
    pqclient.WithCallSubject("user-456"),
    pqclient.WithCallAudience("https://api.example.com"),
    pqclient.WithCallExtraClaims(map[string]interface{}{"tenant": "acme"}),
)

TokenSet

type TokenSet struct {
    AccessToken  string
    TokenType    string
    RefreshToken string
    Scope        string
    ExpiresAt    time.Time
    IssuedAt     time.Time
    Raw          map[string]interface{}  // full token response
}

func (t *TokenSet) IsExpired() bool
func (t *TokenSet) HasRefreshToken() bool
func (t *TokenSet) TimeUntilExpiry() time.Duration

PKCE

The client uses S256 by default. You can also use the PKCE helpers directly:

import "github.com/PQAuth/pqauth-client/pkce"

pair, err := pkce.Generate(pkce.MethodS256)
fmt.Println(pair.Verifier)
fmt.Println(pair.Challenge)
fmt.Println(pair.Method)  // "S256"

Advanced

Token introspection and revocation

// Introspect any token (RFC 7662)
result, err := client.Introspect(ctx, accessToken)
fmt.Println(result.Active, result.Subject)

// Revoke a token (RFC 7009)
err = client.Revoke(ctx, refreshToken)

OIDC UserInfo

userInfo, err := client.UserInfo(ctx)
fmt.Println(userInfo.Subject, userInfo.Email)

Pushed Authorization Requests (RFC 9126)

par, err := client.PushAuthorizationRequest(ctx, params)
// Redirect the user to par.RequestURI

Server metadata

meta := client.Discovery()
fmt.Println(meta.TokenEndpoint)
fmt.Println(meta.SupportedGrantTypes)
fmt.Println(meta.SupportedCodeChallengeMethods)

Related modules

Module Description
pqauth-core Cryptographic primitives and JWT utilities
pqauth-auth-svr OAuth 2.0 Authorization Server
pqauth-resource-svr Resource server token validation
pqauth-svr-core Database and cache abstractions

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages