mirror of
https://github.com/netbirdio/netbird.git
synced 2025-02-08 22:39:55 +01:00
e586eca16c
With this fix, all nested slices and pointers will be copied by value. Also, this fixes tests to compare the original and copy account by their values by marshaling them to JSON strings. Before that, they were copying the pointers that also passed the simple `=` compassion (as the addresses match).
94 lines
2.7 KiB
Go
94 lines
2.7 KiB
Go
package server
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
b64 "encoding/base64"
|
|
"fmt"
|
|
"hash/crc32"
|
|
"time"
|
|
|
|
b "github.com/hashicorp/go-secure-stdlib/base62"
|
|
"github.com/rs/xid"
|
|
|
|
"github.com/netbirdio/netbird/base62"
|
|
)
|
|
|
|
const (
|
|
// PATPrefix is the globally used, 4 char prefix for personal access tokens
|
|
PATPrefix = "nbp_"
|
|
// PATSecretLength number of characters used for the secret inside the token
|
|
PATSecretLength = 30
|
|
// PATChecksumLength number of characters used for the encoded checksum of the secret inside the token
|
|
PATChecksumLength = 6
|
|
// PATLength total number of characters used for the token
|
|
PATLength = 40
|
|
)
|
|
|
|
// PersonalAccessToken holds all information about a PAT including a hashed version of it for verification
|
|
type PersonalAccessToken struct {
|
|
ID string
|
|
Name string
|
|
HashedToken string
|
|
ExpirationDate time.Time
|
|
// scope could be added in future
|
|
CreatedBy string
|
|
CreatedAt time.Time
|
|
LastUsed time.Time
|
|
}
|
|
|
|
func (t *PersonalAccessToken) Copy() *PersonalAccessToken {
|
|
return &PersonalAccessToken{
|
|
ID: t.ID,
|
|
Name: t.Name,
|
|
HashedToken: t.HashedToken,
|
|
ExpirationDate: t.ExpirationDate,
|
|
CreatedBy: t.CreatedBy,
|
|
CreatedAt: t.CreatedAt,
|
|
LastUsed: t.LastUsed,
|
|
}
|
|
}
|
|
|
|
// PersonalAccessTokenGenerated holds the new PersonalAccessToken and the plain text version of it
|
|
type PersonalAccessTokenGenerated struct {
|
|
PlainToken string
|
|
PersonalAccessToken
|
|
}
|
|
|
|
// CreateNewPAT will generate a new PersonalAccessToken that can be assigned to a User.
|
|
// Additionally, it will return the token in plain text once, to give to the user and only save a hashed version
|
|
func CreateNewPAT(name string, expirationInDays int, createdBy string) (*PersonalAccessTokenGenerated, error) {
|
|
hashedToken, plainToken, err := generateNewToken()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
currentTime := time.Now()
|
|
return &PersonalAccessTokenGenerated{
|
|
PersonalAccessToken: PersonalAccessToken{
|
|
ID: xid.New().String(),
|
|
Name: name,
|
|
HashedToken: hashedToken,
|
|
ExpirationDate: currentTime.AddDate(0, 0, expirationInDays),
|
|
CreatedBy: createdBy,
|
|
CreatedAt: currentTime,
|
|
LastUsed: time.Time{},
|
|
},
|
|
PlainToken: plainToken,
|
|
}, nil
|
|
|
|
}
|
|
|
|
func generateNewToken() (string, string, error) {
|
|
secret, err := b.Random(PATSecretLength)
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
checksum := crc32.ChecksumIEEE([]byte(secret))
|
|
encodedChecksum := base62.Encode(checksum)
|
|
paddedChecksum := fmt.Sprintf("%06s", encodedChecksum)
|
|
plainToken := PATPrefix + secret + paddedChecksum
|
|
hashedToken := sha256.Sum256([]byte(plainToken))
|
|
encodedHashedToken := b64.StdEncoding.EncodeToString(hashedToken[:])
|
|
return encodedHashedToken, plainToken, nil
|
|
}
|