security

package
v0.0.78 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 30, 2025 License: Apache-2.0 Imports: 28 Imported by: 0

Documentation

Overview

Package security provides cryptographic and authentication utilities. This file implements password hashing and verification using bcrypt algorithm.

Package security provides utilities for certificate management and security checks. It includes functions for generating Certificate Signing Requests (CSRs) for Ziti, checking TLS certificate expiration, and validating signature algorithms.

Features:

  • ECDSA key pair generation
  • CSR creation for Ziti edge routers
  • TLS certificate expiration checking
  • Signature algorithm validation
  • Support for various cryptographic operations

The package helps ensure secure communications by validating certificates and using strong cryptographic algorithms.

Package security provides authentication utilities including OpenID Connect (OIDC) integration. This file implements OIDC provider discovery and ID token verification for authentication with external identity providers like Auth0, Keycloak, Azure AD, Google, and others.

Package security provides authentication and authorization utilities for SAP BTP XSUAA integration. This package implements OAuth 2.0 client credentials flow for machine-to-machine authentication with SAP Business Technology Platform (BTP) services using XSUAA (Extended Services for UAA).

Example

Example demonstrates how to set up an Echo web server with SAP BTP XSUAA authentication. This example shows the complete flow of:

  1. Loading XSUAA credentials from Cloud Foundry environment
  2. Obtaining an OAuth 2.0 access token using client credentials
  3. Setting up an Echo server with API key authentication middleware
  4. Creating protected and public endpoints
// Get XSUAA credentials from VCAP_SERVICES environment variable
// In Cloud Foundry, this is automatically provided when bound to an XSUAA service
creds, err := security.GetXSUAACredentials()
if err != nil {
	log.Fatalf("Failed to get XSUAA credentials: %v", err)
}

// Construct the OAuth token endpoint URL
tokenURL := creds.URL + "/oauth/token"

// Obtain access token using client credentials flow
token, err := security.GetXSUAAToken(tokenURL, creds.ClientID, creds.ClientSecret)
if err != nil {
	log.Fatalf("Failed to get XSUAA token: %v", err)
}

// Cache the token globally for use in handlers
security.SetGlobalXSUAAToken(token)

// Create Echo instance
e := echo.New()

// Public health check endpoint (no authentication required)
e.GET("/health", func(c echo.Context) error {
	return c.String(http.StatusOK, "OK")
})

// Create API group with authentication middleware
api := e.Group("/api")
api.Use(security.APIKeyAuth())

// Protected endpoint - requires X-API-Key header
api.GET("/response", security.HandleWithClientCredentials)

// Get port from environment or use default
port := os.Getenv("PORT")
if port == "" {
	port = "8080"
}

// Start server
fmt.Printf("Starting server on port %s\n", port)
if err := e.Start(":" + port); err != nil && err != http.ErrServerClosed {
	log.Fatal(err)
}

Index

Examples

Constants

View Source
const (
	// DefaultBcryptCost is the default cost factor for bcrypt password hashing.
	// Cost factor of 10 provides a good balance between security and performance.
	// Higher values increase security but also increase hashing time exponentially.
	DefaultBcryptCost = 10
)

Variables

This section is empty.

Functions

func APIKeyAuth added in v0.0.6

func APIKeyAuth() echo.MiddlewareFunc

APIKeyAuth creates an Echo middleware for API key authentication. This middleware validates incoming requests against an API key stored in the API_KEY environment variable. The /health endpoint is exempted from authentication to allow health checks.

The middleware expects the API key in the X-API-Key request header.

Returns:

  • echo.MiddlewareFunc: Configured middleware function

Example:

e := echo.New()
api := e.Group("/api")
api.Use(APIKeyAuth())
api.GET("/protected", handler) // This endpoint requires X-API-Key header

e.GET("/health", healthHandler) // This endpoint is public
Example

ExampleAPIKeyAuth demonstrates how to use API key authentication middleware with Echo framework.

// Set API key in environment
os.Setenv("API_KEY", "my-secret-key")
defer os.Unsetenv("API_KEY")

e := echo.New()

// Public endpoint
e.GET("/health", func(c echo.Context) error {
	return c.String(http.StatusOK, "OK")
})

