package auth import ( "crypto/subtle" "net/http" ) // CSRFFieldName ist der Name des versteckten Formularfelds in den Templates. const CSRFFieldName = "csrf_token" // CSRFHeaderName erlaubt es, das Token bei einem fetch()-Aufruf im Header statt // im Formular zu schicken. const CSRFHeaderName = "X-CSRF-Token" // CSRFToken berechnet das Token zu einer Sitzung. // // # Wogegen schützt das? // // CSRF ("Cross-Site Request Forgery") nutzt aus, dass der Browser Cookies // automatisch mitschickt. Eine fremde Seite kann ein Formular auf unseren Server // abschicken lassen, und für den Server sieht es aus wie eine Aktion des // angemeldeten Nutzers: // //
// // // Das Token unterbindet das: Die fremde Seite kennt es nicht und kann es wegen // der Same-Origin-Policy des Browsers auch nicht auslesen. // // Das Präfix "csrf:" sorgt für Domänentrennung — dasselbe Geheimnis signiert auch // Session-Cookies, und eine Signatur aus dem einen Zusammenhang darf im anderen // nicht gelten. func (s *Signer) CSRFToken(subject string) string { return s.sign("csrf:" + subject) } // ValidCSRFToken prüft ein übermitteltes Token gegen die Sitzung. func (s *Signer) ValidCSRFToken(token, subject string) bool { expected := s.CSRFToken(subject) return subtle.ConstantTimeCompare([]byte(token), []byte(expected)) == 1 } // CSRFTokenFromRequest holt das Token aus dem Formular oder dem Header. func CSRFTokenFromRequest(r *http.Request) string { if token := r.Header.Get(CSRFHeaderName); token != "" { return token } return r.FormValue(CSRFFieldName) }