@@ -16,6 +16,7 @@ package security
1616
1717import (
1818 "context"
19+ "fmt"
1920 "net/http"
2021 "testing"
2122
@@ -25,181 +26,199 @@ import (
2526)
2627
2728const (
28- apiToken = "token123 "
29- apiTokenPrincipal = "admin "
29+ apiKeyParam = "api_key "
30+ apiKeyHeader = "X-API-KEY "
3031)
3132
32- var tokenAuth = TokenAuthentication (func (token string ) (interface {}, error ) {
33- if token == apiToken {
34- return apiTokenPrincipal , nil
35- }
36- return nil , errors .Unauthenticated ("token" )
37- })
38-
39- var tokenAuthCtx = TokenAuthenticationCtx (func (ctx context.Context , token string ) (context.Context , interface {}, error ) {
40- if token == apiToken {
41- return context .WithValue (ctx , extra , extraWisdom ), apiTokenPrincipal , nil
42- }
43- return context .WithValue (ctx , reason , expReason ), nil , errors .Unauthenticated ("token" )
44- })
45-
46- func TestInvalidApiKeyAuthInitialization (t * testing.T ) {
47- assert .Panics (t , func () { APIKeyAuth ("api_key" , "qery" , tokenAuth ) })
33+ func TestApiKeyAuth (t * testing.T ) {
34+ tokenAuth := TokenAuthentication (func (token string ) (interface {}, error ) {
35+ if token == validToken {
36+ return principal , nil
37+ }
38+ return nil , errors .Unauthenticated ("token" )
39+ })
40+
41+ t .Run ("with invalid initialization" , func (t * testing.T ) {
42+ assert .Panics (t , func () { APIKeyAuth (apiKeyParam , "qery" , tokenAuth ) })
43+ })
44+
45+ t .Run ("with token in query param" , func (t * testing.T ) {
46+ ta := APIKeyAuth (apiKeyParam , query , tokenAuth )
47+
48+ t .Run ("with valid token" , func (t * testing.T ) {
49+ req , err := http .NewRequestWithContext (context .Background (), http .MethodGet , fmt .Sprintf ("%s?%s=%s" , authPath , apiKeyParam , validToken ), nil )
50+ require .NoError (t , err )
51+
52+ ok , usr , err := ta .Authenticate (req )
53+ assert .True (t , ok )
54+ assert .Equal (t , principal , usr )
55+ require .NoError (t , err )
56+ })
57+
58+ t .Run ("with invalid token" , func (t * testing.T ) {
59+ req , err := http .NewRequestWithContext (context .Background (), http .MethodGet , fmt .Sprintf ("%s?%s=%s" , authPath , apiKeyParam , invalidToken ), nil )
60+ require .NoError (t , err )
61+
62+ ok , usr , err := ta .Authenticate (req )
63+ assert .True (t , ok )
64+ assert .Equal (t , nil , usr )
65+ require .Error (t , err )
66+ })
67+
68+ t .Run ("with missing token" , func (t * testing.T ) {
69+ // put the token in the header, but query param is expected
70+ req , err := http .NewRequestWithContext (context .Background (), http .MethodGet , authPath , nil )
71+ require .NoError (t , err )
72+ req .Header .Set (apiKeyHeader , validToken )
73+
74+ ok , usr , err := ta .Authenticate (req )
75+ assert .False (t , ok )
76+ assert .Equal (t , nil , usr )
77+ require .NoError (t , err )
78+ })
79+ })
80+
81+ t .Run ("with token in header" , func (t * testing.T ) {
82+ ta := APIKeyAuth (apiKeyHeader , header , tokenAuth )
83+
84+ t .Run ("with valid token" , func (t * testing.T ) {
85+ req , err := http .NewRequestWithContext (context .Background (), http .MethodGet , authPath , nil )
86+ require .NoError (t , err )
87+ req .Header .Set (apiKeyHeader , validToken )
88+
89+ ok , usr , err := ta .Authenticate (req )
90+ assert .True (t , ok )
91+ assert .Equal (t , principal , usr )
92+ require .NoError (t , err )
93+ })
94+
95+ t .Run ("with invalid token" , func (t * testing.T ) {
96+ req , err := http .NewRequestWithContext (context .Background (), http .MethodGet , authPath , nil )
97+ require .NoError (t , err )
98+ req .Header .Set (apiKeyHeader , invalidToken )
99+
100+ ok , usr , err := ta .Authenticate (req )
101+ assert .True (t , ok )
102+ assert .Equal (t , nil , usr )
103+ require .Error (t , err )
104+ })
105+
106+ t .Run ("with missing token" , func (t * testing.T ) {
107+ // put the token in the query param, but header is expected
108+ req , err := http .NewRequestWithContext (context .Background (), http .MethodGet , fmt .Sprintf ("%s?%s=%s" , authPath , apiKeyParam , validToken ), nil )
109+ require .NoError (t , err )
110+
111+ ok , usr , err := ta .Authenticate (req )
112+ assert .False (t , ok )
113+ assert .Equal (t , nil , usr )
114+ require .NoError (t , err )
115+ })
116+ })
48117}
49118
50- func TestValidApiKeyAuth (t * testing.T ) {
51- ta := APIKeyAuth ("api_key" , "query" , tokenAuth )
52- ta2 := APIKeyAuth ("X-API-KEY" , "header" , tokenAuth )
53-
54- req1 , err := http .NewRequestWithContext (context .Background (), http .MethodGet , "/blah?api_key=token123" , nil )
55- require .NoError (t , err )
56-
57- ok , usr , err := ta .Authenticate (req1 )
58- assert .True (t , ok )
59- assert .Equal (t , apiTokenPrincipal , usr )
60- require .NoError (t , err )
61-
62- req2 , err := http .NewRequestWithContext (context .Background (), http .MethodGet , "/blah" , nil )
63- require .NoError (t , err )
64- req2 .Header .Set ("X-API-KEY" , apiToken )
65-
66- ok , usr , err = ta2 .Authenticate (req2 )
67- assert .True (t , ok )
68- assert .Equal (t , apiTokenPrincipal , usr )
69- require .NoError (t , err )
70- }
71-
72- func TestInvalidApiKeyAuth (t * testing.T ) {
73- ta := APIKeyAuth ("api_key" , "query" , tokenAuth )
74- ta2 := APIKeyAuth ("X-API-KEY" , "header" , tokenAuth )
75-
76- req1 , err := http .NewRequestWithContext (context .Background (), http .MethodGet , "/blah?api_key=token124" , nil )
77- require .NoError (t , err )
78-
79- ok , usr , err := ta .Authenticate (req1 )
80- assert .True (t , ok )
81- assert .Equal (t , nil , usr )
82- require .Error (t , err )
83-
84- req2 , err := http .NewRequestWithContext (context .Background (), http .MethodGet , "/blah" , nil )
85- require .NoError (t , err )
86- req2 .Header .Set ("X-API-KEY" , "token124" )
87-
88- ok , usr , err = ta2 .Authenticate (req2 )
89- assert .True (t , ok )
90- assert .Equal (t , nil , usr )
91- require .Error (t , err )
92- }
93-
94- func TestMissingApiKeyAuth (t * testing.T ) {
95- ta := APIKeyAuth ("api_key" , "query" , tokenAuth )
96- ta2 := APIKeyAuth ("X-API-KEY" , "header" , tokenAuth )
97-
98- req1 , err := http .NewRequestWithContext (context .Background (), http .MethodGet , "/blah" , nil )
99- require .NoError (t , err )
100- req1 .Header .Set ("X-API-KEY" , apiToken )
101-
102- ok , usr , err := ta .Authenticate (req1 )
103- assert .False (t , ok )
104- assert .Equal (t , nil , usr )
105- require .NoError (t , err )
106-
107- req2 , err := http .NewRequestWithContext (context .Background (), http .MethodGet , "/blah?api_key=token123" , nil )
108- require .NoError (t , err )
109-
110- ok , usr , err = ta2 .Authenticate (req2 )
111- assert .False (t , ok )
112- assert .Equal (t , nil , usr )
113- require .NoError (t , err )
114- }
115-
116- func TestInvalidApiKeyAuthInitializationCtx (t * testing.T ) {
117- assert .Panics (t , func () { APIKeyAuthCtx ("api_key" , "qery" , tokenAuthCtx ) })
118- }
119-
120- func TestValidApiKeyAuthCtx (t * testing.T ) {
121- ta := APIKeyAuthCtx ("api_key" , "query" , tokenAuthCtx )
122- ta2 := APIKeyAuthCtx ("X-API-KEY" , "header" , tokenAuthCtx )
123-
124- req1 , err := http .NewRequestWithContext (context .Background (), http .MethodGet , "/blah?api_key=token123" , nil )
125- require .NoError (t , err )
126- req1 = req1 .WithContext (context .WithValue (req1 .Context (), original , wisdom ))
127- ok , usr , err := ta .Authenticate (req1 )
128- assert .True (t , ok )
129- assert .Equal (t , apiTokenPrincipal , usr )
130- require .NoError (t , err )
131- assert .Equal (t , wisdom , req1 .Context ().Value (original ))
132- assert .Equal (t , extraWisdom , req1 .Context ().Value (extra ))
133- assert .Nil (t , req1 .Context ().Value (reason ))
134-
135- req2 , err := http .NewRequestWithContext (context .Background (), http .MethodGet , "/blah" , nil )
136- require .NoError (t , err )
137- req2 = req2 .WithContext (context .WithValue (req2 .Context (), original , wisdom ))
138- req2 .Header .Set ("X-API-KEY" , apiToken )
139-
140- ok , usr , err = ta2 .Authenticate (req2 )
141- assert .True (t , ok )
142- assert .Equal (t , apiTokenPrincipal , usr )
143- require .NoError (t , err )
144- assert .Equal (t , wisdom , req2 .Context ().Value (original ))
145- assert .Equal (t , extraWisdom , req2 .Context ().Value (extra ))
146- assert .Nil (t , req2 .Context ().Value (reason ))
147- }
148-
149- func TestInvalidApiKeyAuthCtx (t * testing.T ) {
150- ta := APIKeyAuthCtx ("api_key" , "query" , tokenAuthCtx )
151- ta2 := APIKeyAuthCtx ("X-API-KEY" , "header" , tokenAuthCtx )
152-
153- req1 , err := http .NewRequestWithContext (context .Background (), http .MethodGet , "/blah?api_key=token124" , nil )
154- require .NoError (t , err )
155- req1 = req1 .WithContext (context .WithValue (req1 .Context (), original , wisdom ))
156- ok , usr , err := ta .Authenticate (req1 )
157- assert .True (t , ok )
158- assert .Equal (t , nil , usr )
159- require .Error (t , err )
160- assert .Equal (t , wisdom , req1 .Context ().Value (original ))
161- assert .Equal (t , expReason , req1 .Context ().Value (reason ))
162- assert .Nil (t , req1 .Context ().Value (extra ))
163-
164- req2 , err := http .NewRequestWithContext (context .Background (), http .MethodGet , "/blah" , nil )
165- require .NoError (t , err )
166- req2 = req2 .WithContext (context .WithValue (req2 .Context (), original , wisdom ))
167- req2 .Header .Set ("X-API-KEY" , "token124" )
168-
169- ok , usr , err = ta2 .Authenticate (req2 )
170- assert .True (t , ok )
171- assert .Equal (t , nil , usr )
172- require .Error (t , err )
173- assert .Equal (t , wisdom , req2 .Context ().Value (original ))
174- assert .Equal (t , expReason , req2 .Context ().Value (reason ))
175- assert .Nil (t , req2 .Context ().Value (extra ))
176- }
177-
178- func TestMissingApiKeyAuthCtx (t * testing.T ) {
179- ta := APIKeyAuthCtx ("api_key" , "query" , tokenAuthCtx )
180- ta2 := APIKeyAuthCtx ("X-API-KEY" , "header" , tokenAuthCtx )
181-
182- req1 , err := http .NewRequestWithContext (context .Background (), http .MethodGet , "/blah" , nil )
183- require .NoError (t , err )
184- req1 = req1 .WithContext (context .WithValue (req1 .Context (), original , wisdom ))
185- req1 .Header .Set ("X-API-KEY" , apiToken )
186-
187- ok , usr , err := ta .Authenticate (req1 )
188- assert .False (t , ok )
189- assert .Equal (t , nil , usr )
190- require .NoError (t , err )
191- assert .Equal (t , wisdom , req1 .Context ().Value (original ))
192- assert .Nil (t , req1 .Context ().Value (reason ))
193- assert .Nil (t , req1 .Context ().Value (extra ))
194-
195- req2 , err := http .NewRequestWithContext (context .Background (), http .MethodGet , "/blah?api_key=token123" , nil )
196- require .NoError (t , err )
197- req2 = req2 .WithContext (context .WithValue (req2 .Context (), original , wisdom ))
198- ok , usr , err = ta2 .Authenticate (req2 )
199- assert .False (t , ok )
200- assert .Equal (t , nil , usr )
201- require .NoError (t , err )
202- assert .Equal (t , wisdom , req2 .Context ().Value (original ))
203- assert .Nil (t , req2 .Context ().Value (reason ))
204- assert .Nil (t , req2 .Context ().Value (extra ))
119+ func TestApiKeyAuthCtx (t * testing.T ) {
120+ tokenAuthCtx := TokenAuthenticationCtx (func (ctx context.Context , token string ) (context.Context , interface {}, error ) {
121+ if token == validToken {
122+ return context .WithValue (ctx , extra , extraWisdom ), principal , nil
123+ }
124+ return context .WithValue (ctx , reason , expReason ), nil , errors .Unauthenticated ("token" )
125+ })
126+ ctx := context .WithValue (context .Background (), original , wisdom )
127+
128+ t .Run ("with invalid initialization" , func (t * testing.T ) {
129+ assert .Panics (t , func () { APIKeyAuthCtx (apiKeyParam , "qery" , tokenAuthCtx ) })
130+ })
131+
132+ t .Run ("with token in query param" , func (t * testing.T ) {
133+ ta := APIKeyAuthCtx (apiKeyParam , query , tokenAuthCtx )
134+
135+ t .Run ("with valid token" , func (t * testing.T ) {
136+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , fmt .Sprintf ("%s?%s=%s" , authPath , apiKeyParam , validToken ), nil )
137+ require .NoError (t , err )
138+ ok , usr , err := ta .Authenticate (req )
139+ assert .True (t , ok )
140+ assert .Equal (t , principal , usr )
141+ require .NoError (t , err )
142+
143+ assert .Equal (t , wisdom , req .Context ().Value (original ))
144+ assert .Equal (t , extraWisdom , req .Context ().Value (extra ))
145+ assert .Nil (t , req .Context ().Value (reason ))
146+ })
147+
148+ t .Run ("with invalid token" , func (t * testing.T ) {
149+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , fmt .Sprintf ("%s?%s=%s" , authPath , apiKeyParam , invalidToken ), nil )
150+ require .NoError (t , err )
151+ ok , usr , err := ta .Authenticate (req )
152+ assert .True (t , ok )
153+ assert .Equal (t , nil , usr )
154+ require .Error (t , err )
155+
156+ assert .Equal (t , wisdom , req .Context ().Value (original ))
157+ assert .Equal (t , expReason , req .Context ().Value (reason ))
158+ assert .Nil (t , req .Context ().Value (extra ))
159+ })
160+
161+ t .Run ("with missing token" , func (t * testing.T ) {
162+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , authPath , nil )
163+ require .NoError (t , err )
164+ req .Header .Set (apiKeyHeader , validToken )
165+
166+ ok , usr , err := ta .Authenticate (req )
167+ assert .False (t , ok )
168+ assert .Equal (t , nil , usr )
169+ require .NoError (t , err )
170+
171+ assert .Equal (t , wisdom , req .Context ().Value (original ))
172+ assert .Nil (t , req .Context ().Value (reason ))
173+ assert .Nil (t , req .Context ().Value (extra ))
174+ })
175+ })
176+
177+ t .Run ("with token in header" , func (t * testing.T ) {
178+ ta := APIKeyAuthCtx (apiKeyHeader , header , tokenAuthCtx )
179+
180+ t .Run ("with valid token" , func (t * testing.T ) {
181+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , authPath , nil )
182+ require .NoError (t , err )
183+ req .Header .Set (apiKeyHeader , validToken )
184+
185+ ok , usr , err := ta .Authenticate (req )
186+ assert .True (t , ok )
187+ assert .Equal (t , principal , usr )
188+ require .NoError (t , err )
189+
190+ assert .Equal (t , wisdom , req .Context ().Value (original ))
191+ assert .Equal (t , extraWisdom , req .Context ().Value (extra ))
192+ assert .Nil (t , req .Context ().Value (reason ))
193+ })
194+
195+ t .Run ("with invalid token" , func (t * testing.T ) {
196+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , authPath , nil )
197+ require .NoError (t , err )
198+ req .Header .Set (apiKeyHeader , invalidToken )
199+
200+ ok , usr , err := ta .Authenticate (req )
201+ assert .True (t , ok )
202+ assert .Equal (t , nil , usr )
203+ require .Error (t , err )
204+
205+ assert .Equal (t , wisdom , req .Context ().Value (original ))
206+ assert .Equal (t , expReason , req .Context ().Value (reason ))
207+ assert .Nil (t , req .Context ().Value (extra ))
208+ })
209+
210+ t .Run ("with missing token" , func (t * testing.T ) {
211+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , fmt .Sprintf ("%s?%s=%s" , authPath , apiKeyParam , validToken ), nil )
212+ require .NoError (t , err )
213+
214+ ok , usr , err := ta .Authenticate (req )
215+ assert .False (t , ok )
216+ assert .Equal (t , nil , usr )
217+ require .NoError (t , err )
218+
219+ assert .Equal (t , wisdom , req .Context ().Value (original ))
220+ assert .Nil (t , req .Context ().Value (reason ))
221+ assert .Nil (t , req .Context ().Value (extra ))
222+ })
223+ })
205224}
0 commit comments