Skip to content

Commit d1b3e1b

Browse files
committed
chore: updates based on PR comments
- Removed `authResponse.HashedToken` field - Improved error messages, log messages, and comments - Improved error propagation - Improve description of `--use-hashed-tokens` command line parameter - Removed dead code - Implemented test to make sure hashed version of tokens can not be presented for authentication
1 parent 19a4057 commit d1b3e1b

File tree

8 files changed

+22
-23
lines changed

8 files changed

+22
-23
lines changed

authorization/http_server.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ type postAuthorizationRequest struct {
137137
type authResponse struct {
138138
ID platform.ID `json:"id"`
139139
Token string `json:"token"`
140-
HashedToken string `json:"hashedToken"`
141140
Status influxdb.Status `json:"status"`
142141
Description string `json:"description"`
143142
OrgID platform.ID `json:"orgID"`
@@ -167,7 +166,6 @@ func (h *AuthHandler) newAuthResponse(ctx context.Context, a *influxdb.Authoriza
167166
res := &authResponse{
168167
ID: a.ID,
169168
Token: a.Token,
170-
HashedToken: a.HashedToken,
171169
Status: a.Status,
172170
Description: a.Description,
173171
OrgID: a.OrgID,
@@ -199,7 +197,6 @@ func (a *authResponse) toInfluxdb() *influxdb.Authorization {
199197
res := &influxdb.Authorization{
200198
ID: a.ID,
201199
Token: a.Token,
202-
HashedToken: a.HashedToken,
203200
Status: a.Status,
204201
Description: a.Description,
205202
OrgID: a.OrgID,

authorization/storage.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,9 @@ into BoltDB. Raw tokens are not stored.
8282
To verify tokens when hashed tokens are enabled, the presented token's hash is calculated and used
8383
for token index lookup. The rest of the authorization flow is unchanged.
8484
85-
The hashed token index is separate from the raw token index. Newer versions also verify that the token
86-
is not a valid PHC string before starting authorization. This prevents the following attack:
85+
The hashed token index is separate from the raw token index. In addition, the token presented by the API
86+
is rejected if it is a PHC encoded hash before starting authorization. The separate index and rejected
87+
PHC tokens from the API prevent the following attack:
8788
1. Hashed token is extracted from BoltDB.
8889
2. Token hashing is disabled.
8990
3. The hashed token is presented to the API, which will misinterpret it as a raw token and allow access.
@@ -300,17 +301,16 @@ func (s *Store) hashedTokenMigration(ctx context.Context) error {
300301
// Figure out which authorization records need to be updated.
301302
var authsNeedingUpdate []*influxdb.Authorization
302303
err := s.View(ctx, func(tx kv.Tx) error {
303-
s.forEachAuthorization(ctx, tx, nil, func(a *influxdb.Authorization) bool {
304+
return s.forEachAuthorization(ctx, tx, nil, func(a *influxdb.Authorization) bool {
304305
if a.IsHashedTokenClear() {
305306
if a.IsTokenSet() {
306307
authsNeedingUpdate = append(authsNeedingUpdate, a)
307308
} else {
308-
s.log.Warn("found authorization without any token set during hashed token migration", zap.Uint64("ID", uint64(a.ID)), zap.String("description", a.Description))
309+
s.log.Warn("during hashed token migration, found authorization without any token set", zap.Uint64("ID", uint64(a.ID)), zap.String("description", a.Description))
309310
}
310311
}
311312
return true
312313
})
313-
return nil
314314
})
315315
if err != nil {
316316
return err

authorization/storage_authorization.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
var (
2121
ErrNilAuthorization = goerrors.New("authorization cannot be nil")
2222
ErrHashedTokenMismatch = goerrors.New("HashedToken does not match Token")
23-
ErrIncorrectToken = goerrors.New("token is incorrect for authorization")
2423
ErrNoTokenAvailable = goerrors.New("no token available for authorization")
2524
)
2625

cmd/influxd/launcher/cmd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@ func (o *InfluxdOpts) BindCliOpts() []cli.Opt {
707707
DestP: &o.UseHashedTokens,
708708
Flag: "use-hashed-tokens",
709709
Default: o.UseHashedTokens,
710-
Desc: "enable token hashing",
710+
Desc: "enable storing hashed API tokens on disk (improves security, but prevents downgrades to < 2.8)",
711711
},
712712
}
713713
}

cmd/influxd/launcher/launcher.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ func (m *Launcher) run(ctx context.Context, opts *InfluxdOpts) (err error) {
293293
var authSvc platform.AuthorizationService
294294
{
295295
hasherVariantName := authorization.DefaultHashVariantName // This value could come from opts in the future.
296-
authStore, err := authorization.NewStore(ctx, m.kvStore, opts.UseHashedTokens, authorization.WithAuthorizationHashVariantName(hasherVariantName), authorization.WithLogger(m.log))
296+
authStoreLogger := m.log.With(zap.String("store", "auth"))
297+
authStore, err := authorization.NewStore(ctx, m.kvStore, opts.UseHashedTokens, authorization.WithAuthorizationHashVariantName(hasherVariantName), authorization.WithLogger(authStoreLogger))
297298
if err != nil {
298299
m.log.Error("Failed creating new authorization store", zap.Error(err), zap.Bool("UseHashedTokens", opts.UseHashedTokens), zap.String("hasherVariant", hasherVariantName))
299300
return err

pkg/crypt/algorithm/influxdb2/decoder.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,6 @@ func RegisterDecoderVariant(r algorithm.DecoderRegister, variant Variant) error
3636
return nil
3737
}
3838

39-
// Decode the encoded digest into a algorithm.Digest.
40-
func Decode(encodedDigest string) (digest algorithm.Digest, err error) {
41-
return DecodeVariant(VariantNone)(encodedDigest)
42-
}
43-
4439
// DecodeVariant the encoded digest into a algorithm.Digest provided it matches the provided plaintext.Variant. If
4540
// plaintext.VariantNone is used all variants can be decoded.
4641
func DecodeVariant(v Variant) func(encodedDigest string) (digest algorithm.Digest, err error) {

pkg/crypt/algorithm/influxdb2/digest.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ package influxdb2
22

33
import (
44
"crypto/subtle"
5+
"errors"
56
"fmt"
67

78
"github.com/go-crypt/crypt/algorithm"
89
)
910

10-
// NewDigest creates a new plaintext.Digest using the plaintext.Variant.
11-
func NewDigest(password string) (digest Digest) {
12-
return NewSHA256Digest(password)
13-
}
11+
// ErrDigestInvalid is an error returned when a hash digest has an invalid or unsupported properties. It is NOT
12+
// returned on token or password mismatches. It is equivalent to go-crypt's algorithm.ErrPasswordInvalid
13+
// error, but with a message that makes more sense for our usage with tokens.
14+
var ErrDigestInvalid = errors.New("hashed token or password is invalid")
1415

1516
// NewSHA256Digest creates a new influxdb2.Digest using the SHA256 for the hash.
1617
func NewSHA256Digest(password string) (digest Digest) {
@@ -48,7 +49,7 @@ func (d *Digest) MatchAdvanced(password string) (match bool, err error) {
4849
// MatchBytesAdvanced is the same as MatchBytes except if there is an error it returns that as well.
4950
func (d *Digest) MatchBytesAdvanced(passwordBytes []byte) (match bool, err error) {
5051
if len(d.key) == 0 {
51-
return false, fmt.Errorf(algorithm.ErrFmtDigestMatch, AlgName, fmt.Errorf("%w: key has 0 bytes", algorithm.ErrPasswordInvalid))
52+
return false, fmt.Errorf(algorithm.ErrFmtDigestMatch, AlgName, fmt.Errorf("%w: key has 0 bytes", ErrDigestInvalid))
5253
}
5354

5455
input := d.Variant.Hash(passwordBytes)

testing/auth.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/influxdata/influxdb/v2/kit/platform"
1414
"github.com/influxdata/influxdb/v2/kit/platform/errors"
1515
"github.com/influxdata/influxdb/v2/mock"
16+
"github.com/stretchr/testify/require"
1617
)
1718

1819
const (
@@ -706,7 +707,6 @@ func FindAuthorizationByToken(
706707
authorization *influxdb.Authorization
707708
}
708709

709-
// VALIS: Add tests to make sure look-up by hashed token does /not/ work
710710
tests := []struct {
711711
name string
712712
fields AuthorizationFields
@@ -859,6 +859,13 @@ func FindAuthorizationByToken(
859859
if diff := cmp.Diff(authorization, tt.wants.authorization, authorizationCmpOptions...); diff != "" {
860860
t.Errorf("authorization is different -got/+want\ndiff %s", diff)
861861
}
862+
863+
// Verify that lookup by the hashed token does not work.
864+
if authorization.IsHashedTokenSet() {
865+
a, err := s.FindAuthorizationByToken(ctx, authorization.HashedToken)
866+
require.ErrorContains(t, err, "authorization not found")
867+
require.Nil(t, a)
868+
}
862869
})
863870
}
864871
}
@@ -875,7 +882,6 @@ func FindAuthorizations(
875882
token string
876883
}
877884

878-
// VALIS: Do we need tests that set HashedToken, or tests with Token and HashedToken set?
879885
type wants struct {
880886
authorizations []*influxdb.Authorization
881887
err error

0 commit comments

Comments
 (0)