// Package client provides clients for communicating with sibling services. package client import ( "context" "fmt" "net/http" "git.threesix.ai/jordan/sp4-verify-1770325799/pkg/auth" "git.threesix.ai/jordan/sp4-verify-1770325799/pkg/svc" ) // AuthClient communicates with the auth-svc for token validation. type AuthClient struct { client *svc.Client } // ValidateResponse is the response from the auth-svc /validate endpoint. type ValidateResponse struct { Data struct { Valid bool `json:"valid"` User *auth.User `json:"user,omitempty"` Error string `json:"error,omitempty"` } `json:"data"` } // NewAuthClient creates a new client for the auth-svc. // Returns an error if AUTH_SVC_URL is not configured. func NewAuthClient() (*AuthClient, error) { client, err := svc.NewClient("auth-svc") if err != nil { return nil, err } return &AuthClient{client: client}, nil } // ValidateToken validates a JWT token by calling auth-svc. // Returns the user if valid, or an error if invalid or communication fails. func (c *AuthClient) ValidateToken(ctx context.Context, token string) (*auth.User, error) { req, err := c.client.NewRequest(ctx, http.MethodGet, "/api/auth-svc/validate", nil) if err != nil { return nil, fmt.Errorf("create request: %w", err) } req.Header.Set("Authorization", "Bearer "+token) resp, err := c.client.DoRequest(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("decode response: %w", err) } if !result.Data.Valid { return nil, fmt.Errorf("token validation failed: %s", result.Data.Error) } return result.Data.User, nil } // ValidateTokenWithHeader validates a token by forwarding the Authorization header. func (c *AuthClient) ValidateTokenWithHeader(ctx context.Context, authHeader string) (*auth.User, error) { req, err := c.client.NewRequest(ctx, http.MethodGet, "/api/auth-svc/validate", nil) if err != nil { return nil, fmt.Errorf("create request: %w", err) } req.Header.Set("Authorization", authHeader) resp, err := c.client.DoRequest(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("decode response: %w", err) } if !result.Data.Valid { return nil, fmt.Errorf("token validation failed: %s", result.Data.Error) } return result.Data.User, nil }