auth
auth/token_test.go
Create Docker image for authd. Create a Dockerfile for authd, which will wrap the compiled Go binary up into a tiny little Docker image. Create an authd/build-docker.sh script that will build the statically-linked binary in a Docker container, so the authd Docker image can use it. We had to include ca-certificates.crt in the Dockerfile, as well, so we could communicate over SSL with things. A wrapper.sh file is included that will pull the JWT_SECRET environment variable out of a kubernetes secrets file, which is a handy wrapper to have. Finally, we added the authd/docker-authd binary to the .hgignore.
1 package auth
3 import (
4 "os"
5 "testing"
6 "time"
8 "code.secondbit.org/uuid.hg"
9 )
11 func init() {
12 if os.Getenv("PG_TEST_DB") != "" {
13 p, err := NewPostgres(os.Getenv("PG_TEST_DB"))
14 if err != nil {
15 panic(err)
16 }
17 tokenStores = append(tokenStores, &p)
18 }
19 }
21 var tokenStores = []tokenStore{NewMemstore()}
23 func compareTokens(token1, token2 Token) (success bool, field string, val1, val2 interface{}) {
24 if token1.AccessToken != token2.AccessToken {
25 return false, "access token", token1.AccessToken, token2.AccessToken
26 }
27 if token1.RefreshToken != token2.RefreshToken {
28 return false, "refresh token", token1.RefreshToken, token2.RefreshToken
29 }
30 if !token1.Created.Equal(token2.Created) {
31 return false, "created", token1.Created, token2.Created
32 }
33 if token1.CreatedFrom != token2.CreatedFrom {
34 return false, "created from", token1.CreatedFrom, token2.CreatedFrom
35 }
36 if token1.ExpiresIn != token2.ExpiresIn {
37 return false, "expires in", token1.ExpiresIn, token2.ExpiresIn
38 }
39 if token1.TokenType != token2.TokenType {
40 return false, "token type", token1.TokenType, token2.TokenType
41 }
42 if len(token1.Scopes) != len(token2.Scopes) {
43 return false, "scopes", token1.Scopes, token2.Scopes
44 }
45 for pos, scope := range token1.Scopes {
46 if scope != token2.Scopes[pos] {
47 return false, "scopes", token1.Scopes, token2.Scopes
48 }
49 }
50 if !token1.ProfileID.Equal(token2.ProfileID) {
51 return false, "profile ID", token1.ProfileID, token2.ProfileID
52 }
53 if token1.Revoked != token2.Revoked {
54 return false, "revoked", token1.Revoked, token2.Revoked
55 }
56 return true, "", nil, nil
57 }
59 func TestTokenStoreSuccess(t *testing.T) {
60 t.Parallel()
61 token := Token{
62 AccessToken: "access",
63 RefreshToken: "refresh",
64 Created: time.Now().Round(time.Millisecond),
65 ExpiresIn: 3600,
66 TokenType: "bearer",
67 Scopes: stringsToScopes([]string{"scope"}),
68 ProfileID: uuid.NewID(),
69 }
70 for _, store := range tokenStores {
71 context := Context{tokens: store}
72 retrievedAccess, err := context.GetToken(token.AccessToken, false)
73 if err == nil {
74 t.Errorf("Expected ErrTokenNotFound from %T, got %+v", store, retrievedAccess)
75 } else if err != ErrTokenNotFound {
76 t.Errorf("Expected ErrTokenNotFound from %T, got %s", store, err)
77 }
78 retrievedRefresh, err := context.GetToken(token.RefreshToken, true)
79 if err == nil {
80 t.Errorf("Expected ErrTokenNotFound from %T, got %+v", store, retrievedRefresh)
81 } else if err != ErrTokenNotFound {
82 t.Errorf("Expected ErrTokenNotFound from %T, got %s", store, err)
83 }
84 err = context.RevokeToken(token.RefreshToken)
85 if err != ErrTokenNotFound {
86 t.Errorf("Expected ErrTokenNotFound from %T, got %s", store, err)
87 }
88 err = context.SaveToken(token)
89 if err != nil {
90 t.Errorf("Error saving token to %T: %s", store, err)
91 }
92 err = context.SaveToken(token)
93 if err != ErrTokenAlreadyExists {
94 t.Errorf("Expected ErrTokenAlreadyExists from %T, got %s", store, err)
95 }
96 retrievedAccess, err = context.GetToken(token.AccessToken, false)
97 if err != nil {
98 t.Errorf("Error retrieving token from %T: %s", store, err)
99 }
100 success, field, expectation, result := compareTokens(token, retrievedAccess)
101 if !success {
102 t.Errorf("Expected field %s to be %v, but got %v from %T", field, expectation, result, store)
103 }
104 retrievedRefresh, err = context.GetToken(token.RefreshToken, true)
105 if err != nil {
106 t.Errorf("Error retrieving refresh token from %T: %s", store, err)
107 }
108 success, field, expectation, result = compareTokens(token, retrievedRefresh)
109 if !success {
110 t.Errorf("Expected field %s to be %v, but got %v from %T", field, expectation, result, store)
111 }
112 retrievedProfile, err := context.GetTokensByProfileID(token.ProfileID, 25, 0)
113 if err != nil {
114 t.Errorf("Error retrieving token by profile from %T: %s", store, err)
115 }
116 if len(retrievedProfile) != 1 {
117 t.Errorf("Expected 1 token retrieved by profile ID from %T, got %+v", store, retrievedProfile)
118 }
119 success, field, expectation, result = compareTokens(token, retrievedProfile[0])
120 if !success {
121 t.Errorf("Expected field %s to be %v, but got %v from %T", field, expectation, result, store)
122 }
123 err = context.RevokeToken(token.RefreshToken)
124 if err != nil {
125 t.Errorf("Error revoking token in %T: %s", store, err)
126 }
127 retrievedRevoked, err := context.GetToken(token.AccessToken, false)
128 if err != nil {
129 t.Errorf("Error retrieving token from %T: %s", store, err)
130 }
131 token.Revoked = true
132 success, field, expectation, result = compareTokens(token, retrievedRevoked)
133 if !success {
134 t.Errorf("Expected field %s to be %v, but got %v from %T", field, expectation, result, store)
135 }
136 }
137 }
139 // BUG(paddy): We need to test the refreshTokenValidate function.
140 // BUG(paddy): We need to test the refreshTokenInvalidate function.