Files
mcias/clients/go
Kyle Isom 39d9ffb79a Add service-context login policy enforcement
Services send service_name and tags in POST /v1/auth/login.
MCIAS evaluates auth:login policy with these as the resource
context after credentials are verified, enabling rules like:
  deny guest/viewer human accounts from env:restricted services
  deny guest accounts from specific named services

- loginRequest: add ServiceName and Tags fields
- handleLogin: evaluate policy after credential+TOTP check;
  policy deny returns 403 (not 401) to distinguish access
  restriction from bad credentials
- Go client: Options.ServiceName/Tags stored on Client,
  sent automatically in every Login() call
- Python client: service_name/tags on __init__, sent in login()
- Rust client: ClientOptions.service_name/tags, LoginRequest
  fields, Client stores and sends them in login()
- openapi.yaml: document service_name/tags request fields
  and 403 response for policy-denied logins
- engineering-standards.md: document service_name/tags in
  [mcias] config section with policy examples

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 21:11:35 -07:00
..

mcias-client (Go)

Go client library for the MCIAS identity and access management API.

Requirements

  • Go 1.21+

Installation

go get git.wntrmute.dev/kyle/mcias/clients/go

Quick Start

import "git.wntrmute.dev/kyle/mcias/clients/go/mcias"

// Connect to the MCIAS server.
client, err := mcias.New("https://auth.example.com", mcias.Options{})
if err != nil {
    log.Fatal(err)
}

// Authenticate.
token, expiresAt, err := client.Login("alice", "s3cret", "")
if err != nil {
    log.Fatal(err)
}
fmt.Printf("token expires at %s\n", expiresAt)

// The token is stored in the client automatically.
// Call authenticated endpoints...
accounts, err := client.ListAccounts()

// Revoke the token when done.
if err := client.Logout(); err != nil {
    log.Fatal(err)
}

Custom CA Certificate

client, err := mcias.New("https://auth.example.com", mcias.Options{
    CACertPath: "/etc/mcias/ca.pem",
})

Error Handling

All methods return typed errors:

_, _, err := client.Login("alice", "wrongpass", "")
switch {
case errors.Is(err, new(mcias.MciasAuthError)):
    // 401 — wrong credentials or token invalid
case errors.Is(err, new(mcias.MciasForbiddenError)):
    // 403 — insufficient role
case errors.Is(err, new(mcias.MciasNotFoundError)):
    // 404 — resource not found
case errors.Is(err, new(mcias.MciasInputError)):
    // 400 — malformed request
case errors.Is(err, new(mcias.MciasConflictError)):
    // 409 — conflict (e.g. duplicate username)
case errors.Is(err, new(mcias.MciasServerError)):
    // 5xx — unexpected server error
}

All error types embed MciasError which carries StatusCode int and Message string.

Thread Safety

Client is safe for concurrent use from multiple goroutines. The internal token is protected by sync.RWMutex.

Running Tests

go test -race ./...