diff --git a/authority/authorize.go b/authority/authorize.go index 0d3b767f..f84bd6f5 100644 --- a/authority/authorize.go +++ b/authority/authorize.go @@ -2,7 +2,9 @@ package authority import ( "context" + "crypto/sha256" "crypto/x509" + "encoding/hex" "net/http" "strings" @@ -69,8 +71,13 @@ func (a *Authority) authorizeToken(ctx context.Context, token string) (provision } // Store the token to protect against reuse unless it's skipped. + // If we cannot get a token id from the provisioner, just hash the token. if !SkipTokenReuseFromContext(ctx) { if reuseKey, err := p.GetTokenID(token); err == nil { + if reuseKey == "" { + sum := sha256.Sum256([]byte(token)) + reuseKey = strings.ToLower(hex.EncodeToString(sum[:])) + } ok, err := a.db.UseToken(reuseKey, token) if err != nil { return nil, errs.Wrap(http.StatusInternalServerError, err, diff --git a/authority/authorize_test.go b/authority/authorize_test.go index 90eb8e46..f20e2976 100644 --- a/authority/authorize_test.go +++ b/authority/authorize_test.go @@ -188,6 +188,41 @@ func TestAuthority_authorizeToken(t *testing.T) { code: http.StatusUnauthorized, } }, + "ok/sha256": func(t *testing.T) *authorizeTest { + cl := jose.Claims{ + Subject: "test.smallstep.com", + Issuer: validIssuer, + NotBefore: jose.NewNumericDate(now), + Expiry: jose.NewNumericDate(now.Add(time.Minute)), + Audience: validAudience, + } + raw, err := jose.Signed(sig).Claims(cl).CompactSerialize() + assert.FatalError(t, err) + return &authorizeTest{ + auth: a, + token: raw, + } + }, + "fail/sha256/token-already-used": func(t *testing.T) *authorizeTest { + _a := testAuthority(t) + cl := jose.Claims{ + Subject: "test.smallstep.com", + Issuer: validIssuer, + NotBefore: jose.NewNumericDate(now), + Expiry: jose.NewNumericDate(now.Add(time.Minute)), + Audience: validAudience, + } + raw, err := jose.Signed(sig).Claims(cl).CompactSerialize() + assert.FatalError(t, err) + _, err = _a.authorizeToken(context.Background(), raw) + assert.FatalError(t, err) + return &authorizeTest{ + auth: _a, + token: raw, + err: errors.New("authority.authorizeToken: token already used"), + code: http.StatusUnauthorized, + } + }, "ok/mockNoSQLDB": func(t *testing.T) *authorizeTest { _a := testAuthority(t) _a.db = &db.MockAuthDB{