Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/auth0/go-auth0/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Auth0 Go SDK provides two mechanisms for working with fields that aren’t included in the generated types:
  1. ExtraProperties - Available on select request/response types for capturing additional fields
  2. WithBodyProperties - Request option for adding custom fields to any request body
These features are useful when:
  • Working with custom metadata fields
  • Using advanced configuration options not yet in the SDK
  • Handling fields that may be added to the Auth0 API
  • Accessing beta or experimental API features

ExtraProperties Field

Some SDK types include an ExtraProperties field (map[string]interface{}) that works in both directions:
  • In Requests: Send additional fields to Auth0
  • In Responses: Capture additional fields returned by Auth0

Setting ExtraProperties in Requests

Add custom fields directly to request structures:
import (
    "context"
    "github.com/auth0/go-auth0/v2/management"
)

ctx := context.Background()

// Example: Creating a connection with extra properties
createRequest := &management.CreateConnectionRequestContent{
    Name:     "My Custom DB",
    Strategy: management.ConnectionIdentityProviderEnumAuth0,
    Options: &management.ConnectionPropertiesOptions{
        ImportMode: management.Bool(true),
        // Set extra properties directly on the struct
        ExtraProperties: map[string]interface{}{
            "custom_timeout":     30,
            "retry_policy":       "exponential_backoff",
            "webhook_endpoints": []string{
                "https://api.example.com/auth-webhook",
                "https://backup.example.com/auth-webhook",
            },
            "advanced_config": map[string]interface{}{
                "enable_debug_logs": true,
                "api_version":       "v2.1",
                "custom_headers": map[string]string{
                    "X-Custom-Source": "auth0-sdk",
                    "X-Environment":   "production",
                },
            },
        },
    },
}

newConn, err := mgmt.Connections.Create(ctx, createRequest)
if err != nil {
    return err
}

Nested ExtraProperties Example

Complex nested structures work seamlessly:
updateRequest := &management.UpdateConnectionRequestContent{
    Options: &management.ConnectionPropertiesOptions{
        ExtraProperties: map[string]interface{}{
            "maintenance_mode":    false,
            "last_updated_by":     "admin-user-123",
            "migration_settings": map[string]interface{}{
                "batch_size":     1000,
                "rate_limit_ms":  100,
                "error_handling": "continue",
                "transformations": []map[string]interface{}{
                    {
                        "field":     "email",
                        "operation": "lowercase",
                    },
                    {
                        "field":     "phone",
                        "operation": "normalize",
                        "format":    "E.164",
                    },
                },
            },
        },
    },
}

updatedConn, err := mgmt.Connections.Update(ctx, "con_123", updateRequest)

Reading ExtraProperties from Responses

Access additional fields returned by Auth0:
conn, err := mgmt.Connections.Get(ctx, "con_123")
if err != nil {
    return err
}

if conn.Options != nil && conn.Options.ExtraProperties != nil {
    // Access custom fields from the response
    if timeout, ok := conn.Options.ExtraProperties["custom_timeout"].(float64); ok {
        fmt.Printf("Custom timeout: %v seconds\n", timeout)
    }

    if config, ok := conn.Options.ExtraProperties["advanced_config"].(map[string]interface{}); ok {
        if debugLogs, ok := config["enable_debug_logs"].(bool); ok {
            fmt.Printf("Debug logs enabled: %v\n", debugLogs)
        }
    }
}

WithBodyProperties Request Option

The WithBodyProperties option allows adding custom fields to any request body, even for types without ExtraProperties:
import (
    "github.com/auth0/go-auth0/v2/management/option"
)

// Example: Creating a client with additional custom properties
customBodyProps := map[string]interface{}{
    "custom_domain_verified": true,
    "integration_metadata": map[string]interface{}{
        "source":      "terraform",
        "environment": "production",
        "team":        "platform",
    },
    "advanced_settings": map[string]interface{}{
        "custom_login_page":         true,
        "universal_login_branding":  true,
    },
}

createRequest := &management.CreateClientRequestContent{
    Name:    "My Custom App",
    AppType: &management.ClientAppTypeEnumSpa,
    Callbacks: []string{"https://myapp.com/callback"},
}

client, err := mgmt.Clients.Create(
    ctx,
    createRequest,
    option.WithBodyProperties(customBodyProps),
)

Setting Fields to Null

Use WithBodyProperties to explicitly set fields to null:
_, err := mgmt.Clients.Update(
    ctx,
    clientID,
    &management.UpdateClientRequestContent{
        Name: management.String("Updated App Name"),
    },
    option.WithBodyProperties(map[string]interface{}{
        "description":     nil, // This will set description to null
        "logo_uri":        "https://example.com/new-logo.png",
        "custom_metadata": nil, // This will set custom_metadata to null
    }),
)