// Protected API group
api := e.Group("/api")
api.Use(security.APIKeyAuth())

// This endpoint requires X-API-Key header
api.GET("/protected", func(c echo.Context) error {
	return c.JSON(http.StatusOK, map[string]string{
		"message": "Access granted",
	})
})

// Start server
// Clients must send: X-API-Key: my-secret-key
e.Start(":8080")

func CertsCheckHost

func CertsCheckHost(host string, warnYears, warnMonths, warnDays *int) (result hostResult)

CertsCheckHost checks the TLS certificates of a host for expiration and security issues. This function connects to the host, examines its certificate chain, and checks for:

  • Certificates expiring within the warning period
  • Use of deprecated signature algorithms

Parameters:

  • host: The host:port to check (e.g., "example.com:443")
  • warnYears: Number of years before expiration to start warning
  • warnMonths: Number of months before expiration to start warning
  • warnDays: Number of days before expiration to start warning

Returns:

  • hostResult: A struct containing the host information, any errors found, and the common name from the certificate

The function:

  1. Establishes a TLS connection to the host
  2. Examines each certificate in the verified chains
  3. Checks expiration dates against the warning thresholds
  4. Validates signature algorithms against known deprecated algorithms
  5. Returns any issues found

func DecryptFile

func DecryptFile(pass, inputPath, outputPath string) error

DecryptFile decrypts a ciphertext file to a plaintext file using AES-256-GCM.

The decryption key is derived from the provided password using SHA-256. The ciphertext file must contain a prepended nonce (generated during encryption). The function verifies authenticity and integrity during decryption.

Parameters:

  • pass: Password used to derive the decryption key.
  • inputPath: Path to the ciphertext file to decrypt.
  • outputPath: Path to write the decrypted plaintext file.

Returns an error if reading, decryption, authentication, or writing fails.

func EncryptFile

func EncryptFile(pass, inputPath, outputPath string) error

EncryptFile encrypts a plaintext file to a ciphertext file using AES-256-GCM.

The encryption key is derived from the provided password using SHA-256, producing a 32-byte key for AES-256. A random nonce is generated and prepended to the ciphertext. The resulting data is written to outputPath.

Parameters:

  • pass: Password used to derive the encryption key.
  • inputPath: Path to the plaintext file to encrypt.
  • outputPath: Path to write the resulting ciphertext file.

Returns an error if reading, encryption, or writing fails.

func ExtractScopesFromXSUAA added in v0.0.12

func ExtractScopesFromXSUAA(claims map[string]interface{}) []string

ExtractScopesFromXSUAA extracts scopes from XSUAA token claims. XSUAA tokens store scopes in the "scope" claim as an array of strings.

Parameters:

  • claims: The token claims map

Returns:

  • []string: List of scopes, or nil if not found

Example:

claims, _ := VerifyXSUAAToken(token, xsuaaURL)
scopes := ExtractScopesFromXSUAA(claims)
for _, scope := range scopes {
    fmt.Println("Scope:", scope)
}

func HandleWithClientCredentials added in v0.0.6

func HandleWithClientCredentials(c echo.Context) error

HandleWithClientCredentials is an Echo HTTP handler that forwards requests to a backend service using XSUAA client credentials authentication. This demonstrates how to use client credentials tokens to authenticate service-to-service API calls.

The handler:

  1. Constructs a target URL with query parameters
  2. Adds the XSUAA bearer token to the Authorization header
  3. Forwards the request to the backend service
  4. Returns the backend response to the client

Query Parameters:

  • product_group: Product category identifier
  • publication_id: Publication identifier for the X-Publication-Id header
  • filter_columns: Comma-separated list of columns to filter

Returns:

  • error: Any error encountered during request processing

Example usage in Echo router:

e := echo.New()
e.GET("/api/response", HandleWithClientCredentials)

func HasXSUAAScope added in v0.0.12

func HasXSUAAScope(claims map[string]interface{}, scope string) bool

HasXSUAAScope checks if the claims contain a specific scope. Scopes in XSUAA typically have the format "appname.scopename".

Parameters:

  • claims: The token claims map
  • scope: The scope to check for

Returns:

  • bool: true if the scope is present, false otherwise

Example:

