package auth import ( "errors" "log/slog" mcdslauth "git.wntrmute.dev/kyle/mcdsl/auth" ) // Client communicates with an MCIAS server for authentication and token // validation. It delegates to mcdsl/auth.Authenticator and adapts the // results to MCR's Claims type (which includes AccountType for the policy // engine). type Client struct { auth *mcdslauth.Authenticator } // NewClient creates an auth Client that talks to the MCIAS server at // serverURL. If caCert is non-empty, it is used as a custom CA cert. // TLS 1.3 is required for all HTTPS connections. func NewClient(serverURL, caCert, serviceName string, tags []string) (*Client, error) { a, err := mcdslauth.New(mcdslauth.Config{ ServerURL: serverURL, CACert: caCert, ServiceName: serviceName, Tags: tags, }, slog.Default()) if err != nil { return nil, err } return &Client{auth: a}, nil } // Login authenticates a user against MCIAS and returns a bearer token. func (c *Client) Login(username, password string) (token string, expiresIn int, err error) { tok, _, loginErr := c.auth.Login(username, password, "") if loginErr != nil { if errors.Is(loginErr, mcdslauth.ErrForbidden) { return "", 0, ErrForbidden } if errors.Is(loginErr, mcdslauth.ErrInvalidCredentials) { return "", 0, ErrUnauthorized } return "", 0, loginErr } return tok, 0, nil } // ValidateToken checks a bearer token against MCIAS. Results are cached // by SHA-256 hash for 30 seconds (handled by mcdsl/auth). func (c *Client) ValidateToken(token string) (*Claims, error) { info, err := c.auth.ValidateToken(token) if err != nil { if errors.Is(err, mcdslauth.ErrInvalidToken) { return nil, ErrUnauthorized } return nil, ErrMCIASUnavailable } return &Claims{ Subject: info.Username, Roles: info.Roles, }, nil }