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:
- Loading XSUAA credentials from Cloud Foundry environment
- Obtaining an OAuth 2.0 access token using client credentials
- Setting up an Echo server with API key authentication middleware
- 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 ¶
- Constants
- func APIKeyAuth() echo.MiddlewareFunc
- func CertsCheckHost(host string, warnYears, warnMonths, warnDays *int) (result hostResult)
- func DecryptFile(pass, inputPath, outputPath string) error
- func EncryptFile(pass, inputPath, outputPath string) error
- func ExtractScopesFromXSUAA(claims map[string]interface{}) []string
- func HandleWithClientCredentials(c echo.Context) error
- func HasXSUAAScope(claims map[string]interface{}, scope string) bool
- func HashPassword(password string) (string, error)
- func HashPasswordWithCost(password string, cost int) (string, error)
- func InfisicalSecrets(host, client_id, client_secret, project_id, environment, format string) string
- func NeedsRehash(hash string, cost int) (bool, error)
- func SetGlobalXSUAAToken(token *TokenResponse)
- func VerifyPassword(hash, password string) error
- func VerifyXSUAAToken(token, xsuaaURL string) (map[string]interface{}, error)
- func VerifyXSUAATokenWithKey(token, publicKey string) (map[string]interface{}, error)
- func ZitiCreateCSR(privateFilePath, csrFilePath string) error
- type Claims
- type JWTService
- func (j *JWTService) GenerateToken(userID string, expiration time.Duration) (string, error)
- func (j *JWTService) GenerateTokenWithClaims(userID string, expiration time.Duration, customClaims map[string]interface{}) (string, error)
- func (j *JWTService) ValidateToken(tokenString string) (jwt.Token, error)
- func (j *JWTService) ValidateTokenWithOptions(tokenString string, options ...jwt.ParseOption) (jwt.Token, error)
- type OIDCConfig
- type OIDCProvider
- func (p *OIDCProvider) Endpoint() oauth2.Endpoint
- func (p *OIDCProvider) GetUserInfo(ctx context.Context, tokenSource oauth2.TokenSource) (*oidc.UserInfo, error)
- func (p *OIDCProvider) OAuth2Config() *oauth2.Config
- func (p *OIDCProvider) VerifyIDToken(ctx context.Context, token string) (*Claims, error)
- type TokenResponse
- type VCAPServices
- type XSUAACredentials
Examples ¶
Constants ¶
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 ¶
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:
- Establishes a TLS connection to the host
- Examines each certificate in the verified chains
- Checks expiration dates against the warning thresholds
- Validates signature algorithms against known deprecated algorithms
- Returns any issues found
func DecryptFile ¶
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 ¶
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
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
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:
- Constructs a target URL with query parameters
- Adds the XSUAA bearer token to the Authorization header
- Forwards the request to the backend service
- 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
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
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
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
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
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
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:
- Fetches the JWK Set from the XSUAA provider's token_keys endpoint
- Verifies the token signature using the appropriate public key
- 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
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 ¶
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:
- Generates an ECDSA key pair using P-256 curve
- Saves the private key to a PEM file
- Creates a CSR template with appropriate subject information
- Generates the CSR using the private key
- 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
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:
- Google: "https://accounts.google.com"
- Auth0: "https://YOUR_DOMAIN.auth0.com"
- Keycloak: "https://keycloak.example.com/realms/YOUR_REALM"
- Azure AD: "https://login.microsoftonline.com/YOUR_TENANT_ID/v2.0"
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
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