ExtraProperties vs WithBodyProperties

ExtraProperties

When to use:
  • Type has ExtraProperties field
  • Need to read extra fields from responses
  • Want type-safe structure access
Pros:
  • More idiomatic Go code
  • Access to response extra fields
  • Clear structure in code

WithBodyProperties

When to use:
  • Type lacks ExtraProperties field
  • Need to set fields to null
  • Adding fields to any request
Pros:
  • Works with any request type
  • Can override standard fields
  • Flexible for one-off needs

Combining Both Approaches

You can use both mechanisms together:
createRequest := &management.CreateConnectionRequestContent{
    Name:     "My Connection",
    Strategy: management.ConnectionIdentityProviderEnumAuth0,
    Options: &management.ConnectionPropertiesOptions{
        // Standard ExtraProperties
        ExtraProperties: map[string]interface{}{
            "connection_level_field": "value",
        },
    },
}

// Add additional top-level fields
newConn, err := mgmt.Connections.Create(
    ctx,
    createRequest,
    option.WithBodyProperties(map[string]interface{}{
        "top_level_custom_field": "value",
        "experimental_feature":   true,
    }),
)

Type Assertions and Safety

When reading from ExtraProperties, always use type assertions safely:
if conn.Options != nil && conn.Options.ExtraProperties != nil {
    // Safe type assertion with check
    if value, ok := conn.Options.ExtraProperties["field_name"].(string); ok {
        fmt.Printf("Field value: %s\n", value)
    }

    // Handle different types
    switch v := conn.Options.ExtraProperties["dynamic_field"].(type) {
    case string:
        fmt.Printf("String value: %s\n", v)
    case float64:
        fmt.Printf("Numeric value: %f\n", v)
    case bool:
        fmt.Printf("Boolean value: %t\n", v)
    case map[string]interface{}:
        fmt.Printf("Object value: %+v\n", v)
    case []interface{}:
        fmt.Printf("Array value: %+v\n", v)
    default:
        fmt.Printf("Unknown type: %T\n", v)
    }
}

JSON Number Handling

JSON numbers are decoded as float64 by default. For integer values, cast accordingly:
if timeout, ok := props["timeout"].(float64); ok {
    timeoutInt := int(timeout)
    fmt.Printf("Timeout: %d seconds\n", timeoutInt)
}

Real-World Examples

Custom Client Metadata

// Track deployment metadata in client applications
customProps := map[string]interface{}{
    "deployment": map[string]interface{}{
        "deployed_by":   "ci-pipeline",
        "deployed_at":   time.Now().Format(time.RFC3339),
        "version":       "1.2.3",
        "git_commit":    "a1b2c3d4",
        "environment":   "production",
    },
    "monitoring": map[string]interface{}{
        "datadog_enabled":    true,
        "sentry_enabled":     true,
        "log_level":          "info",
    },
}

client, err := mgmt.Clients.Create(
    ctx,
    createRequest,
    option.WithBodyProperties(customProps),
)

Connection Configuration

// Advanced connection settings
connRequest := &management.CreateConnectionRequestContent{
    Name:     "Enterprise SAML",
    Strategy: management.ConnectionIdentityProviderEnumSamlp,
    Options: &management.ConnectionPropertiesOptions{
        ExtraProperties: map[string]interface{}{
            "sign_in_endpoint":     "https://idp.example.com/sso",
            "sign_out_endpoint":    "https://idp.example.com/logout",
            "signing_cert":         certString,
            "protocol_binding":     "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
            "request_template":     customTemplate,
            "user_id_attribute":    "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
            "debug":                true,
            "signature_algorithm": "rsa-sha256",
            "digest_algorithm":     "sha256",
        },
    },
}

Best Practices

1

Document Custom Fields

Maintain documentation of any custom fields you use, including their purpose, type, and valid values.
2

Validate Before Sending

Validate custom field values before sending to avoid API errors:
if timeout < 0 || timeout > 300 {
    return errors.New("timeout must be between 0 and 300")
}
3

Handle Missing Fields

Always check if fields exist before accessing them:
if props := conn.Options.ExtraProperties; props != nil {
    if value, ok := props["field"]; ok {
        // Use value
    }
}
4

Use Typed Wrappers

For frequently used custom fields, create typed wrapper functions:
func GetCustomTimeout(conn *management.Connection) (int, bool) {
    if conn.Options == nil || conn.Options.ExtraProperties == nil {
        return 0, false
    }
    if timeout, ok := conn.Options.ExtraProperties["custom_timeout"].(float64); ok {
        return int(timeout), true
    }
    return 0, false
}

Build docs developers (and LLMs) love