Add AccountType to TokenInfo
- TokenInfo now includes AccountType ("human" or "system") from the
MCIAS validate response
- Required for policy engines (MCR, Metacrypt) that match on account type
- Mock MCIAS in tests updated to return account_type
- New assertion in TestValidateToken verifies AccountType is populated
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
21
auth/auth.go
21
auth/auth.go
@@ -73,6 +73,11 @@ type TokenInfo struct {
|
|||||||
// Username is the MCIAS username (the "sub" claim).
|
// Username is the MCIAS username (the "sub" claim).
|
||||||
Username string
|
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 is the set of MCIAS roles assigned to the account.
|
||||||
Roles []string
|
Roles []string
|
||||||
|
|
||||||
@@ -193,10 +198,11 @@ func (a *Authenticator) ValidateToken(token string) (*TokenInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var resp struct {
|
var resp struct {
|
||||||
Valid bool `json:"valid"`
|
Valid bool `json:"valid"`
|
||||||
Sub string `json:"sub"`
|
Sub string `json:"sub"`
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Roles []string `json:"roles"`
|
AccountType string `json:"account_type"`
|
||||||
|
Roles []string `json:"roles"`
|
||||||
}
|
}
|
||||||
status, err := a.doJSON(http.MethodPost, "/v1/token/validate",
|
status, err := a.doJSON(http.MethodPost, "/v1/token/validate",
|
||||||
map[string]string{"token": token}, &resp)
|
map[string]string{"token": token}, &resp)
|
||||||
@@ -209,9 +215,10 @@ func (a *Authenticator) ValidateToken(token string) (*TokenInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
info := &TokenInfo{
|
info := &TokenInfo{
|
||||||
Username: resp.Username,
|
Username: resp.Username,
|
||||||
Roles: resp.Roles,
|
AccountType: resp.AccountType,
|
||||||
IsAdmin: hasRole(resp.Roles, "admin"),
|
Roles: resp.Roles,
|
||||||
|
IsAdmin: hasRole(resp.Roles, "admin"),
|
||||||
}
|
}
|
||||||
if info.Username == "" {
|
if info.Username == "" {
|
||||||
info.Username = resp.Sub
|
info.Username = resp.Sub
|
||||||
|
|||||||
@@ -54,18 +54,20 @@ func mockMCIAS(t *testing.T) *httptest.Server {
|
|||||||
case "tok-admin-123":
|
case "tok-admin-123":
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
_ = json.NewEncoder(w).Encode(map[string]interface{}{
|
_ = json.NewEncoder(w).Encode(map[string]interface{}{
|
||||||
"valid": true,
|
"valid": true,
|
||||||
"sub": "uuid-admin",
|
"sub": "uuid-admin",
|
||||||
"username": "admin",
|
"username": "admin",
|
||||||
"roles": []string{"admin", "user"},
|
"account_type": "human",
|
||||||
|
"roles": []string{"admin", "user"},
|
||||||
})
|
})
|
||||||
case "tok-user-456":
|
case "tok-user-456":
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
_ = json.NewEncoder(w).Encode(map[string]interface{}{
|
_ = json.NewEncoder(w).Encode(map[string]interface{}{
|
||||||
"valid": true,
|
"valid": true,
|
||||||
"sub": "uuid-user",
|
"sub": "uuid-user",
|
||||||
"username": "alice",
|
"username": "alice",
|
||||||
"roles": []string{"user"},
|
"account_type": "human",
|
||||||
|
"roles": []string{"user"},
|
||||||
})
|
})
|
||||||
case "tok-expired":
|
case "tok-expired":
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
@@ -154,6 +156,9 @@ func TestValidateToken(t *testing.T) {
|
|||||||
if info.Username != "admin" {
|
if info.Username != "admin" {
|
||||||
t.Fatalf("Username = %q, want %q", 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 {
|
if !info.IsAdmin {
|
||||||
t.Fatal("IsAdmin = false, want true")
|
t.Fatal("IsAdmin = false, want true")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user