detached 3dc5982

refactor(auth): support both password and token auth in password mode

commit
3dc5982577fecde1380e49aa48782435a1c4411d
author
bnema · · 2026-01-18 03:16 UTC
parent
f3f65ba
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
1 file · +8 -1
M internal/adapters/in/http/middleware/auth.go +8 -1
@@ -144,11 +144,18 @@ func RegistryAuthV2(authSvc in.AuthService, internalAuth InternalRegistryAuth, l
144144 ctx := r.Context()
145145
146146 // Authenticate based on auth type
147+ // When auth type is "password", accept BOTH password and token auth
148+ // (allows CI/CD tokens while still supporting interactive password login)
147149 var authenticated bool
148150 var tokenClaims *domain.TokenClaims
149151 switch authSvc.GetAuthType() {
150152 case domain.AuthTypePassword:
153+ // Try password auth first
151154 authenticated = authenticatePassword(ctx, r, authSvc, log)
155+ if !authenticated {
156+ // Fall back to token auth (for CI/CD tokens)
157+ authenticated, tokenClaims = authenticateToken(ctx, r, authSvc, log)
158+ }
152159 case domain.AuthTypeToken:
153160 authenticated, tokenClaims = authenticateToken(ctx, r, authSvc, log)
154161 default:
@@ -410,7 +417,7 @@ func sendUnauthorized(w http.ResponseWriter, authType domain.AuthType, host stri
410417 } else if r.TLS != nil {
411418 scheme = "https"
412419 }
413- realm := scheme + "://" + realmHost + "/v2/token"
420+ realm := scheme + "://" + realmHost + "/auth/token"
414421 w.Header().Set("WWW-Authenticate", `Bearer realm="`+realm+`",service="gordon-registry"`)
415422 default:
416423 w.Header().Set("WWW-Authenticate", `Basic realm="Gordon Registry"`)
@@ -144,11 +144,18 @@ func RegistryAuthV2(authSvc in.AuthService, internalAuth InternalRegistryAuth, l
144 ctx := r.Context()144 ctx := r.Context()
145 145
146 // Authenticate based on auth type146 // Authenticate based on auth type
147+ // When auth type is "password", accept BOTH password and token auth
148+ // (allows CI/CD tokens while still supporting interactive password login)
147 var authenticated bool149 var authenticated bool
148 var tokenClaims *domain.TokenClaims150 var tokenClaims *domain.TokenClaims
149 switch authSvc.GetAuthType() {151 switch authSvc.GetAuthType() {
150 case domain.AuthTypePassword:152 case domain.AuthTypePassword:
153+ // Try password auth first
151 authenticated = authenticatePassword(ctx, r, authSvc, log)154 authenticated = authenticatePassword(ctx, r, authSvc, log)
155+ if !authenticated {
156+ // Fall back to token auth (for CI/CD tokens)
157+ authenticated, tokenClaims = authenticateToken(ctx, r, authSvc, log)
158+ }
152 case domain.AuthTypeToken:159 case domain.AuthTypeToken:
153 authenticated, tokenClaims = authenticateToken(ctx, r, authSvc, log)160 authenticated, tokenClaims = authenticateToken(ctx, r, authSvc, log)
154 default:161 default:
@@ -410,7 +417,7 @@ func sendUnauthorized(w http.ResponseWriter, authType domain.AuthType, host stri
410 } else if r.TLS != nil {417 } else if r.TLS != nil {
411 scheme = "https"418 scheme = "https"
412 }419 }
413- realm := scheme + "://" + realmHost + "/v2/token"420+ realm := scheme + "://" + realmHost + "/auth/token"
414 w.Header().Set("WWW-Authenticate", `Bearer realm="`+realm+`",service="gordon-registry"`)421 w.Header().Set("WWW-Authenticate", `Bearer realm="`+realm+`",service="gordon-registry"`)
415 default:422 default:
416 w.Header().Set("WWW-Authenticate", `Basic realm="Gordon Registry"`)423 w.Header().Set("WWW-Authenticate", `Basic realm="Gordon Registry"`)

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close