Skip to content

Commit

Permalink
compose: Expose token entropy setting (#342)
Browse files Browse the repository at this point in the history
Signed-off-by: nerocrux <nerocrux@gmail.com>
  • Loading branch information
nerocrux authored and aeneasr committed Dec 4, 2018
1 parent b156e6b commit 0761fca
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 22 deletions.
1 change: 1 addition & 0 deletions compose/compose_strategy.go
Expand Up @@ -41,6 +41,7 @@ func NewOAuth2HMACStrategy(config *Config, secret []byte, rotatedSecrets [][]byt
Enigma: &hmac.HMACStrategy{
GlobalSecret: secret,
RotatedGlobalSecrets: rotatedSecrets,
TokenEntropy: config.GetTokenEntropy(),
},
AccessTokenLifespan: config.GetAccessTokenLifespan(),
AuthorizeCodeLifespan: config.GetAuthorizeCodeLifespan(),
Expand Down
12 changes: 12 additions & 0 deletions compose/config.go
Expand Up @@ -78,6 +78,10 @@ type Config struct {
// JWKSFetcherStrategy is responsible for fetching JSON Web Keys from remote URLs. This is required when the private_key_jwt
// client authentication method is used. Defaults to fosite.DefaultJWKSFetcherStrategy.
JWKSFetcher fosite.JWKSFetcherStrategy

// TokenEntropy indicates the entropy of the random string, used as the "message" part of the HMAC token.
// Defaults to 32.
TokenEntropy int
}

// GetScopeStrategy returns the scope strategy to be used. Defaults to glob scope strategy.
Expand Down Expand Up @@ -144,3 +148,11 @@ func (c *Config) GetJWKSFetcherStrategy() fosite.JWKSFetcherStrategy {
}
return c.JWKSFetcher
}

// GetTokenEntropy returns the entropy of the "message" part of a HMAC Token. Defaults to 32.
func (c *Config) GetTokenEntropy() int {
if c.TokenEntropy == 0 {
return 32
}
return c.TokenEntropy
}
8 changes: 4 additions & 4 deletions token/hmac/hmacsha.go
Expand Up @@ -39,7 +39,7 @@ import (

// HMACStrategy is responsible for generating and validating challenges.
type HMACStrategy struct {
AuthCodeEntropy int
TokenEntropy int
GlobalSecret []byte
RotatedGlobalSecrets [][]byte
sync.Mutex
Expand Down Expand Up @@ -68,8 +68,8 @@ func (c *HMACStrategy) Generate() (string, string, error) {
var signingKey [32]byte
copy(signingKey[:], c.GlobalSecret)

if c.AuthCodeEntropy < minimumEntropy {
c.AuthCodeEntropy = minimumEntropy
if c.TokenEntropy < minimumEntropy {
c.TokenEntropy = minimumEntropy
}

// When creating secrets not intended for usage by human users (e.g.,
Expand All @@ -79,7 +79,7 @@ func (c *HMACStrategy) Generate() (string, string, error) {
// constructed from a cryptographically strong random or pseudo-random
// number sequence (see [RFC4086] for best current practice) generated
// by the authorization server.
tokenKey, err := RandomBytes(c.AuthCodeEntropy)
tokenKey, err := RandomBytes(c.TokenEntropy)
if err != nil {
return "", "", errors.WithStack(err)
}
Expand Down
51 changes: 33 additions & 18 deletions token/hmac/hmacsha_test.go
Expand Up @@ -37,25 +37,40 @@ func TestGenerateFailsWithShortCredentials(t *testing.T) {
}

func TestGenerate(t *testing.T) {
cg := HMACStrategy{
GlobalSecret: []byte("1234567890123456789012345678901234567890"),
for _, c := range []struct {
globalSecret []byte
tokenEntropy int
}{
{
globalSecret: []byte("1234567890123456789012345678901234567890"),
tokenEntropy: 32,
},
{
globalSecret: []byte("1234567890123456789012345678901234567890"),
tokenEntropy: 64,
},
} {
cg := HMACStrategy{
GlobalSecret: c.globalSecret,
TokenEntropy: c.tokenEntropy,
}

token, signature, err := cg.Generate()
require.NoError(t, err)
require.NotEmpty(t, token)
require.NotEmpty(t, signature)
t.Logf("Token: %s\n Signature: %s", token, signature)

err = cg.Validate(token)
require.NoError(t, err)

validateSignature := cg.Signature(token)
assert.Equal(t, signature, validateSignature)

cg.GlobalSecret = []byte("baz")
err = cg.Validate(token)
require.Error(t, err)
}

token, signature, err := cg.Generate()
require.NoError(t, err)
require.NotEmpty(t, token)
require.NotEmpty(t, signature)
t.Logf("Token: %s\n Signature: %s", token, signature)

err = cg.Validate(token)
require.NoError(t, err)

validateSignature := cg.Signature(token)
assert.Equal(t, signature, validateSignature)

cg.GlobalSecret = []byte("baz")
err = cg.Validate(token)
require.Error(t, err)
}

func TestValidateSignatureRejects(t *testing.T) {
Expand Down

0 comments on commit 0761fca

Please sign in to comment.