mirror of
https://github.com/luxfi/aml.git
synced 2026-09-24 00:25:20 +00:00
brand: an unstated issuer must refuse, not skip the check
golang-jwt validates `iss` only when an expectation is stated (validator.go, `if v.expectedIss != ""`), so a brand row carrying no issuer would not weaken the per-Host pin — it would delete it, and every brand's tokens would authenticate on that host. Stated expectation or no tenant. The shared-keyset fixture now says why it is the honest one: the live issuers serve the SAME set, and zoolabs.id publishes cert-lux beside cert-zoo, so a Lux token's signature does verify against Zoo's keys and the pin is the whole defence. Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
@@ -110,6 +110,13 @@ func IAMIdentity(jwks Keysets) Identity {
|
||||
// original host is a claim, and this decides which issuer is trusted.
|
||||
id := brand.ForHost(r.Host)
|
||||
issuer := brand.IssuerFor(id)
|
||||
// An empty expectation does not loosen the issuer check, it removes it:
|
||||
// golang-jwt validates `iss` only when one is stated (validator.go, `if
|
||||
// v.expectedIss != ""`). A brand row without an issuer would therefore admit
|
||||
// every brand's tokens on that host, so it admits none.
|
||||
if issuer == "" {
|
||||
return "", fmt.Errorf("brand %s states no issuer, so nothing is trusted to have signed this", id)
|
||||
}
|
||||
|
||||
raw, err := bearer(r)
|
||||
if err != nil {
|
||||
|
||||
+8
-5
@@ -53,11 +53,14 @@ func mint(t *testing.T, signer *rsa.PrivateKey, c jwt.MapClaims) string {
|
||||
}
|
||||
|
||||
// published is the keyset every brand issuer publishes in these tests: ONE key,
|
||||
// shared. That is what the in-cluster IAM does — it serves every brand's signing
|
||||
// certificate from one JWKS — and it is the sharp version of the white-label
|
||||
// claim: with the same key behind every issuer, the only thing that can refuse a
|
||||
// Lux token on a Zoo host is the `iss` pin itself, not a signature that happens
|
||||
// not to verify.
|
||||
// shared. That is what the live IAM does — every brand's issuer serves the same
|
||||
// set, and zoolabs.id's /v1/iam/.well-known/jwks carries cert-lux, cert-hanzo,
|
||||
// cert-pars and cert-zoo together — so a Lux token's signature really does verify
|
||||
// against the Zoo issuer's keys.
|
||||
//
|
||||
// It is therefore the sharp version of the white-label claim: with the same key
|
||||
// behind every issuer, the only thing that can refuse a Lux token on a Zoo host is
|
||||
// the `iss` pin itself, and not a signature that happens not to verify.
|
||||
func published(issuer string) (Keyset, error) {
|
||||
return Keyset{"iam": &key().PublicKey}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user