claims, _ := VerifyXSUAAToken(token, xsuaaURL)
if HasXSUAAScope(claims, "myapp.read") {
    fmt.Println("User has read permission")
}

func HashPassword added in v0.0.12

func HashPassword(password string) (string, error)

HashPassword creates a bcrypt hash of the provided password. Uses the default cost factor (10) which provides good security for most use cases.

Bcrypt is a password hashing function designed to be slow and computationally expensive, making it resistant to brute-force attacks. Each hash includes a random salt automatically.

Parameters:

  • password: The plaintext password to hash

Returns:

  • string: The bcrypt hash string (includes algorithm, cost, salt, and hash)
  • error: Any error encountered during hashing

Example:

hash, err := HashPassword("mySecurePassword123")
if err != nil {
    log.Fatalf("Failed to hash password: %v", err)
}
// Store hash in database: $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy

func HashPasswordWithCost added in v0.0.12

func HashPasswordWithCost(password string, cost int) (string, error)

HashPasswordWithCost creates a bcrypt hash of the provided password with a custom cost factor. Use this when you need fine-grained control over the hashing cost.

Cost factor recommendations:

  • 10: Default, suitable for most applications
  • 12: Higher security, slower hashing (~250ms)
  • 14: Very high security, much slower (~1 second)
  • 4-9: Faster but less secure (not recommended for production)

Parameters:

  • password: The plaintext password to hash
  • cost: The bcrypt cost factor (must be between bcrypt.MinCost and bcrypt.MaxCost)

Returns:

  • string: The bcrypt hash string
  • error: Any error encountered during hashing

Example:

// Use higher cost for admin passwords
hash, err := HashPasswordWithCost("adminPassword", 12)
if err != nil {
    log.Fatalf("Failed to hash password: %v", err)
}

func InfisicalSecrets

func InfisicalSecrets(host, client_id, client_secret, project_id, environment, format string) string

InfisicalSecrets retrieves secrets from an Infisical project environment.

It authenticates using the provided client ID and secret, fetches secrets for the given project and environment, and returns them formatted as either environment variable declarations or `.netrc` entries.

Parameters:

  • host: The Infisical host domain (e.g. "app.infisical.com").
  • client_id: The Infisical client ID for authentication.
  • client_secret: The Infisical client secret for authentication.
  • project_id: The project identifier from which to fetch secrets.
  • environment: The target environment name (e.g. "dev", "prod").
  • format: Output format, either "env" (default) or "netrc".

Returns:

A string containing either key=value pairs (one per line) or `.netrc`
formatted credentials if format == "netrc".

Behavior:

  • On authentication or retrieval failure, the program logs the error using eve.Logger and exits with status code 1.
  • If format == "netrc", it looks for secrets with keys "MACHINE", "LOGIN", and "PASSWORD" to construct the .netrc entry.

Example Output (env format):

MACHINE=github.com
LOGIN=myuser
PASSWORD=mytoken

Example Output (netrc format):

machine github.com
login myuser
password mytoken

func NeedsRehash added in v0.0.12

func NeedsRehash(hash string, cost int) (bool, error)

NeedsRehash checks if a password hash needs to be regenerated with a different cost factor. This is useful when you increase the cost factor in your application and want to upgrade old hashes during user login.

Parameters:

  • hash: The bcrypt hash to check
  • cost: The desired cost factor

Returns:

  • bool: true if the hash needs to be regenerated with the new cost
  • error: Any error encountered while parsing the hash

Example:

const CurrentCost = 12

// During login after successful password verification
needsRehash, err := NeedsRehash(storedHash, CurrentCost)
if err == nil && needsRehash {
    newHash, _ := HashPasswordWithCost(password, CurrentCost)
    // Update hash in database
}

func SetGlobalXSUAAToken added in v0.0.6

func SetGlobalXSUAAToken(token *TokenResponse)

SetGlobalXSUAAToken sets the global XSUAA token for use in handlers. This is typically called during application initialization after obtaining the token via GetXSUAAToken.

Parameters:

  • token: The token response to cache globally

Example:

token, err := GetXSUAAToken(tokenURL, clientID, clientSecret)
if err != nil {
    log.Fatal(err)
}
SetGlobalXSUAAToken(token)
Example

