feat: accept lists in the token audience claim
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
This commit is contained in:
parent
97fa1183bf
commit
3472f7a8e3
4 changed files with 35 additions and 22 deletions
|
@ -180,7 +180,7 @@ func (issuer *TokenIssuer) CreateJWT(subject string, audience string, grantedAcc
|
||||||
claimSet := token.ClaimSet{
|
claimSet := token.ClaimSet{
|
||||||
Issuer: issuer.Issuer,
|
Issuer: issuer.Issuer,
|
||||||
Subject: subject,
|
Subject: subject,
|
||||||
Audience: audience,
|
Audience: []string{audience},
|
||||||
Expiration: now.Add(exp).Unix(),
|
Expiration: now.Add(exp).Unix(),
|
||||||
NotBefore: now.Unix(),
|
NotBefore: now.Unix(),
|
||||||
IssuedAt: now.Unix(),
|
IssuedAt: now.Unix(),
|
||||||
|
|
|
@ -42,13 +42,13 @@ type ResourceActions struct {
|
||||||
// ClaimSet describes the main section of a JSON Web Token.
|
// ClaimSet describes the main section of a JSON Web Token.
|
||||||
type ClaimSet struct {
|
type ClaimSet struct {
|
||||||
// Public claims
|
// Public claims
|
||||||
Issuer string `json:"iss"`
|
Issuer string `json:"iss"`
|
||||||
Subject string `json:"sub"`
|
Subject string `json:"sub"`
|
||||||
Audience string `json:"aud"`
|
Audience WeakStringList `json:"aud"`
|
||||||
Expiration int64 `json:"exp"`
|
Expiration int64 `json:"exp"`
|
||||||
NotBefore int64 `json:"nbf"`
|
NotBefore int64 `json:"nbf"`
|
||||||
IssuedAt int64 `json:"iat"`
|
IssuedAt int64 `json:"iat"`
|
||||||
JWTID string `json:"jti"`
|
JWTID string `json:"jti"`
|
||||||
|
|
||||||
// Private claims
|
// Private claims
|
||||||
Access []*ResourceActions `json:"access"`
|
Access []*ResourceActions `json:"access"`
|
||||||
|
@ -141,8 +141,8 @@ func (t *Token) Verify(verifyOpts VerifyOptions) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the Audience claim is allowed.
|
// Verify that the Audience claim is allowed.
|
||||||
if !contains(verifyOpts.AcceptedAudiences, t.Claims.Audience) {
|
if !containsAny(verifyOpts.AcceptedAudiences, t.Claims.Audience) {
|
||||||
log.Infof("token intended for another audience: %q", t.Claims.Audience)
|
log.Infof("token intended for another audience: %v", t.Claims.Audience)
|
||||||
return ErrInvalidToken
|
return ErrInvalidToken
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,13 +185,15 @@ func (t *Token) Verify(verifyOpts VerifyOptions) error {
|
||||||
|
|
||||||
// VerifySigningKey attempts to get the key which was used to sign this token.
|
// VerifySigningKey attempts to get the key which was used to sign this token.
|
||||||
// The token header should contain either of these 3 fields:
|
// The token header should contain either of these 3 fields:
|
||||||
// `x5c` - The x509 certificate chain for the signing key. Needs to be
|
//
|
||||||
// verified.
|
// `x5c` - The x509 certificate chain for the signing key. Needs to be
|
||||||
// `jwk` - The JSON Web Key representation of the signing key.
|
// verified.
|
||||||
// May contain its own `x5c` field which needs to be verified.
|
// `jwk` - The JSON Web Key representation of the signing key.
|
||||||
// `kid` - The unique identifier for the key. This library interprets it
|
// May contain its own `x5c` field which needs to be verified.
|
||||||
// as a libtrust fingerprint. The key itself can be looked up in
|
// `kid` - The unique identifier for the key. This library interprets it
|
||||||
// the trustedKeys field of the given verify options.
|
// as a libtrust fingerprint. The key itself can be looked up in
|
||||||
|
// the trustedKeys field of the given verify options.
|
||||||
|
//
|
||||||
// Each of these methods are tried in that order of preference until the
|
// Each of these methods are tried in that order of preference until the
|
||||||
// signing key is found or an error is returned.
|
// signing key is found or an error is returned.
|
||||||
func (t *Token) VerifySigningKey(verifyOpts VerifyOptions) (signingKey libtrust.PublicKey, err error) {
|
func (t *Token) VerifySigningKey(verifyOpts VerifyOptions) (signingKey libtrust.PublicKey, err error) {
|
||||||
|
|
|
@ -117,7 +117,7 @@ func makeTestToken(issuer, audience string, access []*ResourceActions, rootKey l
|
||||||
claimSet := &ClaimSet{
|
claimSet := &ClaimSet{
|
||||||
Issuer: issuer,
|
Issuer: issuer,
|
||||||
Subject: "foo",
|
Subject: "foo",
|
||||||
Audience: audience,
|
Audience: []string{audience},
|
||||||
Expiration: exp.Unix(),
|
Expiration: exp.Unix(),
|
||||||
NotBefore: now.Unix(),
|
NotBefore: now.Unix(),
|
||||||
IssuedAt: now.Unix(),
|
IssuedAt: now.Unix(),
|
||||||
|
@ -307,10 +307,10 @@ func writeTempRootCerts(rootKeys []libtrust.PrivateKey) (filename string, err er
|
||||||
// TestAccessController tests complete integration of the token auth package.
|
// TestAccessController tests complete integration of the token auth package.
|
||||||
// It starts by mocking the options for a token auth accessController which
|
// It starts by mocking the options for a token auth accessController which
|
||||||
// it creates. It then tries a few mock requests:
|
// it creates. It then tries a few mock requests:
|
||||||
// - don't supply a token; should error with challenge
|
// - don't supply a token; should error with challenge
|
||||||
// - supply an invalid token; should error with challenge
|
// - supply an invalid token; should error with challenge
|
||||||
// - supply a token with insufficient access; should error with challenge
|
// - supply a token with insufficient access; should error with challenge
|
||||||
// - supply a valid token; should not error
|
// - supply a valid token; should not error
|
||||||
func TestAccessController(t *testing.T) {
|
func TestAccessController(t *testing.T) {
|
||||||
// Make 2 keys; only the first is to be a trusted root key.
|
// Make 2 keys; only the first is to be a trusted root key.
|
||||||
rootKeys, err := makeRootKeys(2)
|
rootKeys, err := makeRootKeys(2)
|
||||||
|
|
|
@ -56,3 +56,14 @@ func contains(ss []string, q string) bool {
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// containsAny returns true if any of q is found in ss.
|
||||||
|
func containsAny(ss []string, q []string) bool {
|
||||||
|
for _, s := range ss {
|
||||||
|
if contains(q, s) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue