package handler
import (
"html/template"
"log"
"net/http"
)
const loginPageHTML = `
Login with Nostr
🗝
Login with Nostr
Sign in using your Nostr identity
No Nostr extension detected. Please install one of these:
`
func (h *Handler) Authorize(w http.ResponseWriter, r *http.Request) {
// Extract OAuth2 parameters
clientID := r.URL.Query().Get("client_id")
redirectURI := r.URL.Query().Get("redirect_uri")
state := r.URL.Query().Get("state")
responseType := r.URL.Query().Get("response_type")
// Validate required parameters
if clientID == "" {
http.Error(w, "missing client_id", http.StatusBadRequest)
return
}
if redirectURI == "" {
http.Error(w, "missing redirect_uri", http.StatusBadRequest)
return
}
if responseType != "code" {
http.Error(w, "unsupported response_type, must be 'code'", http.StatusBadRequest)
return
}
// Validate client and redirect URI
if !h.cfg.ValidateRedirectURI(clientID, redirectURI) {
http.Error(w, "invalid client_id or redirect_uri", http.StatusBadRequest)
return
}
// Create challenge
challenge, err := h.store.CreateChallenge(clientID, state, redirectURI, h.cfg.Nostr.ChallengeTTL)
if err != nil {
log.Printf("failed to create challenge: %v", err)
http.Error(w, "internal error", http.StatusInternalServerError)
return
}
// Render login page
tmpl, err := template.New("login").Parse(loginPageHTML)
if err != nil {
log.Printf("failed to parse template: %v", err)
http.Error(w, "internal error", http.StatusInternalServerError)
return
}
data := struct {
Challenge string
VerifyURL string
}{
Challenge: challenge.Nonce,
VerifyURL: h.cfg.Server.BaseURL + "/verify",
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
if err := tmpl.Execute(w, data); err != nil {
log.Printf("failed to execute template: %v", err)
}
}