Add support for `domain metadata` in `CustomDomain` struct, implement `ListWithPagination` method, and update Management options with `WithCustomDomainHeader`
🔧 Changes
- Added support for domain metadata to the
CustomDomainstruct. - Implemented the
ListWithPaginationmethod to handle paginated results in domain listing. - Updated Management options with the
WithCustomDomainHeaderto allow setting a custom domain for requests. - Refactored custom domain manager tests to incorporate domain metadata and pagination.
- Added
CustomDomainHeaderoption 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
ListWithPaginationmethod. - Confirm that custom domain headers are being applied properly with the new Management option
WithCustomDomainHeaderand theCustomDomainHeaderin request options.
📝 Checklist
- [x] All new/changed/fixed functionality is covered by tests (or N/A)
- [x] I have added documentation for all new/changed functionality (or N/A)
Codecov Report
All modified and coverable lines are covered by tests :white_check_mark:
Project coverage is 96.01%. Comparing base (
dd66229) to head (5417e8a).
Additional details and impacted files
@@ Coverage Diff @@
## main #551 +/- ##
==========================================
+ Coverage 95.98% 96.01% +0.03%
==========================================
Files 60 60
Lines 12131 12226 +95
==========================================
+ Hits 11644 11739 +95
Misses 367 367
Partials 120 120
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.