The Workbrew SDK uses Bearer token authentication to securely access the Workbrew API. Your API key is sent as a Bearer token with every request to identify and authorize your application.
Proper authentication handling helps you:
- Secure your credentials - Avoid hardcoding API keys in source code
- Prevent unauthorized access - Ensure only valid API keys are used
- Support multiple environments - Use different keys for dev, staging, and production
- Audit usage - Track which keys are making requests
- Simplify key rotation - Create new clients with new keys when needed
Always use proper authentication when:
- Accessing the Workbrew API from any application
- Deploying to production environments
- Sharing code in version control systems
- Running automated tests or CI/CD pipelines
- Managing multiple Workbrew workspaces or API tiers
Here's the recommended way to authenticate with the Workbrew SDK:
package main
import (
"context"
"log"
"os"
"github.com/deploymenttheory/go-api-sdk-workbrew/workbrew/client"
"github.com/deploymenttheory/go-api-sdk-workbrew/workbrew/services/devices"
)
func main() {
// Step 1: Get API key and workspace from environment variables (recommended)
apiKey := os.Getenv("WORKBREW_API_KEY")
if apiKey == "" {
log.Fatal("WORKBREW_API_KEY environment variable is required")
}
workspace := os.Getenv("WORKBREW_WORKSPACE")
if workspace == "" {
log.Fatal("WORKBREW_WORKSPACE environment variable is required")
}
// Step 2: Create client with API key and workspace
workbrewClient, err := client.NewClient(apiKey, workspace)
if err != nil {
log.Fatal(err)
}
// Step 3: Use the client - authentication is automatic
devicesService := devices.NewService(workbrewClient)
result, _, err := devicesService.ListDevices(context.Background())
if err != nil {
log.Fatal(err)
}
log.Printf("Found %d devices", len(result))
}Run the example:
export WORKBREW_API_KEY="your-api-key-here"
export WORKBREW_WORKSPACE="your-workspace-id"
go run main.goStore API keys in environment variables for security and flexibility:
// Production: Read from environment
apiKey := os.Getenv("WORKBREW_API_KEY")
workspace := os.Getenv("WORKBREW_WORKSPACE")
workbrewClient, err := client.NewClient(apiKey, workspace)When to use: Always in production. This is the most secure approach.
Setup:
# Linux/macOS
export WORKBREW_API_KEY="your-api-key"
export WORKBREW_WORKSPACE="your-workspace-id"
# Windows PowerShell
$env:WORKBREW_API_KEY="your-api-key"
$env:WORKBREW_WORKSPACE="your-workspace-id"
# Docker
docker run -e WORKBREW_API_KEY="your-api-key" -e WORKBREW_WORKSPACE="your-workspace-id" myapp
# Kubernetes Secret
kubectl create secret generic workbrew-credentials --from-literal=api-key="your-api-key" --from-literal=workspace="your-workspace-id"Load API keys from configuration files (not committed to version control):
package main
import (
"encoding/json"
"os"
)
type Config struct {
APIKey string `json:"api_key"`
Workspace string `json:"workspace"`
}
func loadConfig(path string) (*Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var config Config
if err := json.Unmarshal(data, &config); err != nil {
return nil, err
}
return &config, nil
}
func main() {
// Load from config file
config, err := loadConfig("config.json")
if err != nil {
log.Fatal(err)
}
workbrewClient, err := client.NewClient(config.APIKey, config.Workspace)
// ... use client
}config.json:
{
"api_key": "your-api-key-here",
"workspace": "your-workspace-id"
}When to use: Development environments where you need per-developer configuration.
.gitignore:
config.json
*.local.json
Use dedicated secret management services for enterprise deployments:
AWS Secrets Manager:
import (
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/secretsmanager"
)
func getAPIKeyFromAWS() (string, error) {
sess := session.Must(session.NewSession())
svc := secretsmanager.New(sess)
result, err := svc.GetSecretValue(&secretsmanager.GetSecretValueInput{
SecretId: aws.String("workbrew/api-key"),
})
if err != nil {
return "", err
}
return *result.SecretString, nil
}
func main() {
apiKey, err := getAPIKeyFromAWS()
if err != nil {
log.Fatal(err)
}
workspace := os.Getenv("WORKBREW_WORKSPACE")
workbrewClient, err := client.NewClient(apiKey, workspace)
// ... use client
}HashiCorp Vault:
import "github.com/hashicorp/vault/api"
func getAPIKeyFromVault() (string, error) {
vaultClient, err := api.NewClient(api.DefaultConfig())
if err != nil {
return "", err
}
secret, err := vaultClient.Logical().Read("secret/data/workbrew")
if err != nil {
return "", err
}
apiKey := secret.Data["data"].(map[string]any)["api_key"].(string)
return apiKey, nil
}When to use: Production environments with compliance requirements or centralized secret management.
Use different API keys for different purposes or rate limits:
package main
type WorkbrewService struct {
publicClient *client.Client
premiumClient *client.Client
}
func NewWorkbrewService() (*WorkbrewService, error) {
workspace := os.Getenv("WORKBREW_WORKSPACE")
// Public API (free tier)
publicClient, err := client.NewClient(
os.Getenv("WORKBREW_PUBLIC_API_KEY"),
workspace,
)
if err != nil {
return nil, err
}
// Premium API (higher limits)
premiumClient, err := client.NewClient(
os.Getenv("WORKBREW_PREMIUM_API_KEY"),
workspace,
)
if err != nil {
return nil, err
}
return &WorkbrewService{
publicClient: publicClient,
premiumClient: premiumClient,
}, nil
}
func (s *WorkbrewService) ListDevices(ctx context.Context, usePremium bool) {
// Choose client based on requirements
var c *client.Client
if usePremium {
c = s.premiumClient
} else {
c = s.publicClient
}
devicesService := devices.NewService(c)
// ... use service
}When to use: When you have multiple API keys with different rate limits or permissions.
- Store API keys in environment variables
- Use secret management services in production
- Rotate API keys regularly (recreate client with new key)
- Use different keys for different environments
- Revoke compromised keys immediately
- Add
*.envfiles to.gitignore
- Hardcode API keys in source code
- Commit API keys to version control
- Share API keys in plaintext (email, chat, etc.)
- Use production keys in development
- Log API keys in application logs
- Store API keys in client-side code
When you need to rotate an API key, create a new client:
// Old client with compromised key
oldClient, _ := client.NewClient(oldKey, workspace)
// Create new client with rotated key
newClient, _ := client.NewClient(newKey, workspace)
// Switch to using newClient
// The API key is immutable after client creationSymptoms: WrongCredentialsError or AuthenticationRequiredError
Solutions:
import "github.com/deploymenttheory/go-api-sdk-workbrew/workbrew/client"
// Check for authentication errors
if err != nil && client.IsUnauthorized(err) {
log.Println("Invalid API key - check your credentials")
}
// Or check specific error codes
if err != nil && client.IsWrongCredentials(err) {
log.Println("API key is incorrect")
}Common causes:
- Invalid or expired API key
- API key not set in environment variable
- Typo in the API key
- Using wrong key for the environment
Symptoms: QuotaExceededError or TooManyRequestsError
Solution:
if err != nil && client.IsQuotaExceeded(err) {
log.Println("Rate limit exceeded - wait before retrying")
time.Sleep(60 * time.Second)
}Note: Configure retry logic to handle rate limits - see Timeouts & Retries for more details.
Mock the client to avoid real API calls:
func TestMyFunction(t *testing.T) {
// Use a mock/test API key and workspace
testClient, _ := client.NewClient("test-api-key", "test-workspace")
// Configure mock HTTP responses
// ... your test code
}Use a dedicated test API key:
# Set test API key
export WORKBREW_TEST_API_KEY="your-test-key"
# Run acceptance tests
go test -tags=acceptance ./...- Timeouts & Retries - Configure retry logic for auth errors
- Logging - Log authentication events
- Debugging - Debug authentication issues