Skip to content

Add support for domain metadata in CustomDomain struct, implement ListWithPagination method, and update Management options with WithCustomDomainHeader #551

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

developerkunal
Copy link
Contributor

🔧 Changes

  • Added support for domain metadata to the CustomDomain struct.
  • Implemented the ListWithPagination method to handle paginated results in domain listing.
  • Updated Management options with the WithCustomDomainHeader to allow setting a custom domain for requests.
  • Refactored custom domain manager tests to incorporate domain metadata and pagination.
  • Added CustomDomainHeader option to request options to apply a custom domain header on a per-request basis.

🌟 Examples

Managing Custom Domain Metadata

You can associate custom metadata (key-value pairs) with your custom domains.

1. Creating a Custom Domain with Metadata

When creating a new custom domain, you can include a DomainMetadata field.

import (
    "context"
    "fmt"

    "github.com/auth0/go-auth0"
    "github.com/auth0/go-auth0/management"
)

func ExampleCreateCustomDomainWithMetadata() {
    // Initialize your Management API client (apiClient)
    // var apiClient *management.Management = ...

    customDomain := &management.CustomDomain{
        Domain:    auth0.String("shop.example-app.com"),
        Type:      auth0.String(management.CustomDomainTypeAuth0ManagedCerts), // Or management.CustomDomainTypeSelfManagedCerts
        TLSPolicy: auth0.String(management.CustomDomainTLSPolicyRecommended),
        DomainMetadata: map[string]interface{}{
            "region":      "eu-central-1",
            "environment": "production",
            "team_owner":  "checkout-squad",
        },
    }

    err := apiClient.CustomDomain.Create(context.Background(), customDomain)
    if err != nil {
        fmt.Printf("Error creating custom domain: %v\n", err)
        return
    }

    fmt.Printf("Custom domain %s created successfully with ID: %s\n", *customDomain.Domain, *customDomain.ID)
    fmt.Printf("Metadata: %v\n", customDomain.DomainMetadata)
}

2. Updating Custom Domain Metadata

You can update the metadata of an existing custom domain. To remove a metadata key, set its value to nil or an empty map if you want to clear all metadata.

import (
    "context"
    "fmt"

    "github.com/auth0/go-auth0"
    "github.com/auth0/go-auth0/management"
)

func ExampleUpdateCustomDomainMetadata() {
    // Initialize your Management API client (apiClient)
    // var apiClient *management.Management = ...
    // var customDomainID string = "cd_..." // ID of the custom domain to update

    // To add or modify metadata keys:
    updatedMetadata := &management.CustomDomain{
        DomainMetadata: map[string]interface{}{
            "region":      "us-east-1",       // Update existing key
            "sla_tier":    "premium",         // Add new key
            "team_owner":  "core-infra",      // Update existing key
            "environment": nil,               // To remove the 'environment' key
        },
    }

    err := apiClient.CustomDomain.Update(context.Background(), customDomainID, updatedMetadata)
    if err != nil {
        fmt.Printf("Error updating custom domain metadata: %v\n", err)
        return
    }
    fmt.Printf("Custom domain %s metadata updated.\n", customDomainID)
}

3. Listing Custom Domains with Pagination

The ListWithPagination method allows you to retrieve custom domains in pages, which is useful for tenants with a large number of custom domains. It uses checkpoint pagination.

import (
    "context"
    "fmt"

    "github.com/auth0/go-auth0"
    "github.com/auth0/go-auth0/management"
)

func ExampleListCustomDomainsWithPagination() {
    var allCustomDomains []*management.CustomDomain
    var nextCheckpoint string

    fmt.Println("Fetching custom domains...")

    for {
        requestOptions := []management.RequestOption{management.Take(5)}
        if nextCheckpoint != "" {
            requestOptions = append(requestOptions, management.From(nextCheckpoint))
        }

        pageResult, err := apiClient.CustomDomain.ListWithPagination(context.Background(), requestOptions...)
        if err != nil {
            fmt.Println("Error:", err)
            return
        }

        if len(pageResult.CustomDomains) == 0 {
            fmt.Println("No more pages.")
            break
        }

        allCustomDomains = append(allCustomDomains, pageResult.CustomDomains...)

        for _, cd := range pageResult.CustomDomains {
            fmt.Printf("Domain: %s, ID: %s\n", *cd.Domain, *cd.ID)
        }

        if pageResult.Next == "" {
            break
        }
        nextCheckpoint = pageResult.Next
    }

    fmt.Printf("Total custom domains: %d\n", len(allCustomDomains))
}

4. Using Custom Domain Headers

You can configure the SDK to send an Auth0-Custom-Domain header. This is useful in scenarios where Auth0 needs to know the original custom domain a request was intended for, especially for certain email templates or universal login flows.

  • WithCustomDomainHeader (Management Option)

This option sets a custom domain header globally for all requests made by a management client instance. The header is only applied if the request path is whitelisted (e.g., /api/v2/users, /api/v2/jobs/verification-email).

import (
    "context"
    "fmt"

    "github.com/auth0/go-auth0/management"
)

func ExampleWithCustomDomainHeader() {
    // Initialize Management client with the global custom domain header
    apiClient, err := management.New(
        "YOUR_AUTH0_TENANT_DOMAIN", // e.g., my-tenant.auth0.com
        management.WithClientCredentials(context.Background(), "YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET"),
        management.WithCustomDomainHeader("login.mycompany.com"), // Global custom domain
    )
    if err != nil {
        fmt.Printf("Error creating management client: %v\n", err)
        return
    }

    fmt.Println("Management client initialized with global custom domain header: login.mycompany.com")

    // Example: Create a new user
    user := &management.User{
        Email:    management.String("[email protected]"),
        Password: management.String("password123"),
        Connection: management.String("Username-Password-Authentication"),
    }

    createdUser, err := apiClient.User.Create(context.Background(), user)
    if err != nil {
        fmt.Printf("Error creating user: %v\n", err)
        return
    }

    fmt.Printf("Successfully created user with ID: %s\n", *createdUser.ID)

    // Example: Request to a whitelisted endpoint (e.g., creating a user)
    // The "Auth0-Custom-Domain: login.mycompany.com" header WILL be sent.
    fmt.Println("Header 'Auth0-Custom-Domain: login.mycompany.com' would be sent with the user creation request.")
}
  • CustomDomainHeader (Request Option)

This option sets or overrides the Auth0-Custom-Domain header for a specific API request. It takes precedence over any globally set header via WithCustomDomainHeader and applies regardless of whether the endpoint is whitelisted for the global option.

import (
    "context"
    "fmt"

    "github.com/auth0/go-auth0/management"
)

func ExampleCustomDomainHeaderRequestOption() {
    // Initialize Management client with a global custom domain header
    apiClient, err := management.New(
        "YOUR_AUTH0_TENANT_DOMAIN",
        management.WithClientCredentials(context.Background(), "YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET"),
        management.WithCustomDomainHeader("global.login.mycompany.com"), // Global setting
    )
    if err != nil {
        fmt.Printf("Error creating management client: %v\n", err)
        return
    }
    fmt.Println("Management client initialized with global custom domain: global.login.mycompany.com")

    // Create a user with a per-request custom domain header
    user := &management.User{
        Email:      management.String("[email protected]"),
        Password:   management.String("password123"),
        Connection: management.String("Username-Password-Authentication"),
    }

    createdUser, err := apiClient.User.Create(
        context.Background(),
        user,
        management.CustomDomainHeader("specific-user-request.mycompany.com"), // Per-request override
    )
    if err != nil {
        fmt.Printf("Error creating user with per-request header: %v\n", err)
    } else {
        fmt.Printf("Created user with ID: %s and per-request header 'Auth0-Custom-Domain: specific-user-request.mycompany.com'.\n", *createdUser.ID)
    }
}
import (
    "context"
    "fmt"

    "github.com/auth0/go-auth0/management"
)

func ExampleCreateUserWithCustomDomainHeader() {
    // Initialize your Management API client
    apiClient, err := management.New(
        "YOUR_AUTH0_TENANT_DOMAIN", // e.g., my-tenant.auth0.com
        management.WithClientCredentials(context.Background(), "YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET"),
    )
    if err != nil {
        fmt.Printf("Error creating management client: %v\n", err)
        return
    }

    // Create a new user with a per-request custom domain header
    user := &management.User{
        Email:      management.String("[email protected]"),
        Password:   management.String("password123"),
        Connection: management.String("Username-Password-Authentication"),
    }

    createdUser, err := apiClient.User.Create(
        context.Background(),
        user,
        management.CustomDomainHeader("specific-user-request.mycompany.com"), // Per-request custom domain header
    )
    if err != nil {
        fmt.Printf("Error creating user with per-request header: %v\n", err)
        return
    }

    fmt.Printf("Successfully created user with ID: %s and per-request custom domain header 'Auth0-Custom-Domain: specific-user-request.mycompany.com'.\n", *createdUser.ID)
}

📚 References

🔬 Testing

  • Test the updated custom domain manager functionality, ensuring that domain metadata is handled correctly.
  • Verify that pagination works with the new ListWithPagination method.
  • Confirm that custom domain headers are being applied properly with the new Management option WithCustomDomainHeader and the CustomDomainHeader in request options.

📝 Checklist

  • All new/changed/fixed functionality is covered by tests (or N/A)
  • I have added documentation for all new/changed functionality (or N/A)

…pagination test, and update Management options with WithCustomDomainHeader for custom domain handling
@developerkunal developerkunal requested a review from a team as a code owner May 8, 2025 09:05
@codecov-commenter
Copy link

codecov-commenter commented May 8, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 95.96%. Comparing base (05d9865) to head (2a31f03).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #551      +/-   ##
==========================================
+ Coverage   95.93%   95.96%   +0.03%     
==========================================
  Files          60       60              
  Lines       11968    12063      +95     
==========================================
+ Hits        11481    11576      +95     
  Misses        367      367              
  Partials      120      120              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants