feat: accept lists in the token audience claim
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>master
							parent
							
								
									97fa1183bf
								
							
						
					
					
						commit
						3472f7a8e3
					
				|  | @ -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 New Issue