auth_proxy_middleware.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package ui // import "miniflux.app/v2/internal/ui"
  4. import (
  5. "log/slog"
  6. "net/http"
  7. "miniflux.app/v2/internal/config"
  8. "miniflux.app/v2/internal/http/request"
  9. "miniflux.app/v2/internal/http/response"
  10. "miniflux.app/v2/internal/model"
  11. "miniflux.app/v2/internal/storage"
  12. )
  13. type authProxyMiddleware struct {
  14. basePath string
  15. store *storage.Storage
  16. }
  17. func newAuthProxyMiddleware(basePath string, store *storage.Storage) *authProxyMiddleware {
  18. return &authProxyMiddleware{basePath: basePath, store: store}
  19. }
  20. func (m *authProxyMiddleware) handle(next http.Handler) http.Handler {
  21. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  22. if request.IsAuthenticated(r) || config.Opts.AuthProxyHeader() == "" {
  23. next.ServeHTTP(w, r)
  24. return
  25. }
  26. remoteIP := request.FindRemoteIP(r)
  27. trustedNetworks := config.Opts.TrustedReverseProxyNetworks()
  28. if !request.IsTrustedIP(remoteIP, trustedNetworks) {
  29. slog.Warn("[AuthProxy] Rejecting authentication request from untrusted proxy",
  30. slog.String("remote_ip", remoteIP),
  31. slog.String("client_ip", request.ClientIP(r)),
  32. slog.String("user_agent", r.UserAgent()),
  33. slog.Any("trusted_networks", trustedNetworks),
  34. )
  35. next.ServeHTTP(w, r)
  36. return
  37. }
  38. username := r.Header.Get(config.Opts.AuthProxyHeader())
  39. if username == "" {
  40. next.ServeHTTP(w, r)
  41. return
  42. }
  43. clientIP := request.ClientIP(r)
  44. slog.Debug("[AuthProxy] Received authenticated requested",
  45. slog.String("client_ip", clientIP),
  46. slog.String("remote_ip", remoteIP),
  47. slog.String("user_agent", r.UserAgent()),
  48. slog.String("username", username),
  49. )
  50. user, err := m.store.UserByUsername(username)
  51. if err != nil {
  52. response.HTMLServerError(w, r, err)
  53. return
  54. }
  55. if user == nil {
  56. if !config.Opts.IsAuthProxyUserCreationAllowed() {
  57. slog.Debug("[AuthProxy] User doesn't exist and user creation is not allowed",
  58. slog.Bool("authentication_failed", true),
  59. slog.String("client_ip", clientIP),
  60. slog.String("remote_ip", remoteIP),
  61. slog.String("user_agent", r.UserAgent()),
  62. slog.String("username", username),
  63. )
  64. response.HTMLForbidden(w, r)
  65. return
  66. }
  67. if user, err = m.store.CreateUser(&model.UserCreationRequest{Username: username}); err != nil {
  68. response.HTMLServerError(w, r, err)
  69. return
  70. }
  71. }
  72. slog.Info("[AuthProxy] User authenticated successfully",
  73. slog.Bool("authentication_successful", true),
  74. slog.String("client_ip", clientIP),
  75. slog.String("remote_ip", remoteIP),
  76. slog.String("user_agent", r.UserAgent()),
  77. slog.Int64("user_id", user.ID),
  78. slog.String("username", user.Username),
  79. )
  80. m.store.SetLastLogin(user.ID)
  81. if err := authenticateWebSession(w, r, m.store, user); err != nil {
  82. response.HTMLServerError(w, r, err)
  83. return
  84. }
  85. response.HTMLRedirect(w, r, m.basePath+"/"+user.DefaultHomePage)
  86. })
  87. }