Files

66 lines
1.9 KiB
Go

package handlers
import (
"net/http"
"amnezia-share/internal/auth"
"amnezia-share/internal/web"
)
func registerOIDC(a *web.App, mux *http.ServeMux) {
mux.HandleFunc("GET /oidc/callback", OIDCCallback(a))
}
// OIDCCallback completes the Pocket ID authorization-code + PKCE flow, matching
// or auto-provisioning the local admin account (oidc_callback.php).
func OIDCCallback(a *web.App) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
q := r.URL.Query()
if errParam := q.Get("error"); errParam != "" {
renderOIDCError(a, w, r, "Pocket ID вернул ошибку: "+errParam)
return
}
state := q.Get("state")
code := q.Get("code")
wantState := a.Sessions.GetString(ctx, "oidc_state")
verifier := a.Sessions.GetString(ctx, "oidc_verifier")
a.Sessions.Remove(ctx, "oidc_state")
a.Sessions.Remove(ctx, "oidc_verifier")
if code == "" || wantState == "" || state != wantState {
renderOIDCError(a, w, r, "Недействительный ответ от Pocket ID. Попробуйте войти ещё раз.")
return
}
cfg := oidcConfigFromSettings(a, r)
if !cfg.Configured() {
renderOIDCError(a, w, r, "Вход через Pocket ID не настроен.")
return
}
redirectURI := a.AbsoluteURL(r, "oidc/callback")
info, err := auth.ExchangeAndUserinfo(ctx, cfg, code, redirectURI, verifier)
if err != nil {
renderOIDCError(a, w, r, err.Error())
return
}
admin, err := a.Auth.FindOrCreateAdminFromOIDC(ctx, info)
if err != nil {
renderOIDCError(a, w, r, err.Error())
return
}
_ = a.Sessions.RenewToken(ctx)
a.Sessions.Put(ctx, web.SessionAdminID, admin.ID)
redirectTo(w, r, a, "admin")
}
}
func renderOIDCError(a *web.App, w http.ResponseWriter, r *http.Request, msg string) {
a.Render(w, r, "page_login", loginView{Error: msg, PocketEnabled: oidcConfigFromSettings(a, r).Configured()})
}