diff --git a/svid/jwtsvid/svid.go b/svid/jwtsvid/svid.go index 15aabc532..928a97887 100644 --- a/svid/jwtsvid/svid.go +++ b/svid/jwtsvid/svid.go @@ -99,6 +99,10 @@ func (svid *SVID) Marshal() string { } func parse(token string, audience []string, getClaims tokenValidator) (*SVID, error) { + if len(audience) == 0 { + return nil, wrapJwtsvidErr(errors.New("audience must be non-empty")) + } + // Parse serialized token tok, err := jwt.ParseSigned(token, allowedSignatureAlgorithms) if err != nil { @@ -122,6 +126,8 @@ func parse(token string, audience []string, getClaims tokenValidator) (*SVID, er return nil, wrapJwtsvidErr(errors.New("token missing subject claim")) case claims.Expiry == nil: return nil, wrapJwtsvidErr(errors.New("token missing exp claim")) + case len(claims.Audience) == 0: + return nil, wrapJwtsvidErr(errors.New("token missing aud claim")) } spiffeID, err := spiffeid.FromString(claims.Subject) diff --git a/svid/jwtsvid/svid_test.go b/svid/jwtsvid/svid_test.go index 0b12dfe00..702ed619c 100644 --- a/svid/jwtsvid/svid_test.go +++ b/svid/jwtsvid/svid_test.go @@ -64,8 +64,9 @@ func TestParseAndValidate(t *testing.T) { svid *jwtsvid.SVID }{ { - name: "success", - bundle: bundle1, + name: "success", + bundle: bundle1, + audience: []string{"audience"}, generateToken: func(tb testing.TB) string { claims := jwt.Claims{ Subject: spiffeid.RequireFromPath(trustDomain1, "/host").String(), @@ -84,24 +85,76 @@ func TestParseAndValidate(t *testing.T) { }, }, { - name: "malformed", + name: "nil audience argument", bundle: bundle1, + generateToken: func(tb testing.TB) string { + claims := jwt.Claims{ + Subject: spiffeid.RequireFromPath(trustDomain1, "/host").String(), + Issuer: "issuer", + Expiry: expires, + Audience: []string{"audience"}, + IssuedAt: issuedAt, + } + + return generateToken(tb, claims, key1, "authority1", "") + }, + err: "jwtsvid: audience must be non-empty", + }, + { + name: "empty audience argument", + bundle: bundle1, + audience: []string{}, + generateToken: func(tb testing.TB) string { + claims := jwt.Claims{ + Subject: spiffeid.RequireFromPath(trustDomain1, "/host").String(), + Issuer: "issuer", + Expiry: expires, + Audience: []string{"audience"}, + IssuedAt: issuedAt, + } + + return generateToken(tb, claims, key1, "authority1", "") + }, + err: "jwtsvid: audience must be non-empty", + }, + { + name: "token missing aud claim", + bundle: bundle1, + audience: []string{"audience"}, + generateToken: func(tb testing.TB) string { + claims := jwt.Claims{ + Subject: spiffeid.RequireFromPath(trustDomain1, "/host").String(), + Issuer: "issuer", + Expiry: expires, + IssuedAt: issuedAt, + } + + return generateToken(tb, claims, key1, "authority1", "") + }, + err: "jwtsvid: token missing aud claim", + }, + { + name: "malformed", + bundle: bundle1, + audience: []string{"audience"}, generateToken: func(tb testing.TB) string { return "invalid token" }, err: "jwtsvid: unable to parse JWT token", }, { - name: "unsupported algorithm", - bundle: bundle1, + name: "unsupported algorithm", + bundle: bundle1, + audience: []string{"audience"}, generateToken: func(tb testing.TB) string { return hs256Token }, err: "jwtsvid: unable to parse JWT token", }, { - name: "missing subject", - bundle: bundle1, + name: "missing subject", + bundle: bundle1, + audience: []string{"audience"}, generateToken: func(tb testing.TB) string { claims := jwt.Claims{ Issuer: "issuer", @@ -115,8 +168,9 @@ func TestParseAndValidate(t *testing.T) { err: "jwtsvid: token missing subject claim", }, { - name: "missing expiration claim", - bundle: bundle1, + name: "missing expiration claim", + bundle: bundle1, + audience: []string{"audience"}, generateToken: func(tb testing.TB) string { claims := jwt.Claims{ Subject: spiffeid.RequireFromPath(trustDomain1, "/host").String(), @@ -249,8 +303,9 @@ func TestParseAndValidate(t *testing.T) { err: "jwtsvid: unable to get claims from token: go-jose/go-jose: error in cryptographic primitive", }, { - name: "invalid typ", - bundle: bundle1, + name: "invalid typ", + bundle: bundle1, + audience: []string{"audience"}, generateToken: func(tb testing.TB) string { claims := jwt.Claims{ Subject: spiffeid.RequireFromPath(trustDomain1, "/host").String(), @@ -309,7 +364,8 @@ func TestParseInsecure(t *testing.T) { svid *jwtsvid.SVID }{ { - name: "success", + name: "success", + audience: []string{"audience"}, generateToken: func(tb testing.TB) string { claims := jwt.Claims{ Subject: spiffeid.RequireFromPath(trustDomain1, "/host").String(), @@ -328,21 +384,54 @@ func TestParseInsecure(t *testing.T) { }, }, { - name: "malformed", + name: "nil audience argument", + generateToken: func(tb testing.TB) string { + claims := jwt.Claims{ + Subject: spiffeid.RequireFromPath(trustDomain1, "/host").String(), + Issuer: "issuer", + Expiry: expires, + Audience: []string{"audience"}, + IssuedAt: issuedAt, + } + + return generateToken(tb, claims, key1, "key1", "") + }, + err: "jwtsvid: audience must be non-empty", + }, + { + name: "token missing aud claim", + audience: []string{"audience"}, + generateToken: func(tb testing.TB) string { + claims := jwt.Claims{ + Subject: spiffeid.RequireFromPath(trustDomain1, "/host").String(), + Issuer: "issuer", + Expiry: expires, + IssuedAt: issuedAt, + } + + return generateToken(tb, claims, key1, "key1", "") + }, + err: "jwtsvid: token missing aud claim", + }, + { + name: "malformed", + audience: []string{"audience"}, generateToken: func(tb testing.TB) string { return "invalid token" }, err: "jwtsvid: unable to parse JWT token", }, { - name: "invalid algorithm", + name: "invalid algorithm", + audience: []string{"audience"}, generateToken: func(tb testing.TB) string { return hs256Token }, err: "jwtsvid: unable to parse JWT token", }, { - name: "missing subject claim", + name: "missing subject claim", + audience: []string{"audience"}, generateToken: func(tb testing.TB) string { claims := jwt.Claims{ Issuer: "issuer", @@ -356,7 +445,8 @@ func TestParseInsecure(t *testing.T) { err: "jwtsvid: token missing subject claim", }, { - name: "missing expiration claim", + name: "missing expiration claim", + audience: []string{"audience"}, generateToken: func(tb testing.TB) string { claims := jwt.Claims{ Subject: spiffeid.RequireFromPath(trustDomain1, "/host").String(), @@ -418,7 +508,8 @@ func TestParseInsecure(t *testing.T) { err: `jwtsvid: token has an invalid subject claim: scheme is missing or invalid`, }, { - name: "success", + name: "invalid typ", + audience: []string{"audience"}, generateToken: func(tb testing.TB) string { claims := jwt.Claims{ Subject: spiffeid.RequireFromPath(trustDomain1, "/host").String(),