diff --git a/auth/auth.go b/auth/auth.go index e5bb4c4..6264f13 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -73,6 +73,11 @@ type TokenInfo struct { // Username is the MCIAS username (the "sub" claim). Username string + // AccountType is the MCIAS account type: "human" or "system". + // Used by policy engines that need to distinguish interactive users + // from service accounts. + AccountType string + // Roles is the set of MCIAS roles assigned to the account. Roles []string @@ -193,10 +198,11 @@ func (a *Authenticator) ValidateToken(token string) (*TokenInfo, error) { } var resp struct { - Valid bool `json:"valid"` - Sub string `json:"sub"` - Username string `json:"username"` - Roles []string `json:"roles"` + Valid bool `json:"valid"` + Sub string `json:"sub"` + Username string `json:"username"` + AccountType string `json:"account_type"` + Roles []string `json:"roles"` } status, err := a.doJSON(http.MethodPost, "/v1/token/validate", map[string]string{"token": token}, &resp) @@ -209,9 +215,10 @@ func (a *Authenticator) ValidateToken(token string) (*TokenInfo, error) { } info := &TokenInfo{ - Username: resp.Username, - Roles: resp.Roles, - IsAdmin: hasRole(resp.Roles, "admin"), + Username: resp.Username, + AccountType: resp.AccountType, + Roles: resp.Roles, + IsAdmin: hasRole(resp.Roles, "admin"), } if info.Username == "" { info.Username = resp.Sub diff --git a/auth/auth_test.go b/auth/auth_test.go index b6efaee..a113c46 100644 --- a/auth/auth_test.go +++ b/auth/auth_test.go @@ -54,18 +54,20 @@ func mockMCIAS(t *testing.T) *httptest.Server { case "tok-admin-123": w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(map[string]interface{}{ - "valid": true, - "sub": "uuid-admin", - "username": "admin", - "roles": []string{"admin", "user"}, + "valid": true, + "sub": "uuid-admin", + "username": "admin", + "account_type": "human", + "roles": []string{"admin", "user"}, }) case "tok-user-456": w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(map[string]interface{}{ - "valid": true, - "sub": "uuid-user", - "username": "alice", - "roles": []string{"user"}, + "valid": true, + "sub": "uuid-user", + "username": "alice", + "account_type": "human", + "roles": []string{"user"}, }) case "tok-expired": w.Header().Set("Content-Type", "application/json") @@ -154,6 +156,9 @@ func TestValidateToken(t *testing.T) { if info.Username != "admin" { t.Fatalf("Username = %q, want %q", info.Username, "admin") } + if info.AccountType != "human" { + t.Fatalf("AccountType = %q, want %q", info.AccountType, "human") + } if !info.IsAdmin { t.Fatal("IsAdmin = false, want true") }