wip: account details from az and the token

This commit is contained in:
keb committed 2026-10-11 10:06:41 +02:00
1 parent 87d98d038d
commit 482e0805b7
6 files changed
+218 -17

No files matched your search

+28 -9
View File
@@ -42,6 +42,16 @@ type cliCredential struct {
mu sync.Mutex
cache map[string]azcore.AccessToken // by resource and tenant argument
// last is the claims of the latest token in the account's own
// tenant, to describe the account (Provider.Account).
last map[string]any
}
// claims are the latest token's claims, nil before the first.
func (c *cliCredential) claims() map[string]any {
c.mu.Lock()
defer c.mu.Unlock()
return c.last
}
func newCLICredential(user, tenant string, accounts func() ([]account, error)) *cliCredential {
@@ -110,29 +120,38 @@ func (c *cliCredential) GetToken(ctx context.Context, opts policy.TokenRequestOp
if err != nil {
return azcore.AccessToken{}, err
}
if u, ok := tokenUser(tok.Token, others); ok {
claims := tokenClaims(tok.Token)
if u, ok := tokenUser(claims, others); ok {
return azcore.AccessToken{}, fmt.Errorf("az gave a token for %s, not %s: sign in as %s again", u, c.user, c.user)
}
if !otherTenant && claims != nil {
c.last = claims
}
c.cache[key] = tok
return tok, nil
}
// tokenUser reports which of users a token was issued to, if any, from
// its claims. The token isn't verified: this only catches az picking the
// wrong signed-in account.
func tokenUser(token string, users []string) (string, bool) {
// tokenClaims reads a JWT's claims, without verifying it: they only
// describe the account and catch az picking the wrong one. nil if it
// isn't a JWT.
func tokenClaims(token string) map[string]any {
parts := strings.Split(token, ".")
if len(parts) != 3 || len(users) == 0 {
return "", false
if len(parts) != 3 {
return nil
}
b, err := base64.RawURLEncoding.DecodeString(strings.TrimRight(parts[1], "="))
if err != nil {
return "", false
return nil
}
var claims map[string]any
if json.Unmarshal(b, &claims) != nil {
return "", false
return nil
}
return claims
}
// tokenUser reports which of users a token's claims are for, if any.
func tokenUser(claims map[string]any, users []string) (string, bool) {
for _, name := range []string{"upn", "unique_name", "preferred_username", "email"} {
v, _ := claims[name].(string)
if i := strings.LastIndexByte(v, '#'); i >= 0 {