Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/public-api-server/pkg/auth/personal_access_token_test.go
2500 views
1
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package auth
6
7
import (
8
"crypto/sha256"
9
"encoding/base64"
10
"encoding/hex"
11
"fmt"
12
"regexp"
13
"testing"
14
15
"github.com/stretchr/testify/require"
16
)
17
18
func TestGeneratePersonalAccessToken(t *testing.T) {
19
signer := NewHS256Signer([]byte("my-secret"))
20
21
pat, err := GeneratePersonalAccessToken(signer)
22
require.NoError(t, err)
23
24
signature, err := signer.Sign([]byte(pat.value))
25
require.NoError(t, err)
26
27
require.NotEmpty(t, pat.value)
28
require.Len(t, pat.value, 40)
29
require.Equal(t, PersonalAccessToken{
30
prefix: PersonalAccessTokenPrefix,
31
value: pat.value,
32
signature: base64.RawURLEncoding.EncodeToString(signature),
33
}, pat)
34
require.Equal(t, fmt.Sprintf("%s%s.%s", pat.prefix, pat.signature, pat.value), pat.String())
35
36
// must also be able to parse the token back
37
parsed, err := ParsePersonalAccessToken(pat.String(), signer)
38
require.NoError(t, err)
39
require.Equal(t, pat, parsed)
40
}
41
42
func TestPersonalAccessToken_HashValue(t *testing.T) {
43
signer := NewHS256Signer([]byte("my-secret"))
44
pat, err := GeneratePersonalAccessToken(signer)
45
require.NoError(t, err)
46
47
h := sha256.Sum256([]byte(pat.value))
48
49
require.Equal(t, hex.EncodeToString(h[:]), pat.ValueHash(), "hash value must be hex sha-256 hash of value")
50
}
51
52
func TestParsePersonalAccessToken_Errors(t *testing.T) {
53
signer := NewHS256Signer([]byte("my-secret"))
54
55
scenarios := []struct {
56
Name string
57
Token string
58
}{
59
{
60
Name: "empty token is rejected",
61
Token: "",
62
},
63
{
64
Name: "invalid prefix",
65
Token: "gitpod_yolo_fooo",
66
},
67
{
68
Name: "invalid token with correct prefix",
69
Token: "gitpod_pat_foo",
70
},
71
{
72
Name: "invalid token with correct prefix and empty value and signature",
73
Token: "gitpod_pat_.",
74
},
75
{
76
Name: "invalid token with correct prefix but missing signature",
77
Token: "gitpod_pat_.value",
78
},
79
{
80
Name: "invalid token with correct prefix but missing value",
81
Token: "gitpod_pat_signature.",
82
},
83
{
84
Name: "invalid signature",
85
Token: "gitpod_pat_signature.value",
86
},
87
}
88
89
for _, s := range scenarios {
90
t.Run(s.Name, func(t *testing.T) {
91
_, err := ParsePersonalAccessToken(s.Token, signer)
92
require.Error(t, err)
93
})
94
95
}
96
}
97
98
func TestGenerateTokenValue_OnlyAlphaNumberic(t *testing.T) {
99
sizes := []int{10, 20, 30, 40, 50, 60, 70, 80}
100
101
var tokens []string
102
for _, size := range sizes {
103
for i := 0; i < 10; i++ {
104
token, err := generateTokenValue(size)
105
require.NoError(t, err)
106
107
tokens = append(tokens, token)
108
}
109
}
110
111
for _, token := range tokens {
112
rxp := regexp.MustCompile(`([a-zA-Z]|\d)+`)
113
require.Regexp(t, rxp, token, "must match alphanumeric")
114
}
115
}
116
117
func TestGenerateTokenValue_FailsWithSizeZeroOrSmaller(t *testing.T) {
118
_, err := generateTokenValue(0)
119
require.Error(t, err)
120
121
_, err = generateTokenValue(-1)
122
require.Error(t, err)
123
}
124
125