// Package authclient provides a client for validating tokens via the auth-svc. package authclient import ( "context" "fmt" "net/http" "git.threesix.ai/jordan/sp4-debug-1770477266/pkg/auth" "git.threesix.ai/jordan/sp4-debug-1770477266/pkg/httpclient" "git.threesix.ai/jordan/sp4-debug-1770477266/pkg/logging" "git.threesix.ai/jordan/sp4-debug-1770477266/pkg/svc" ) // ValidateResponse is the envelope response from auth-svc /validate endpoint. type ValidateResponse struct { Data ValidateData `json:"data"` } // ValidateData is the user info returned by auth-svc. type ValidateData struct { UserID string `json:"user_id"` Email string `json:"email,omitempty"` Roles []string `json:"roles,omitempty"` Scopes []string `json:"scopes,omitempty"` } // Client validates tokens by calling auth-svc. type Client struct { baseURL string httpClient *httpclient.Client logger *logging.Logger } // New creates a new auth client that calls auth-svc/validate. // Requires AUTH_SVC_URL environment variable to be set. func New(logger *logging.Logger) (*Client, error) { baseURL := svc.ServiceURL("auth-svc") if baseURL == "" { return nil, fmt.Errorf("auth-svc not configured (missing AUTH_SVC_URL env var)") } return &Client{ baseURL: baseURL, httpClient: httpclient.New(httpclient.Config{}), logger: logger.WithComponent("authclient"), }, nil } // Validate calls POST /api/auth-svc/validate with the Bearer token. // Returns the authenticated user or an error. func (c *Client) Validate(ctx context.Context, token string) (*auth.User, error) { url := c.baseURL + "/api/auth-svc/validate" req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, nil) if err != nil { return nil, fmt.Errorf("create request: %w", err) } req.Header.Set("Authorization", "Bearer "+token) req.Header.Set("Accept", "application/json") resp, err := c.httpClient.Do(req) if err != nil { return nil, fmt.Errorf("call auth-svc: %w", err) } result, err := svc.DecodeResponse[ValidateResponse](resp) if err != nil { return nil, fmt.Errorf("auth-svc validation failed: %w", err) } return &auth.User{ ID: result.Data.UserID, Email: result.Data.Email, Roles: result.Data.Roles, Scopes: result.Data.Scopes, }, nil }