ExampleSetGlobalXSUAAToken demonstrates token caching for reuse across requests.

package main

import (
	"fmt"

	"eve.evalgo.org/security"
)

func main() {
	// Obtain token
	token := &security.TokenResponse{
		AccessToken: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
		TokenType:   "bearer",
		ExpiresIn:   3600,
	}

	// Cache token globally
	security.SetGlobalXSUAAToken(token)

	// Later, retrieve the token
	cachedToken := security.GetGlobalXSUAAToken()
	if cachedToken != nil {
		fmt.Printf("Token expires in: %d seconds\n", cachedToken.ExpiresIn)
	}
}
Output:

Token expires in: 3600 seconds

func VerifyPassword added in v0.0.12

func VerifyPassword(hash, password string) error

VerifyPassword compares a plaintext password with a bcrypt hash. Returns nil if the password matches the hash, or an error if they don't match or if verification fails.

This function is constant-time to prevent timing attacks.

Parameters:

  • hash: The bcrypt hash to verify against
  • password: The plaintext password to check

Returns:

  • error: nil if password matches, bcrypt.ErrMismatchedHashAndPassword if mismatch, or other error if verification fails

Example:

// During login
err := VerifyPassword(storedHash, userProvidedPassword)
if err != nil {
    if err == bcrypt.ErrMismatchedHashAndPassword {
        log.Println("Invalid password")
    } else {
        log.Printf("Verification error: %v", err)
    }
    return
}
log.Println("Password correct, user authenticated")

func VerifyXSUAAToken added in v0.0.12

func VerifyXSUAAToken(token, xsuaaURL string) (map[string]interface{}, error)

VerifyXSUAAToken verifies an XSUAA JWT token using the provider's public key. This performs cryptographic validation of the token signature using JWK (JSON Web Key).

The function:

  1. Fetches the JWK Set from the XSUAA provider's token_keys endpoint
  2. Verifies the token signature using the appropriate public key
  3. Validates standard claims (expiration, issuer, etc.)

Parameters:

  • token: The raw JWT token string to verify
  • xsuaaURL: The XSUAA service base URL (e.g., from credentials.URL)

Returns:

  • map[string]interface{}: The validated token claims
  • error: Any error during verification

Example:

creds, _ := GetXSUAACredentials()
claims, err := VerifyXSUAAToken(tokenString, creds.URL)
if err != nil {
    log.Printf("Invalid token: %v", err)
    return
}
fmt.Printf("User: %s\n", claims["user_name"])

func VerifyXSUAATokenWithKey added in v0.0.12

func VerifyXSUAATokenWithKey(token, publicKey string) (map[string]interface{}, error)

VerifyXSUAATokenWithKey verifies an XSUAA JWT token using a provided public key. Use this when you have the public key directly (e.g., from XSUAA_VERIFICATION_KEY env var).

The public key can be:

  • PEM-encoded RSA public key
  • PEM-encoded ECDSA public key
  • Base64-encoded public key

Parameters:

  • token: The raw JWT token string to verify
  • publicKey: The public key in PEM or base64 format

Returns:

  • map[string]interface{}: The validated token claims
  • error: Any error during verification

Example:

publicKey := os.Getenv("XSUAA_VERIFICATION_KEY")
claims, err := VerifyXSUAATokenWithKey(tokenString, publicKey)
if err != nil {
    log.Printf("Invalid token: %v", err)
    return
}
fmt.Printf("Scopes: %v\n", claims["scope"])

func ZitiCreateCSR

func ZitiCreateCSR(privateFilePath, csrFilePath string) error

ZitiCreateCSR generates a Certificate Signing Request (CSR) and private key for Ziti. This function creates an ECDSA key pair and generates a CSR for a Ziti edge router.

Parameters:

  • privateFilePath: Path to save the generated private key
  • csrFilePath: Path to save the generated CSR

The function:

  1. Generates an ECDSA key pair using P-256 curve
  2. Saves the private key to a PEM file
  3. Creates a CSR template with appropriate subject information
  4. Generates the CSR using the private key
  5. Saves the CSR to a PEM file

The generated CSR will have:

  • Common Name: "ziti-edge-router"
  • Organization: "OpenZiti"
  • Signature Algorithm: ECDSA with SHA-256

