token.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // Copyright 2017 Frédéric Guillot. All rights reserved.
  2. // Use of this source code is governed by the Apache 2.0
  3. // license that can be found in the LICENSE file.
  4. package middleware
  5. import (
  6. "context"
  7. "log"
  8. "net/http"
  9. "github.com/miniflux/miniflux2/model"
  10. "github.com/miniflux/miniflux2/storage"
  11. )
  12. // TokenMiddleware represents a token middleware.
  13. type TokenMiddleware struct {
  14. store *storage.Storage
  15. }
  16. // Handler execute the middleware.
  17. func (t *TokenMiddleware) Handler(next http.Handler) http.Handler {
  18. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  19. var err error
  20. token := t.getTokenValueFromCookie(r)
  21. if token == nil {
  22. log.Println("[Middleware:Token] Token not found")
  23. token, err = t.store.CreateToken()
  24. if err != nil {
  25. log.Println(err)
  26. http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
  27. return
  28. }
  29. cookie := &http.Cookie{
  30. Name: "tokenID",
  31. Value: token.ID,
  32. Path: "/",
  33. Secure: r.URL.Scheme == "https",
  34. HttpOnly: true,
  35. }
  36. http.SetCookie(w, cookie)
  37. } else {
  38. log.Println("[Middleware:Token]", token)
  39. }
  40. isTokenValid := token.Value == r.FormValue("csrf") || token.Value == r.Header.Get("X-Csrf-Token")
  41. if r.Method == "POST" && !isTokenValid {
  42. log.Println("[Middleware:CSRF] Invalid or missing CSRF token!")
  43. w.WriteHeader(http.StatusBadRequest)
  44. w.Write([]byte("Invalid or missing CSRF token!"))
  45. } else {
  46. ctx := r.Context()
  47. ctx = context.WithValue(ctx, TokenContextKey, token.Value)
  48. next.ServeHTTP(w, r.WithContext(ctx))
  49. }
  50. })
  51. }
  52. func (t *TokenMiddleware) getTokenValueFromCookie(r *http.Request) *model.Token {
  53. tokenCookie, err := r.Cookie("tokenID")
  54. if err == http.ErrNoCookie {
  55. return nil
  56. }
  57. token, err := t.store.Token(tokenCookie.Value)
  58. if err != nil {
  59. log.Println(err)
  60. return nil
  61. }
  62. return token
  63. }
  64. // NewTokenMiddleware returns a new TokenMiddleware.
  65. func NewTokenMiddleware(s *storage.Storage) *TokenMiddleware {
  66. return &TokenMiddleware{store: s}
  67. }