app_session.go 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // Copyright 2018 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 // import "miniflux.app/middleware"
  5. import (
  6. "context"
  7. "errors"
  8. "net/http"
  9. "miniflux.app/http/cookie"
  10. "miniflux.app/http/request"
  11. "miniflux.app/http/response/html"
  12. "miniflux.app/logger"
  13. "miniflux.app/model"
  14. )
  15. // AppSession handles application session middleware.
  16. func (m *Middleware) AppSession(next http.Handler) http.Handler {
  17. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  18. var err error
  19. session := m.getAppSessionValueFromCookie(r)
  20. if session == nil {
  21. logger.Debug("[Middleware:AppSession] Session not found")
  22. session, err = m.store.CreateSession()
  23. if err != nil {
  24. html.ServerError(w, r, err)
  25. return
  26. }
  27. http.SetCookie(w, cookie.New(cookie.CookieSessionID, session.ID, m.cfg.IsHTTPS, m.cfg.BasePath()))
  28. } else {
  29. logger.Debug("[Middleware:AppSession] %s", session)
  30. }
  31. if r.Method == "POST" {
  32. formValue := r.FormValue("csrf")
  33. headerValue := r.Header.Get("X-Csrf-Token")
  34. if session.Data.CSRF != formValue && session.Data.CSRF != headerValue {
  35. logger.Error(`[Middleware:AppSession] Invalid or missing CSRF token: Form="%s", Header="%s"`, formValue, headerValue)
  36. html.BadRequest(w, r, errors.New("Invalid or missing CSRF"))
  37. return
  38. }
  39. }
  40. ctx := r.Context()
  41. ctx = context.WithValue(ctx, request.SessionIDContextKey, session.ID)
  42. ctx = context.WithValue(ctx, request.CSRFContextKey, session.Data.CSRF)
  43. ctx = context.WithValue(ctx, request.OAuth2StateContextKey, session.Data.OAuth2State)
  44. ctx = context.WithValue(ctx, request.FlashMessageContextKey, session.Data.FlashMessage)
  45. ctx = context.WithValue(ctx, request.FlashErrorMessageContextKey, session.Data.FlashErrorMessage)
  46. ctx = context.WithValue(ctx, request.UserLanguageContextKey, session.Data.Language)
  47. ctx = context.WithValue(ctx, request.UserThemeContextKey, session.Data.Theme)
  48. ctx = context.WithValue(ctx, request.PocketRequestTokenContextKey, session.Data.PocketRequestToken)
  49. next.ServeHTTP(w, r.WithContext(ctx))
  50. })
  51. }
  52. func (m *Middleware) getAppSessionValueFromCookie(r *http.Request) *model.Session {
  53. cookieValue := request.CookieValue(r, cookie.CookieSessionID)
  54. if cookieValue == "" {
  55. return nil
  56. }
  57. session, err := m.store.Session(cookieValue)
  58. if err != nil {
  59. logger.Error("[Middleware:AppSession] %v", err)
  60. return nil
  61. }
  62. return session
  63. }