@@ -112,28 +112,11 @@ func RegisterRoutes(e *echo.Echo, store storage.UnitStore, authEnabled bool) {
112
112
e .GET ("/oauth/debug" , authHandler .DebugConfig )
113
113
114
114
115
- // API v1 protected group
115
+ // API v1 protected group - JWT tokens only
116
116
v1 := e .Group ("/v1" )
117
- var verifyFn middleware.AccessTokenVerifier
118
117
if authEnabled {
119
- verifyFn = func (token string ) error {
120
- // JWT only for /v1
121
- if signer == nil {
122
- return echo .ErrUnauthorized
123
- }
124
- _ , err := signer .VerifyAccess (token )
125
- if err != nil {
126
- // Debug: log the verification failure
127
- fmt .Printf ("[AUTH DEBUG] Token verification failed: %v\n " , err )
128
- tokenPreview := token
129
- if len (token ) > 50 {
130
- tokenPreview = token [:50 ] + "..."
131
- }
132
- fmt .Printf ("[AUTH DEBUG] Token preview: %s\n " , tokenPreview )
133
- }
134
- return err
135
- }
136
- v1 .Use (middleware .RequireAuth (verifyFn ))
118
+ jwtVerifyFn := middleware .JWTOnlyVerifier (signer )
119
+ v1 .Use (middleware .RequireAuth (jwtVerifyFn ))
137
120
}
138
121
139
122
// Setup RBAC manager if available
@@ -148,22 +131,22 @@ func RegisterRoutes(e *echo.Echo, store storage.UnitStore, authEnabled bool) {
148
131
// Unit handlers (management API) - pass RBAC manager and signer for filtering
149
132
unitHandler := unithandlers .NewHandler (store , rbacManager , signer )
150
133
151
- // Management API (units) with RBAC middleware
134
+ // Management API (units) with JWT-only RBAC middleware
152
135
if authEnabled && rbacManager != nil {
153
- v1 .POST ("/units" , middleware .RBACMiddleware (rbacManager , signer , rbac .ActionUnitWrite , "*" )(unitHandler .CreateUnit ))
136
+ v1 .POST ("/units" , middleware .JWTOnlyRBACMiddleware (rbacManager , signer , rbac .ActionUnitWrite , "*" )(unitHandler .CreateUnit ))
154
137
// ListUnits does its own RBAC filtering internally, no middleware needed
155
138
v1 .GET ("/units" , unitHandler .ListUnits )
156
- v1 .GET ("/units/:id" , middleware .RBACMiddleware (rbacManager , signer , rbac .ActionUnitRead , "{id}" )(unitHandler .GetUnit ))
157
- v1 .DELETE ("/units/:id" , middleware .RBACMiddleware (rbacManager , signer , rbac .ActionUnitDelete , "{id}" )(unitHandler .DeleteUnit ))
158
- v1 .GET ("/units/:id/download" , middleware .RBACMiddleware (rbacManager , signer , rbac .ActionUnitRead , "{id}" )(unitHandler .DownloadUnit ))
159
- v1 .POST ("/units/:id/upload" , middleware .RBACMiddleware (rbacManager , signer , rbac .ActionUnitWrite , "{id}" )(unitHandler .UploadUnit ))
160
- v1 .POST ("/units/:id/lock" , middleware .RBACMiddleware (rbacManager , signer , rbac .ActionUnitLock , "{id}" )(unitHandler .LockUnit ))
161
- v1 .DELETE ("/units/:id/unlock" , middleware .RBACMiddleware (rbacManager , signer , rbac .ActionUnitLock , "{id}" )(unitHandler .UnlockUnit ))
139
+ v1 .GET ("/units/:id" , middleware .JWTOnlyRBACMiddleware (rbacManager , signer , rbac .ActionUnitRead , "{id}" )(unitHandler .GetUnit ))
140
+ v1 .DELETE ("/units/:id" , middleware .JWTOnlyRBACMiddleware (rbacManager , signer , rbac .ActionUnitDelete , "{id}" )(unitHandler .DeleteUnit ))
141
+ v1 .GET ("/units/:id/download" , middleware .JWTOnlyRBACMiddleware (rbacManager , signer , rbac .ActionUnitRead , "{id}" )(unitHandler .DownloadUnit ))
142
+ v1 .POST ("/units/:id/upload" , middleware .JWTOnlyRBACMiddleware (rbacManager , signer , rbac .ActionUnitWrite , "{id}" )(unitHandler .UploadUnit ))
143
+ v1 .POST ("/units/:id/lock" , middleware .JWTOnlyRBACMiddleware (rbacManager , signer , rbac .ActionUnitLock , "{id}" )(unitHandler .LockUnit ))
144
+ v1 .DELETE ("/units/:id/unlock" , middleware .JWTOnlyRBACMiddleware (rbacManager , signer , rbac .ActionUnitLock , "{id}" )(unitHandler .UnlockUnit ))
162
145
// Dependency/status
163
- v1 .GET ("/units/:id/status" , middleware .RBACMiddleware (rbacManager , signer , rbac .ActionUnitRead , "{id}" )(unitHandler .GetUnitStatus ))
146
+ v1 .GET ("/units/:id/status" , middleware .JWTOnlyRBACMiddleware (rbacManager , signer , rbac .ActionUnitRead , "{id}" )(unitHandler .GetUnitStatus ))
164
147
// Version operations
165
- v1 .GET ("/units/:id/versions" , middleware .RBACMiddleware (rbacManager , signer , rbac .ActionUnitRead , "{id}" )(unitHandler .ListVersions ))
166
- v1 .POST ("/units/:id/restore" , middleware .RBACMiddleware (rbacManager , signer , rbac .ActionUnitWrite , "{id}" )(unitHandler .RestoreVersion ))
148
+ v1 .GET ("/units/:id/versions" , middleware .JWTOnlyRBACMiddleware (rbacManager , signer , rbac .ActionUnitRead , "{id}" )(unitHandler .ListVersions ))
149
+ v1 .POST ("/units/:id/restore" , middleware .JWTOnlyRBACMiddleware (rbacManager , signer , rbac .ActionUnitWrite , "{id}" )(unitHandler .RestoreVersion ))
167
150
} else {
168
151
// Fallback without RBAC
169
152
v1 .POST ("/units" , unitHandler .CreateUnit )
@@ -181,21 +164,23 @@ func RegisterRoutes(e *echo.Echo, store storage.UnitStore, authEnabled bool) {
181
164
v1 .POST ("/units/:id/restore" , unitHandler .RestoreVersion )
182
165
}
183
166
184
- // Terraform HTTP backend proxy with RBAC middleware
167
+ // Terraform HTTP backend proxy with JWT-only RBAC middleware
185
168
backendHandler := backend .NewHandler (store )
186
169
if authEnabled && rbacManager != nil {
187
- v1 .GET ("/backend/*" , middleware .RBACMiddleware (rbacManager , signer , rbac .ActionUnitRead , "*" )(backendHandler .GetState ))
188
- v1 .POST ("/backend/*" , middleware .RBACMiddleware (rbacManager , signer , rbac .ActionUnitWrite , "*" )(backendHandler .UpdateState ))
189
- v1 .PUT ("/backend/*" , middleware .RBACMiddleware (rbacManager , signer , rbac .ActionUnitWrite , "*" )(backendHandler .UpdateState ))
190
- // Explicitly wire non-standard HTTP methods used by Terraform backend
191
- e .Add ("LOCK" , "/v1/backend/*" , middleware .RequireAuth (verifyFn )(middleware .RBACMiddleware (rbacManager , signer , rbac .ActionUnitLock , "*" )(backendHandler .HandleLockUnlock )))
192
- e .Add ("UNLOCK" , "/v1/backend/*" , middleware .RequireAuth (verifyFn )(middleware .RBACMiddleware (rbacManager , signer , rbac .ActionUnitLock , "*" )(backendHandler .HandleLockUnlock )))
170
+ v1 .GET ("/backend/*" , middleware .JWTOnlyRBACMiddleware (rbacManager , signer , rbac .ActionUnitRead , "*" )(backendHandler .GetState ))
171
+ v1 .POST ("/backend/*" , middleware .JWTOnlyRBACMiddleware (rbacManager , signer , rbac .ActionUnitWrite , "*" )(backendHandler .UpdateState ))
172
+ v1 .PUT ("/backend/*" , middleware .JWTOnlyRBACMiddleware (rbacManager , signer , rbac .ActionUnitWrite , "*" )(backendHandler .UpdateState ))
173
+ // Explicitly wire non-standard HTTP methods used by Terraform backend
174
+ jwtVerifyFn := middleware .JWTOnlyVerifier (signer )
175
+ e .Add ("LOCK" , "/v1/backend/*" , middleware .RequireAuth (jwtVerifyFn )(middleware .JWTOnlyRBACMiddleware (rbacManager , signer , rbac .ActionUnitLock , "*" )(backendHandler .HandleLockUnlock )))
176
+ e .Add ("UNLOCK" , "/v1/backend/*" , middleware .RequireAuth (jwtVerifyFn )(middleware .JWTOnlyRBACMiddleware (rbacManager , signer , rbac .ActionUnitLock , "*" )(backendHandler .HandleLockUnlock )))
193
177
} else if authEnabled {
178
+ jwtVerifyFn := middleware .JWTOnlyVerifier (signer )
194
179
v1 .GET ("/backend/*" , backendHandler .GetState )
195
180
v1 .POST ("/backend/*" , backendHandler .UpdateState )
196
181
v1 .PUT ("/backend/*" , backendHandler .UpdateState )
197
- e .Add ("LOCK" , "/v1/backend/*" , middleware .RequireAuth (verifyFn )(backendHandler .HandleLockUnlock ))
198
- e .Add ("UNLOCK" , "/v1/backend/*" , middleware .RequireAuth (verifyFn )(backendHandler .HandleLockUnlock ))
182
+ e .Add ("LOCK" , "/v1/backend/*" , middleware .RequireAuth (jwtVerifyFn )(backendHandler .HandleLockUnlock ))
183
+ e .Add ("UNLOCK" , "/v1/backend/*" , middleware .RequireAuth (jwtVerifyFn )(backendHandler .HandleLockUnlock ))
199
184
} else {
200
185
v1 .GET ("/backend/*" , backendHandler .GetState )
201
186
v1 .POST ("/backend/*" , backendHandler .UpdateState )
@@ -248,26 +233,11 @@ func RegisterRoutes(e *echo.Echo, store storage.UnitStore, authEnabled bool) {
248
233
// TFE api - inject auth handler, storage, and RBAC dependencies
249
234
tfeHandler := tfe .NewTFETokenHandler (authHandler , store , rbacManager ) // Pass rbacManager (may be nil)
250
235
251
- // Create protected TFE group
236
+ // Create protected TFE group - opaque tokens only
252
237
tfeGroup := e .Group ("/tfe/api/v2" )
253
238
if authEnabled {
254
- // Verifier for TFE: accept JWT or opaque TFE tokens
255
- tfeVerify := func (token string ) error {
256
- // Try JWT first
257
- if signer != nil {
258
- if _ , err := signer .VerifyAccess (token ); err == nil {
259
- return nil
260
- }
261
- }
262
- // Fallback to opaque via S3-backed manager
263
- if apiTokenMgr != nil {
264
- if _ , err := apiTokenMgr .Verify (context .Background (), token ); err == nil {
265
- return nil
266
- }
267
- }
268
- return echo .ErrUnauthorized
269
- }
270
- tfeGroup .Use (middleware .RequireAuth (tfeVerify ))
239
+ opaqueVerifyFn := middleware .OpaqueOnlyVerifier (apiTokenMgr )
240
+ tfeGroup .Use (middleware .RequireAuth (opaqueVerifyFn ))
271
241
}
272
242
273
243
// Move TFE endpoints to protected group
0 commit comments