Skip to content
This repository has been archived by the owner on May 21, 2022. It is now read-only.

Support array of strings and single string for aud value #355

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 52 additions & 13 deletions claims.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ type Claims interface {
// https://tools.ietf.org/html/rfc7519#section-4.1
// See examples for how to use this with your own claim types
type StandardClaims struct {
Audience string `json:"aud,omitempty"`
ExpiresAt int64 `json:"exp,omitempty"`
Id string `json:"jti,omitempty"`
IssuedAt int64 `json:"iat,omitempty"`
Issuer string `json:"iss,omitempty"`
NotBefore int64 `json:"nbf,omitempty"`
Subject string `json:"sub,omitempty"`
// https://tools.ietf.org/html/rfc7519#section-4.1.3
Audience interface{} `json:"aud,omitempty"`
ExpiresAt int64 `json:"exp,omitempty"`
Id string `json:"jti,omitempty"`
IssuedAt int64 `json:"iat,omitempty"`
Issuer string `json:"iss,omitempty"`
NotBefore int64 `json:"nbf,omitempty"`
Subject string `json:"sub,omitempty"`
}

// Validates time based claims "exp, iat, nbf".
Expand Down Expand Up @@ -61,6 +62,10 @@ func (c StandardClaims) Valid() error {
// Compares the aud claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool {
return verifyAud(c.Audience, []string{cmp}, req)
}

func (c *StandardClaims) VerifyMultipleAudiences(cmp []string, req bool) bool {
return verifyAud(c.Audience, cmp, req)
}

Expand Down Expand Up @@ -90,15 +95,49 @@ func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool {

// ----- helpers

func verifyAud(aud string, cmp string, required bool) bool {
if aud == "" {
func contains(aud []string, cmp string) bool {
for _, a := range aud {
if subtle.ConstantTimeCompare([]byte(a), []byte(cmp)) != 0 {
return true
}
}
return false
}

func verifyAud(aud interface{}, cmp []string, required bool) bool {

switch audVal := aud.(type) {
case []interface{}:
var audArray []string
for _, oneVal := range audVal {
if oneStr, ok := oneVal.(string); ok {
audArray = append(audArray, oneStr)
} else {
panic(fmt.Sprintf("Audience is type %T, but must be string or []string", audVal))
}
}
return verifyAudDeep(audArray, cmp, required)
case []string:
return verifyAudDeep(audVal, cmp, required)
case string:
return verifyAudDeep([]string{audVal}, cmp, required)
default:
panic(fmt.Sprintf("Audience is type %T, but must be string or []string", audVal))
}
}

func verifyAudDeep(aud []string, cmp []string, required bool) bool {
if len(aud) < 1 {
return !required
}
if subtle.ConstantTimeCompare([]byte(aud), []byte(cmp)) != 0 {
return true
} else {
return false

for _, c := range cmp {
if !contains(aud, c) {
return false
}
}

return true
}

func verifyExp(exp int64, now int64, required bool) bool {
Expand Down
2 changes: 1 addition & 1 deletion hmac_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func ExampleParse_hmac() {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}

// hmacSampleSecret is a []byte containing your secret, e.g. []byte("my_secret_key")
return hmacSampleSecret, nil
})
Expand Down
3 changes: 1 addition & 2 deletions map_claims.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ type MapClaims map[string]interface{}
// Compares the aud claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (m MapClaims) VerifyAudience(cmp string, req bool) bool {
aud, _ := m["aud"].(string)
return verifyAud(aud, cmp, req)
return verifyAud(m["aud"], []string{cmp}, req)
}

// Compares the exp claim against cmp.
Expand Down