@cryptotaxi247 / kubo / commits / 140486108

test: add regression tests for API.Authorizations (#11060)

Marcin Rataj committed Nov 17, 2025 at 18:52 UTC 1404861086ae9fece37c651f451ecad812413140
1 file changed +123
test/cli/rpc_auth_test.go
+123
@@ -159,4 +159,127 @@ func TestRPCAuth(t *testing.T) {
159
160 node.StopDaemon()
161 })
162 +
163 + t.Run("Requests without Authorization header are rejected when auth is enabled", func(t *testing.T) {
164 + t.Parallel()
165 +
166 + node := makeAndStartProtectedNode(t, map[string]*config.RPCAuthScope{
167 + "userA": {
168 + AuthSecret: "bearer:mytoken",
169 + AllowedPaths: []string{"/api/v0"},
170 + },
171 + })
172 +
173 + // Create client with NO auth
174 + apiClient := node.APIClient() // Uses http.DefaultClient with no auth headers
175 +
176 + // Should be denied without auth header
177 + resp := apiClient.Post("/api/v0/id", nil)
178 + assert.Equal(t, 403, resp.StatusCode)
179 +
180 + // Should contain denial message
181 + assert.Contains(t, resp.Body, rpcDeniedMsg)
182 +
183 + node.StopDaemon()
184 + })
185 +
186 + t.Run("Version endpoint is always accessible even with limited AllowedPaths", func(t *testing.T) {
187 + t.Parallel()
188 +
189 + node := makeAndStartProtectedNode(t, map[string]*config.RPCAuthScope{
190 + "userA": {
191 + AuthSecret: "bearer:mytoken",
192 + AllowedPaths: []string{"/api/v0/id"}, // Only /id allowed
193 + },
194 + })
195 +
196 + apiClient := node.APIClient()
197 + apiClient.Client = &http.Client{
198 + Transport: auth.NewAuthorizedRoundTripper("Bearer mytoken", http.DefaultTransport),
199 + }
200 +
201 + // Can access /version even though not in AllowedPaths
202 + resp := apiClient.Post("/api/v0/version", nil)
203 + assert.Equal(t, 200, resp.StatusCode)
204 +
205 + node.StopDaemon()
206 + })
207 +
208 + t.Run("User cannot access API with another user's secret", func(t *testing.T) {
209 + t.Parallel()
210 +
211 + node := makeAndStartProtectedNode(t, map[string]*config.RPCAuthScope{
212 + "alice": {
213 + AuthSecret: "bearer:alice-secret",
214 + AllowedPaths: []string{"/api/v0/id"},
215 + },
216 + "bob": {
217 + AuthSecret: "bearer:bob-secret",
218 + AllowedPaths: []string{"/api/v0/config"},
219 + },
220 + })
221 +
222 + // Alice tries to use Bob's secret
223 + apiClient := node.APIClient()
224 + apiClient.Client = &http.Client{
225 + Transport: auth.NewAuthorizedRoundTripper("Bearer bob-secret", http.DefaultTransport),
226 + }
227 +
228 + // Bob's secret should work for Bob's paths
229 + resp := apiClient.Post("/api/v0/config/show", nil)
230 + assert.Equal(t, 200, resp.StatusCode)
231 +
232 + // But not for Alice's paths (Bob doesn't have access to /id)
233 + resp = apiClient.Post("/api/v0/id", nil)
234 + assert.Equal(t, 403, resp.StatusCode)
235 +
236 + node.StopDaemon()
237 + })
238 +
239 + t.Run("Empty AllowedPaths denies all access except version", func(t *testing.T) {
240 + t.Parallel()
241 +
242 + node := makeAndStartProtectedNode(t, map[string]*config.RPCAuthScope{
243 + "userA": {
244 + AuthSecret: "bearer:mytoken",
245 + AllowedPaths: []string{}, // Empty!
246 + },
247 + })
248 +
249 + apiClient := node.APIClient()
250 + apiClient.Client = &http.Client{
251 + Transport: auth.NewAuthorizedRoundTripper("Bearer mytoken", http.DefaultTransport),
252 + }
253 +
254 + // Should deny everything
255 + resp := apiClient.Post("/api/v0/id", nil)
256 + assert.Equal(t, 403, resp.StatusCode)
257 +
258 + resp = apiClient.Post("/api/v0/config/show", nil)
259 + assert.Equal(t, 403, resp.StatusCode)
260 +
261 + // Except version
262 + resp = apiClient.Post("/api/v0/version", nil)
263 + assert.Equal(t, 200, resp.StatusCode)
264 +
265 + node.StopDaemon()
266 + })
267 +
268 + t.Run("CLI commands fail without --api-auth when auth is enabled", func(t *testing.T) {
269 + t.Parallel()
270 +
271 + node := makeAndStartProtectedNode(t, map[string]*config.RPCAuthScope{
272 + "userA": {
273 + AuthSecret: "bearer:mytoken",
274 + AllowedPaths: []string{"/api/v0"},
275 + },
276 + })
277 +
278 + // Try to run command without --api-auth flag
279 + resp := node.RunIPFS("id") // No --api-auth flag
280 + require.Error(t, resp.Err)
281 + require.Contains(t, resp.Stderr.String(), rpcDeniedMsg)
282 +
283 + node.StopDaemon()
284 + })
285 }