From c5942e6b33362684e7baf7dd56ea7c0cc7e1c2f6 Mon Sep 17 00:00:00 2001 From: Pascal Fischer Date: Wed, 29 Mar 2023 15:21:53 +0200 Subject: [PATCH] store hashed token base64 encoded --- management/server/account.go | 34 +++++++++++++------ management/server/account_test.go | 9 +++-- management/server/file_store.go | 12 ++++--- management/server/personal_access_token.go | 4 ++- .../server/personal_access_token_test.go | 4 ++- management/server/user_test.go | 2 +- 6 files changed, 43 insertions(+), 22 deletions(-) diff --git a/management/server/account.go b/management/server/account.go index 1d4c10721..55a5a0299 100644 --- a/management/server/account.go +++ b/management/server/account.go @@ -3,6 +3,7 @@ package server import ( "context" "crypto/sha256" + b64 "encoding/base64" "fmt" "hash/crc32" "math/rand" @@ -54,7 +55,7 @@ type AccountManager interface { GetSetupKey(accountID, userID, keyID string) (*SetupKey, error) GetAccountByUserOrAccountID(userID, accountID, domain string) (*Account, error) GetAccountFromToken(claims jwtclaims.AuthorizationClaims) (*Account, *User, error) - GetAccountFromPAT(pat string) (*Account, *User, error) + GetAccountFromPAT(pat string) (*Account, *User, *PersonalAccessToken, error) IsUserAdmin(claims jwtclaims.AuthorizationClaims) (bool, error) AccountExists(accountId string) (*bool, error) GetPeerByKey(peerKey string) (*Peer, error) @@ -1120,44 +1121,55 @@ func (am *DefaultAccountManager) redeemInvite(account *Account, userID string) e } // GetAccountFromPAT returns Account and User associated with a personal access token -func (am *DefaultAccountManager) GetAccountFromPAT(token string) (*Account, *User, error) { +func (am *DefaultAccountManager) GetAccountFromPAT(token string) (*Account, *User, *PersonalAccessToken, error) { if len(token) != PATLength { - return nil, nil, fmt.Errorf("token has wrong length") + return nil, nil, nil, fmt.Errorf("token has wrong length") } + log.Debugf("Token: %s", token) + prefix := token[:len(PATPrefix)] if prefix != PATPrefix { - return nil, nil, fmt.Errorf("token has wrong prefix") + return nil, nil, nil, fmt.Errorf("token has wrong prefix") } secret := token[len(PATPrefix) : len(PATPrefix)+PATSecretLength] encodedChecksum := token[len(PATPrefix)+PATSecretLength : len(PATPrefix)+PATSecretLength+PATChecksumLength] verificationChecksum, err := base62.Decode(encodedChecksum) if err != nil { - return nil, nil, fmt.Errorf("token checksum decoding failed: %w", err) + return nil, nil, nil, fmt.Errorf("token checksum decoding failed: %w", err) } secretChecksum := crc32.ChecksumIEEE([]byte(secret)) if secretChecksum != verificationChecksum { - return nil, nil, fmt.Errorf("token checksum does not match") + return nil, nil, nil, fmt.Errorf("token checksum does not match") } hashedToken := sha256.Sum256([]byte(token)) - tokenID, err := am.Store.GetTokenIDByHashedToken(string(hashedToken[:])) + encodedHashedToken := b64.StdEncoding.EncodeToString(hashedToken[:]) + tokenID, err := am.Store.GetTokenIDByHashedToken(encodedHashedToken) if err != nil { - return nil, nil, err + return nil, nil, nil, err } + log.Debugf("TokenID: %s", tokenID) user, err := am.Store.GetUserByTokenID(tokenID) + log.Debugf("User: %v", user) if err != nil { - return nil, nil, err + return nil, nil, nil, err } account, err := am.Store.GetAccountByUser(user.Id) if err != nil { - return nil, nil, err + return nil, nil, nil, err } - return account, user, nil + + pat := user.PATs[tokenID] + if pat == nil { + return nil, nil, nil, fmt.Errorf("personal access token not found") + } + + return account, user, pat, nil } // GetAccountFromToken returns an account associated with this token diff --git a/management/server/account_test.go b/management/server/account_test.go index 57b1cf3da..8eea04362 100644 --- a/management/server/account_test.go +++ b/management/server/account_test.go @@ -2,6 +2,7 @@ package server import ( "crypto/sha256" + b64 "encoding/base64" "fmt" "net" "reflect" @@ -465,12 +466,13 @@ func TestAccountManager_GetAccountFromPAT(t *testing.T) { token := "nbp_9999EUDNdkeusjentDLSJEn1902u84390W6W" hashedToken := sha256.Sum256([]byte(token)) + encodedHashedToken := b64.StdEncoding.EncodeToString(hashedToken[:]) account.Users["someUser"] = &User{ Id: "someUser", PATs: map[string]*PersonalAccessToken{ - "pat1": { + "tokenId": { ID: "tokenId", - HashedToken: string(hashedToken[:]), + HashedToken: encodedHashedToken, }, }, } @@ -483,13 +485,14 @@ func TestAccountManager_GetAccountFromPAT(t *testing.T) { Store: store, } - account, user, err := am.GetAccountFromPAT(token) + account, user, pat, err := am.GetAccountFromPAT(token) if err != nil { t.Fatalf("Error when getting Account from PAT: %s", err) } assert.Equal(t, "account_id", account.Id) assert.Equal(t, "someUser", user.Id) + assert.Equal(t, account.Users["someUser"].PATs["tokenId"], pat) } func TestAccountManager_PrivateAccount(t *testing.T) { diff --git a/management/server/file_store.go b/management/server/file_store.go index 4f8092cfb..b09dccf81 100644 --- a/management/server/file_store.go +++ b/management/server/file_store.go @@ -112,7 +112,7 @@ func restore(file string) (*FileStore, error) { store.UserID2AccountID[user.Id] = accountID for _, pat := range user.PATs { store.TokenID2UserID[pat.ID] = user.Id - store.HashedPAT2TokenID[pat.HashedToken[:]] = pat.ID + store.HashedPAT2TokenID[pat.HashedToken] = pat.ID } } @@ -268,7 +268,7 @@ func (s *FileStore) SaveAccount(account *Account) error { s.UserID2AccountID[user.Id] = accountCopy.Id for _, pat := range user.PATs { s.TokenID2UserID[pat.ID] = user.Id - s.HashedPAT2TokenID[pat.HashedToken[:]] = pat.ID + s.HashedPAT2TokenID[pat.HashedToken] = pat.ID } } @@ -349,11 +349,13 @@ func (s *FileStore) GetTokenIDByHashedToken(token string) (string, error) { s.mux.Lock() defer s.mux.Unlock() + log.Debugf("TOken still there: %v", token) + log.Debugf("TokenID2UserId %v", s.HashedPAT2TokenID) tokenID, ok := s.HashedPAT2TokenID[token] if !ok { return "", status.Errorf(status.NotFound, "tokenID not found: provided token doesn't exists") } - + log.Debugf("TokenID for token %s is %s", token, tokenID) return tokenID, nil } @@ -366,12 +368,12 @@ func (s *FileStore) GetUserByTokenID(tokenID string) (*User, error) { if !ok { return nil, status.Errorf(status.NotFound, "user not found: provided tokenID doesn't exists") } - + log.Debugf("UserID for tokenID %s is %s", tokenID, userID) accountID, ok := s.UserID2AccountID[userID] if !ok { return nil, status.Errorf(status.NotFound, "accountID not found: provided userID doesn't exists") } - + log.Debugf("AccountID for userID %s is %s", userID, accountID) account, err := s.getAccount(accountID) if err != nil { return nil, err diff --git a/management/server/personal_access_token.go b/management/server/personal_access_token.go index 6eab840b8..a7c55018f 100644 --- a/management/server/personal_access_token.go +++ b/management/server/personal_access_token.go @@ -2,6 +2,7 @@ package server import ( "crypto/sha256" + b64 "encoding/base64" "fmt" "hash/crc32" "time" @@ -74,5 +75,6 @@ func generateNewToken() (string, string, error) { paddedChecksum := fmt.Sprintf("%06s", encodedChecksum) plainToken := PATPrefix + secret + paddedChecksum hashedToken := sha256.Sum256([]byte(plainToken)) - return string(hashedToken[:]), plainToken, nil + encodedHashedToken := b64.StdEncoding.EncodeToString(hashedToken[:]) + return encodedHashedToken, plainToken, nil } diff --git a/management/server/personal_access_token_test.go b/management/server/personal_access_token_test.go index a4e02f750..03dd2ef4e 100644 --- a/management/server/personal_access_token_test.go +++ b/management/server/personal_access_token_test.go @@ -2,6 +2,7 @@ package server import ( "crypto/sha256" + b64 "encoding/base64" "hash/crc32" "strings" "testing" @@ -13,7 +14,8 @@ import ( func TestPAT_GenerateToken_Hashing(t *testing.T) { hashedToken, plainToken, _ := generateNewToken() expectedToken := sha256.Sum256([]byte(plainToken)) - assert.Equal(t, hashedToken, string(expectedToken[:])) + encodedExpectedToken := b64.StdEncoding.EncodeToString(expectedToken[:]) + assert.Equal(t, hashedToken, encodedExpectedToken) } func TestPAT_GenerateToken_Prefix(t *testing.T) { diff --git a/management/server/user_test.go b/management/server/user_test.go index 20f2ca4f1..ffbb71282 100644 --- a/management/server/user_test.go +++ b/management/server/user_test.go @@ -37,7 +37,7 @@ func TestUser_AddPATToUser(t *testing.T) { } fileStore := am.Store.(*FileStore) - tokenID := fileStore.HashedPAT2TokenID[mockToken[:]] + tokenID := fileStore.HashedPAT2TokenID[mockToken] if tokenID == "" { t.Fatal("GetTokenIDByHashedToken failed after adding PAT")