66 lines
1.9 KiB
Go
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()})
|
|
}
|