7
7
"bytes"
8
8
"encoding/json"
9
9
"fmt"
10
- "log"
10
+ "log/slog "
11
11
"net/http"
12
12
"os"
13
13
"path/filepath"
@@ -89,7 +89,7 @@ func (s *IDPServer) LoadFunnelClients() error {
89
89
}
90
90
}
91
91
if migrationPerformed {
92
- log . Println ("Migrated old funnel clients with single redirect_uri to redirect_uris field." )
92
+ slog . Info ("Migrated old funnel clients with single redirect_uri to redirect_uris field." )
93
93
if err := s .storeFunnelClientsLocked (); err != nil {
94
94
return fmt .Errorf ("failed to store migrated clients: %w" , err )
95
95
}
@@ -122,7 +122,7 @@ func (s *IDPServer) storeFunnelClientsLocked() error {
122
122
// Migrated from legacy/tsidp.go:2055-2094
123
123
func (s * IDPServer ) serveClients (w http.ResponseWriter , r * http.Request ) {
124
124
if isFunnelRequest (r ) {
125
- http . Error (w , "tsidp: not found" , http . StatusNotFound )
125
+ writeHTTPError (w , r , http . StatusUnauthorized , "access_denied" , "not available over funnel" )
126
126
return
127
127
}
128
128
@@ -142,7 +142,7 @@ func (s *IDPServer) serveClients(w http.ResponseWriter, r *http.Request) {
142
142
s .mu .Unlock ()
143
143
144
144
if ! ok {
145
- http . Error (w , " tsidp: client not found", http . StatusNotFound )
145
+ writeHTTPError (w , r , http . StatusNotFound , "not_found" , " tsidp: client not found" )
146
146
return
147
147
}
148
148
@@ -157,21 +157,21 @@ func (s *IDPServer) serveClients(w http.ResponseWriter, r *http.Request) {
157
157
RedirectURIs : c .RedirectURIs ,
158
158
})
159
159
default :
160
- http . Error (w , " tsidp: method not allowed", http . StatusMethodNotAllowed )
160
+ writeHTTPError (w , r , http . StatusMethodNotAllowed , "invalid_request" , " tsidp: method not allowed" )
161
161
}
162
162
}
163
163
164
164
// serveNewClient creates a new OAuth client
165
165
// Migrated from legacy/tsidp.go:2096-2126
166
166
func (s * IDPServer ) serveNewClient (w http.ResponseWriter , r * http.Request ) {
167
167
if r .Method != "POST" {
168
- http . Error (w , " tsidp: method not allowed", http . StatusMethodNotAllowed )
168
+ writeHTTPError (w , r , http . StatusMethodNotAllowed , "invalid_request" , " tsidp: method not allowed" )
169
169
return
170
170
}
171
171
redirectURI := r .FormValue ("redirect_uri" )
172
172
name := r .FormValue ("name" )
173
173
if redirectURI == "" || name == "" {
174
- http . Error (w , " tsidp: missing redirect_uri or name", http . StatusBadRequest )
174
+ writeHTTPError (w , r , http . StatusBadRequest , "invalid_request" , " tsidp: missing redirect_uri or name" )
175
175
return
176
176
}
177
177
@@ -196,7 +196,7 @@ func (s *IDPServer) serveNewClient(w http.ResponseWriter, r *http.Request) {
196
196
s .funnelClients [clientID ] = client
197
197
198
198
if err := s .storeFunnelClientsLocked (); err != nil {
199
- http . Error (w , fmt .Sprintf ("tsidp: failed to store client: %v" , err ), http . StatusInternalServerError )
199
+ writeHTTPError (w , r , http . StatusInternalServerError , "server_error" , fmt .Sprintf ("tsidp: failed to store client: %v" , err ))
200
200
return
201
201
}
202
202
@@ -207,7 +207,7 @@ func (s *IDPServer) serveNewClient(w http.ResponseWriter, r *http.Request) {
207
207
// Migrated from legacy/tsidp.go:2128-2145
208
208
func (s * IDPServer ) serveGetClientsList (w http.ResponseWriter , r * http.Request ) {
209
209
if r .Method != "GET" {
210
- http . Error (w , " tsidp: method not allowed", http . StatusMethodNotAllowed )
210
+ writeHTTPError (w , r , http . StatusMethodNotAllowed , "invalid_request" , " tsidp: method not allowed" )
211
211
return
212
212
}
213
213
s .mu .Lock ()
@@ -231,14 +231,14 @@ func (s *IDPServer) serveGetClientsList(w http.ResponseWriter, r *http.Request)
231
231
// Migrated from legacy/tsidp.go:2239-2265
232
232
func (s * IDPServer ) serveDeleteClient (w http.ResponseWriter , r * http.Request , clientID string ) {
233
233
if r .Method != "DELETE" {
234
- http . Error (w , " tsidp: method not allowed", http . StatusMethodNotAllowed )
234
+ writeHTTPError (w , r , http . StatusMethodNotAllowed , "invalid_request" , " tsidp: method not allowed" )
235
235
return
236
236
}
237
237
s .mu .Lock ()
238
238
defer s .mu .Unlock ()
239
239
240
240
if _ , ok := s .funnelClients [clientID ]; ! ok {
241
- http . Error (w , " tsidp: client not found", http . StatusNotFound )
241
+ writeHTTPError (w , r , http . StatusNotFound , "not_found" , " tsidp: client not found" )
242
242
return
243
243
}
244
244
@@ -262,7 +262,7 @@ func (s *IDPServer) serveDeleteClient(w http.ResponseWriter, r *http.Request, cl
262
262
}
263
263
264
264
if err := s .storeFunnelClientsLocked (); err != nil {
265
- http . Error (w , fmt .Sprintf ("tsidp: failed to store clients: %v" , err ), http . StatusInternalServerError )
265
+ writeHTTPError (w , r , http . StatusInternalServerError , "server_error" , fmt .Sprintf ("tsidp: failed to store clients: %v" , err ))
266
266
return
267
267
}
268
268
@@ -274,9 +274,10 @@ func (s *IDPServer) serveDeleteClient(w http.ResponseWriter, r *http.Request, cl
274
274
func (s * IDPServer ) serveDynamicClientRegistration (w http.ResponseWriter , r * http.Request ) {
275
275
// Block funnel requests - dynamic registration is only available over tailnet
276
276
if isFunnelRequest (r ) {
277
- writeJSONError (w , http .StatusForbidden , "access_denied" , "dynamic client registration not available over funnel" )
277
+ writeHTTPError (w , r , http .StatusUnauthorized , "access_denied" , "not available over funnel" )
278
278
return
279
279
}
280
+
280
281
h := w .Header ()
281
282
h .Set ("Access-Control-Allow-Origin" , "*" )
282
283
h .Set ("Access-Control-Allow-Method" , "POST, OPTIONS" )
@@ -288,18 +289,18 @@ func (s *IDPServer) serveDynamicClientRegistration(w http.ResponseWriter, r *htt
288
289
}
289
290
290
291
if r .Method != "POST" {
291
- writeJSONError ( w , http .StatusMethodNotAllowed , "invalid_request" , "method not allowed" )
292
+ writeHTTPError ( w , r , http .StatusMethodNotAllowed , "invalid_request" , "method not allowed" )
292
293
return
293
294
}
294
295
295
296
access , ok := r .Context ().Value (appCapCtxKey ).(* accessGrantedRules )
296
297
if ! ok {
297
- writeJSONError ( w , http .StatusForbidden , "access_denied" , "application capability not found" )
298
+ writeHTTPError ( w , r , http .StatusForbidden , "access_denied" , "application capability not found" )
298
299
return
299
300
}
300
301
301
302
if ! access .allowDCR {
302
- writeJSONError ( w , http .StatusForbidden , "access_denied" , "application capability not granted" )
303
+ writeHTTPError ( w , r , http .StatusForbidden , "access_denied" , "application capability not granted" )
303
304
return
304
305
}
305
306
@@ -317,13 +318,13 @@ func (s *IDPServer) serveDynamicClientRegistration(w http.ResponseWriter, r *htt
317
318
}
318
319
319
320
if err := json .NewDecoder (r .Body ).Decode (& registrationRequest ); err != nil {
320
- writeJSONError ( w , http .StatusBadRequest , "invalid_request" , "invalid request body" )
321
+ writeHTTPError ( w , r , http .StatusBadRequest , "invalid_request" , "invalid request body" )
321
322
return
322
323
}
323
324
324
325
// Validate required fields
325
326
if len (registrationRequest .RedirectURIs ) == 0 {
326
- writeJSONError ( w , http .StatusBadRequest , "invalid_client_metadata" , "redirect_uris is required" )
327
+ writeHTTPError ( w , r , http .StatusBadRequest , "invalid_client_metadata" , "redirect_uris is required" )
327
328
return
328
329
}
329
330
@@ -371,7 +372,7 @@ func (s *IDPServer) serveDynamicClientRegistration(w http.ResponseWriter, r *htt
371
372
s .funnelClients [clientID ] = client
372
373
373
374
if err := s .storeFunnelClientsLocked (); err != nil {
374
- writeJSONError ( w , http .StatusInternalServerError , "server_error" , "failed to store client" )
375
+ writeHTTPError ( w , r , http .StatusInternalServerError , "server_error" , "failed to store client" )
375
376
return
376
377
}
377
378
0 commit comments