Types

type Claims added in v0.0.12

type Claims struct {
	// Subject is the unique identifier for the user (required)
	Subject string `json:"sub"`

	// Email is the user's email address
	Email string `json:"email,omitempty"`

	// EmailVerified indicates if the email has been verified by the provider
	EmailVerified bool `json:"email_verified,omitempty"`

	// Name is the user's full name
	Name string `json:"name,omitempty"`

	// GivenName is the user's first name
	GivenName string `json:"given_name,omitempty"`

	// FamilyName is the user's last name
	FamilyName string `json:"family_name,omitempty"`

	// Picture is the URL of the user's profile picture
	Picture string `json:"picture,omitempty"`

	// Locale is the user's preferred locale
	Locale string `json:"locale,omitempty"`

	// Issuer is the token issuer URL
	Issuer string `json:"iss,omitempty"`

	// Audience is the intended audience for the token
	Audience string `json:"aud,omitempty"`

	// ExpiresAt is the token expiration time (Unix timestamp)
	ExpiresAt int64 `json:"exp,omitempty"`

	// IssuedAt is the token issuance time (Unix timestamp)
	IssuedAt int64 `json:"iat,omitempty"`

	// Custom claims as a map for provider-specific claims
	Extra map[string]interface{} `json:"-"`
}

Claims represents the standard OIDC claims extracted from an ID token.

type JWTService added in v0.0.2

type JWTService struct {
	// contains filtered or unexported fields
}

JWTService provides methods for generating and validating JSON Web Tokens (JWTs) using the HMAC SHA-256 (HS256) signing algorithm.

func NewJWTService added in v0.0.2

func NewJWTService(secret string) *JWTService

NewJWTService initializes and returns a new JWTService instance.

The secret parameter is the signing key used for both token generation and validation. It should be a sufficiently random and securely stored string.

Example:

j := security.NewJWTService("my-super-secret-key")

func NewJWTServiceWithIssuer added in v0.0.12

func NewJWTServiceWithIssuer(secret, issuer, audience string) *JWTService

NewJWTServiceWithIssuer creates a JWT service with issuer and audience validation. This provides enhanced security by validating the token's issuer and audience claims.

Parameters:

  • secret: The signing key for HMAC SHA-256
  • issuer: The expected issuer claim (iss) - typically your application's identifier
  • audience: The expected audience claim (aud) - typically your API's identifier

Example:

j := security.NewJWTServiceWithIssuer(
    "my-super-secret-key",
    "https://myapp.example.com",
    "https://api.example.com",
)

func (*JWTService) GenerateToken added in v0.0.2

func (j *JWTService) GenerateToken(userID string, expiration time.Duration) (string, error)

GenerateToken creates a new signed JWT containing the specified user ID as the subject.

Parameters:

  • userID: The unique identifier of the user (stored as the "sub" claim).
  • expiration: Token validity duration (e.g. 1 * time.Hour).

The generated token includes the following standard claims:

  • "sub": The subject (user ID)
  • "iat": Issued-at timestamp
  • "exp": Expiration timestamp
  • "iss": Issuer (if configured)
  • "aud": Audience (if configured)

Returns:

  • The signed JWT string.
  • An error if token building or signing fails.

Example:

token, err := jwtService.GenerateToken("user123", time.Hour)

func (*JWTService) GenerateTokenWithClaims added in v0.0.12

func (j *JWTService) GenerateTokenWithClaims(userID string, expiration time.Duration, customClaims map[string]interface{}) (string, error)

GenerateTokenWithClaims creates a signed JWT with custom claims in addition to standard claims.

Parameters:

  • userID: The unique identifier of the user (stored as the "sub" claim)
  • expiration: Token validity duration
  • customClaims: Additional custom claims to include in the token

Returns:

  • The signed JWT string
  • An error if token building or signing fails

Example:

claims := map[string]interface{}{
    "role":  "admin",
    "scope": "read write delete",
    "email": "[email protected]",
}
token, err := jwtService.GenerateTokenWithClaims("user123", time.Hour, claims)

func (*JWTService) ValidateToken added in v0.0.2

