P4-05: OIDC login (generic, JIT-provisioned) #16

Merged
steve merged 19 commits from p4-05-oidc into main 2026-05-05 14:46:23 +01:00
2 changed files with 32 additions and 0 deletions
Showing only changes of commit c62d7d3ac3 - Show all commits
+3
View File
@@ -56,6 +56,9 @@ func (s *Server) authenticateAndSession(w stdhttp.ResponseWriter, r *stdhttp.Req
// existence to a probing attacker.
return nil, errInvalidCredentials
}
if u.AuthSource == "oidc" {
return nil, errInvalidCredentials
}
if err := auth.VerifyPassword(u.PasswordHash, password); err != nil {
return nil, errInvalidCredentials
}
@@ -1,7 +1,9 @@
package http
import (
"bytes"
"context"
"encoding/json"
stdhttp "net/http"
"net/http/cookiejar"
"net/http/httptest"
@@ -262,3 +264,30 @@ func TestOIDCLogoutRedirectsToEndSession(t *testing.T) {
t.Errorf("location missing post_logout_redirect_uri: %q", loc)
}
}
func TestLocalLoginRejectsOIDCUser(t *testing.T) {
t.Parallel()
srv, urlBase := newTestServer(t, false)
uid := "u-oidc"
sub := "sub-x"
if err := srv.deps.Store.CreateUser(t.Context(), store.User{
ID: uid, Username: "ouser", PasswordHash: "",
Role: store.RoleOperator, CreatedAt: time.Now().UTC(),
AuthSource: "oidc", OIDCSubject: &sub,
}); err != nil {
t.Fatalf("create: %v", err)
}
body, _ := json.Marshal(map[string]string{
"username": "ouser", "password": "anything",
})
res, err := stdhttp.Post(urlBase+"/api/auth/login",
"application/json", bytes.NewReader(body))
if err != nil {
t.Fatalf("post: %v", err)
}
defer res.Body.Close()
if res.StatusCode != stdhttp.StatusUnauthorized {
t.Errorf("status: got %d want 401", res.StatusCode)
}
}