Adding a New Auth Method
Steps
- Create the auth client in
internal/auth/<name>.go - Implement the
Authenticatorinterface - Add type constant to
internal/auth/auth.go - Add YAML decoder to
internal/config/auth.go - Register decoder in the
authDecodersmap - Write tests
1. Auth client
Create internal/auth/my_auth.go:
package auth
import "net/http"
type MyAuthClient struct {
Token string `yaml:"token" validate:"required"`
}
func (c *MyAuthClient) New() error {
c.Token = resolveEnv(c.Token)
return nil
}
func (c *MyAuthClient) Type() Type {
return MyAuth
}
func (c *MyAuthClient) Apply(req *http.Request, out *Info) error {
if c.Token == "" {
return nil
}
setAuthHeader(req, out, "X-My-Auth", c.Token)
return nil
}
func (c *MyAuthClient) Validate() error {
return authValidator.Struct(c)
}2. Authenticator interface
Every auth client must implement:
type Authenticator interface {
New() error // Initialize, resolve env vars
Type() Type // Return the auth type identifier
Apply(req *http.Request, out *Info) error // Apply auth to request
Validate() error // Validate required fields
}3. Type constant
Add to internal/auth/auth.go:
const MyAuth Type = "my-auth"4. YAML decoder
Add a decoder function in internal/config/auth.go. The decoder receives a *yaml.Node and must decode it into your auth client struct:
func decodeMyAuth(node *yaml.Node) (auth.Authenticator, error) {
var client auth.MyAuthClient
if err := decodeConfig(node, &client); err != nil {
return nil, err
}
return &client, nil
}The decodeConfig helper handles the common pattern: it checks that the node is not empty, decodes YAML into the struct, and returns a descriptive error on failure.
5. Register decoder
Add your decoder to the authDecoders map in internal/config/auth.go:
var authDecoders = map[string]authDecoder{
// ... existing decoders
auth.MyAuth.String(): decodeMyAuth,
}The UnmarshalYAML method on Auth reads the type field from the YAML, normalises underscores to hyphens, looks up the decoder in authDecoders, and calls it with the config node. This is how swag2mcp knows which auth client to instantiate for each spec.
6. Tests
Create internal/auth/my_auth_test.go with table-driven tests covering:
New()resolves env vars correctlyType()returns the correct typeApply()sets the right headers/query paramsApply()handles empty values gracefullyValidate()passes for valid configValidate()fails for missing required fields