func (j *JWTService) ValidateToken(tokenString string) (jwt.Token, error)

ValidateToken verifies and parses a JWT string using the configured secret key.

The token's signature and expiration are validated automatically. If issuer and audience are configured, they are also validated. If validation succeeds, it returns a `jwt.Token` instance that allows access to claims such as subject, expiration, and issued-at time.

Parameters:

  • tokenString: The signed JWT string to validate.

Returns:

  • jwt.Token: The parsed and validated token.
  • error: Non-nil if the token is invalid, expired, or improperly signed.

Example:

token, err := jwtService.ValidateToken(tokenStr)
if err != nil {
	log.Println("Invalid token:", err)
} else {
	fmt.Println("User:", token.Subject())
}

func (*JWTService) ValidateTokenWithOptions added in v0.0.12

func (j *JWTService) ValidateTokenWithOptions(tokenString string, options ...jwt.ParseOption) (jwt.Token, error)

ValidateTokenWithOptions validates a JWT with custom validation options. This provides fine-grained control over token validation.

Parameters:

  • tokenString: The signed JWT string to validate
  • options: Custom validation options (issuer, audience, clock skew, etc.)

Returns:

  • jwt.Token: The parsed and validated token
  • error: Non-nil if validation fails

Example:

token, err := jwtService.ValidateTokenWithOptions(tokenStr,
    jwt.WithIssuer("https://myapp.example.com"),
    jwt.WithAudience("https://api.example.com"),
    jwt.WithAcceptableSkew(30*time.Second),
)

type OIDCConfig added in v0.0.12

type OIDCConfig struct {
	// ProviderURL is the OIDC provider's discovery URL (e.g., "https://accounts.google.com")
	ProviderURL string

	// ClientID is your application's client ID registered with the OIDC provider
	ClientID string

	// ClientSecret is your application's client secret (required for some flows)
	ClientSecret string

	// RedirectURL is the callback URL for OAuth2 authorization code flow
	RedirectURL string

	// Scopes are the OAuth2 scopes to request (default: ["openid", "profile", "email"])
	Scopes []string

	// SkipIssuerCheck disables issuer validation (not recommended for production)
	SkipIssuerCheck bool

	// SkipExpiryCheck disables expiration time validation (not recommended for production)
	SkipExpiryCheck bool
}

OIDCConfig contains the configuration for an OIDC provider.

type OIDCProvider added in v0.0.12

type OIDCProvider struct {
	// contains filtered or unexported fields
}

OIDCProvider wraps an OpenID Connect provider with token verification capabilities. It handles provider discovery, token verification, and claims extraction.

func NewOIDCProvider added in v0.0.12

func NewOIDCProvider(ctx context.Context, config OIDCConfig) (*OIDCProvider, error)

NewOIDCProvider creates a new OIDC provider instance with automatic discovery. It contacts the OIDC provider's discovery endpoint to retrieve configuration and sets up token verification.

The provider URL should be the issuer URL without the /.well-known/openid-configuration path. For example:

Parameters:

  • ctx: Context for the HTTP request to the discovery endpoint
  • config: OIDC provider configuration

Returns:

  • *OIDCProvider: Initialized OIDC provider
  • error: Any error during provider discovery or initialization

Example:

config := OIDCConfig{
    ProviderURL:  "https://accounts.google.com",
    ClientID:     "your-client-id.apps.googleusercontent.com",
    ClientSecret: "your-client-secret",
    Scopes:       []string{"openid", "profile", "email"},
}

provider, err := NewOIDCProvider(context.Background(), config)
if err != nil {
    log.Fatalf("Failed to initialize OIDC provider: %v", err)
}

func (*OIDCProvider) Endpoint added in v0.0.12

func (p *OIDCProvider) Endpoint() oauth2.Endpoint

Endpoint returns the OAuth2 endpoint configuration for this provider.

Returns:

  • oauth2.Endpoint: The provider's authorization and token endpoints

func (*OIDCProvider) GetUserInfo added in v0.0.12

func (p *OIDCProvider) GetUserInfo(ctx context.Context, tokenSource oauth2.TokenSource) (*oidc.UserInfo, error)

GetUserInfo fetches additional user information from the provider's UserInfo endpoint. This is optional and provides claims not included in the ID token.

Parameters:

  • ctx: Context for the HTTP request
  • tokenSource: OAuth2 token source (from oauth2.Config.TokenSource)

Returns:

  • *oidc.UserInfo: User information from the provider
  • error: Any error during the UserInfo request

Example:

token, _ := oauth2Config.Exchange(ctx, code)
userInfo, err := provider.GetUserInfo(ctx, oauth2Config.TokenSource(ctx, token))
if err != nil {
    log.Fatal(err)
}

var claims Claims
userInfo.Claims(&claims)
fmt.Printf("User: %s\n", claims.Email)

func (*OIDCProvider) OAuth2Config added in v0.0.12

func (p *OIDCProvider) OAuth2Config() *oauth2.Config

OAuth2Config returns an OAuth2 configuration for the authorization code flow. Use this to redirect users to the provider's login page and exchange authorization codes for tokens.

Returns:

  • *oauth2.Config: OAuth2 configuration ready for authorization code flow

Example:

oauth2Config := provider.OAuth2Config()

// Redirect user to login
authURL := oauth2Config.AuthCodeURL("state-string")
http.Redirect(w, r, authURL, http.StatusFound)

// In callback handler
code := r.URL.Query().Get("code")
token, err := oauth2Config.Exchange(context.Background(), code)
if err != nil {
    log.Fatal(err)
}

// Verify ID token
rawIDToken, ok := token.Extra("id_token").(string)
if !ok {
    log.Fatal("No id_token in response")
}
claims, err := provider.VerifyIDToken(context.Background(), rawIDToken)

func (*OIDCProvider) VerifyIDToken added in v0.0.12

func (p *OIDCProvider) VerifyIDToken(ctx context.Context, token string) (*Claims, error)

VerifyIDToken verifies and parses an OIDC ID token. It validates the token signature, expiration, issuer, and audience claims.

The token string should be the raw JWT ID token (not an access token).

Parameters:

  • ctx: Context for the verification operation
  • token: The raw JWT ID token string

Returns:

  • *Claims: Parsed and verified claims from the ID token
  • error: Any error during verification or parsing

Example:

claims, err := provider.VerifyIDToken(context.Background(), rawIDToken)
if err != nil {
    log.Printf("Invalid token: %v", err)
    return
}
fmt.Printf("Authenticated user: %s (%s)\n", claims.Name, claims.Email)

type TokenResponse added in v0.0.6

type TokenResponse struct {
	// AccessToken is the JWT bearer token for API authentication
	AccessToken string `json:"access_token"`

	// TokenType is the type of token (typically "bearer")
	TokenType string `json:"token_type"`

	// ExpiresIn indicates token validity duration in seconds
	ExpiresIn int `json:"expires_in"`
}

TokenResponse represents the OAuth 2.0 token response from XSUAA. This contains the access token and metadata required for authenticated API calls.

func GetGlobalXSUAAToken added in v0.0.6

func GetGlobalXSUAAToken() *TokenResponse

GetGlobalXSUAAToken retrieves the currently cached XSUAA token. Returns nil if no token has been set.

Returns:

  • *TokenResponse: The cached token, or nil if not set

Example:

token := GetGlobalXSUAAToken()
if token == nil {
    log.Println("No token cached")
}

func GetXSUAAToken added in v0.0.6

func GetXSUAAToken(tokenURL, clientID, clientSecret string) (*TokenResponse, error)

GetXSUAAToken obtains an OAuth 2.0 access token from XSUAA using client credentials flow. This is used for machine-to-machine authentication where no user interaction is required.

The client credentials grant is suitable for:

  • Backend service-to-service communication
  • Scheduled jobs and batch processes
  • API clients that act on behalf of the application itself

Parameters:

  • tokenURL: The XSUAA token endpoint URL (typically "{xsuaa-url}/oauth/token")
  • clientID: Your application's OAuth client ID
  • clientSecret: Your application's OAuth client secret

Returns:

  • *TokenResponse: Contains the access token and expiration information
  • error: Any error encountered during token acquisition

Example:

