UpdateClientConfiguration returns an http.HandlerFunc that handles PUT /oauth2/clients/{client_id}
(db database.Store, auditor *audit.Auditor, logger slog.Logger)
| 233 | |
| 234 | // UpdateClientConfiguration returns an http.HandlerFunc that handles PUT /oauth2/clients/{client_id} |
| 235 | func UpdateClientConfiguration(db database.Store, auditor *audit.Auditor, logger slog.Logger) http.HandlerFunc { |
| 236 | return func(rw http.ResponseWriter, r *http.Request) { |
| 237 | ctx := r.Context() |
| 238 | aReq, commitAudit := audit.InitRequest[database.OAuth2ProviderApp](rw, &audit.RequestParams{ |
| 239 | Audit: *auditor, |
| 240 | Log: logger, |
| 241 | Request: r, |
| 242 | Action: database.AuditActionWrite, |
| 243 | }) |
| 244 | defer commitAudit() |
| 245 | |
| 246 | // Extract client ID from URL path |
| 247 | clientIDStr := chi.URLParam(r, "client_id") |
| 248 | clientID, err := uuid.Parse(clientIDStr) |
| 249 | if err != nil { |
| 250 | writeOAuth2RegistrationError(ctx, rw, http.StatusBadRequest, |
| 251 | "invalid_client_metadata", "Invalid client ID format") |
| 252 | return |
| 253 | } |
| 254 | |
| 255 | // Parse request |
| 256 | var req codersdk.OAuth2ClientRegistrationRequest |
| 257 | if !httpapi.Read(ctx, rw, r, &req) { |
| 258 | return |
| 259 | } |
| 260 | |
| 261 | // Validate request |
| 262 | if err := req.Validate(); err != nil { |
| 263 | writeOAuth2RegistrationError(ctx, rw, http.StatusBadRequest, |
| 264 | "invalid_client_metadata", err.Error()) |
| 265 | return |
| 266 | } |
| 267 | |
| 268 | // Apply defaults |
| 269 | req = req.ApplyDefaults() |
| 270 | |
| 271 | // Get existing app to verify it exists and is dynamically registered |
| 272 | //nolint:gocritic // OAuth2 system context — RFC 7592 client configuration endpoint |
| 273 | existingApp, err := db.GetOAuth2ProviderAppByClientID(dbauthz.AsSystemOAuth2(ctx), clientID) |
| 274 | if err == nil { |
| 275 | aReq.Old = existingApp |
| 276 | } |
| 277 | if err != nil { |
| 278 | if xerrors.Is(err, sql.ErrNoRows) { |
| 279 | writeOAuth2RegistrationError(ctx, rw, http.StatusUnauthorized, |
| 280 | "invalid_token", "Client not found") |
| 281 | } else { |
| 282 | writeOAuth2RegistrationError(ctx, rw, http.StatusInternalServerError, |
| 283 | "server_error", "Failed to retrieve client") |
| 284 | } |
| 285 | return |
| 286 | } |
| 287 | |
| 288 | // Check if client was dynamically registered |
| 289 | if !existingApp.DynamicallyRegistered.Bool { |
| 290 | writeOAuth2RegistrationError(ctx, rw, http.StatusForbidden, |
| 291 | "invalid_token", "Client was not dynamically registered") |
| 292 | return |
no test coverage detected