tokenURL := "https://tenant.authentication.eu10.hana.ondemand.com/oauth/token"
token, err := GetXSUAAToken(tokenURL, "client-id", "client-secret")
if err != nil {
    log.Fatalf("Failed to get token: %v", err)
}
fmt.Printf("Access token: %s\n", token.AccessToken)
Example

ExampleGetXSUAAToken demonstrates how to obtain an XSUAA access token using client credentials flow.

package main

import (
	"fmt"
	"log"

	"eve.evalgo.org/security"
)

func main() {
	tokenURL := "https://tenant.authentication.eu10.hana.ondemand.com/oauth/token"
	clientID := "your-client-id"
	clientSecret := "your-client-secret"

	token, err := security.GetXSUAAToken(tokenURL, clientID, clientSecret)
	if err != nil {
		log.Fatalf("Failed to get token: %v", err)
	}

	fmt.Printf("Token type: %s\n", token.TokenType)
	fmt.Printf("Expires in: %d seconds\n", token.ExpiresIn)
	// Output will show token details
}

type VCAPServices added in v0.0.6

type VCAPServices struct {
	// XSUAA contains one or more XSUAA service bindings
	XSUAA []struct {
		Credentials XSUAACredentials `json:"credentials"`
	} `json:"xsuaa"`
}

VCAPServices represents the Cloud Foundry VCAP_SERVICES environment variable structure. This is automatically provided by Cloud Foundry when services are bound to your application.

type XSUAACredentials added in v0.0.6

type XSUAACredentials struct {
	// URL is the XSUAA service base URL (e.g., "https://tenant.authentication.eu10.hana.ondemand.com")
	URL string `json:"url"`

	// ClientID is the OAuth 2.0 client identifier for your application
	ClientID string `json:"clientid"`

	// ClientSecret is the OAuth 2.0 client secret for authentication
	ClientSecret string `json:"clientsecret"`

	// XSAppName is the application name registered in XSUAA
	XSAppName string `json:"xsappname"`
}

XSUAACredentials represents the XSUAA service binding credentials from Cloud Foundry. These credentials are typically provided through the VCAP_SERVICES environment variable when your application is bound to an XSUAA service instance.

func GetXSUAACredentials added in v0.0.6

func GetXSUAACredentials() (*XSUAACredentials, error)

GetXSUAACredentials retrieves XSUAA service credentials from the VCAP_SERVICES environment variable. This function is designed for Cloud Foundry environments where service bindings are automatically provided through environment variables.

The VCAP_SERVICES variable contains JSON with all bound services. This function extracts the first XSUAA service binding credentials.

Returns:

  • *XSUAACredentials: The XSUAA service credentials including URL, client ID, and secret
  • error: Error if VCAP_SERVICES is not set, malformed, or contains no XSUAA service

Example:

creds, err := GetXSUAACredentials()
if err != nil {
    log.Fatalf("Failed to get XSUAA credentials: %v", err)
}
fmt.Printf("XSUAA URL: %s\n", creds.URL)
Example

ExampleGetXSUAACredentials demonstrates how to extract XSUAA credentials from Cloud Foundry's VCAP_SERVICES environment variable.

package main

import (
	"fmt"
	"log"
	"os"

	"eve.evalgo.org/security"
)

func main() {
	// In Cloud Foundry, VCAP_SERVICES is automatically set
	// Here's an example of what it might contain:
	vcapExample := `{
		"xsuaa": [{
			"credentials": {
				"url": "https://tenant.authentication.eu10.hana.ondemand.com",
				"clientid": "sb-myapp!t123",
				"clientsecret": "secret123",
				"xsappname": "myapp!t123"
			}
		}]
	}`

	// Temporarily set for demonstration
	os.Setenv("VCAP_SERVICES", vcapExample)
	defer os.Unsetenv("VCAP_SERVICES")

	creds, err := security.GetXSUAACredentials()
	if err != nil {
		log.Fatalf("Failed to get credentials: %v", err)
	}

	fmt.Printf("XSUAA URL: %s\n", creds.URL)
	fmt.Printf("Client ID: %s\n", creds.ClientID)
	fmt.Printf("App Name: %s\n", creds.XSAppName)
}
Output:

XSUAA URL: https://tenant.authentication.eu10.hana.ondemand.com
Client ID: sb-myapp!t123
App Name: myapp!t123

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL