Make secure cookie configurable
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -34,6 +34,7 @@ probod:
|
|||||||
domain: "localhost"
|
domain: "localhost"
|
||||||
secret: "this-is-a-secure-secret-for-cookie-signing-at-least-32-bytes"
|
secret: "this-is-a-secure-secret-for-cookie-signing-at-least-32-bytes"
|
||||||
duration: 24
|
duration: 24
|
||||||
|
secure: true
|
||||||
password:
|
password:
|
||||||
pepper: "this-is-a-secure-pepper-for-password-hashing-at-least-32-bytes"
|
pepper: "this-is-a-secure-pepper-for-password-hashing-at-least-32-bytes"
|
||||||
iterations: 1000000
|
iterations: 1000000
|
||||||
|
|||||||
@@ -363,6 +363,12 @@ Secret key used for signing session cookies. Should be at least 32 bytes for sec
|
|||||||
|
|
||||||
Session cookie lifetime in hours.
|
Session cookie lifetime in hours.
|
||||||
|
|
||||||
|
#### `auth.cookie.secure` (boolean)
|
||||||
|
|
||||||
|
**Default**: `true`
|
||||||
|
|
||||||
|
Controls whether the Secure flag is set on session cookies. When true, cookies are only sent over HTTPS connections.
|
||||||
|
|
||||||
#### `auth.password.pepper` (string)
|
#### `auth.password.pepper` (string)
|
||||||
|
|
||||||
**Default**: Auto-generated
|
**Default**: Auto-generated
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ This document provides a comprehensive reference for all environment variables u
|
|||||||
| `AUTH_COOKIE_DOMAIN` | Domain for the session cookie | `localhost` | No |
|
| `AUTH_COOKIE_DOMAIN` | Domain for the session cookie | `localhost` | No |
|
||||||
| `AUTH_COOKIE_SECRET` | Secret key for signing session cookies (32+ bytes) | - | **Yes** |
|
| `AUTH_COOKIE_SECRET` | Secret key for signing session cookies (32+ bytes) | - | **Yes** |
|
||||||
| `AUTH_COOKIE_DURATION` | Session cookie validity duration in hours | `24` | No |
|
| `AUTH_COOKIE_DURATION` | Session cookie validity duration in hours | `24` | No |
|
||||||
|
| `AUTH_COOKIE_SECURE` | Set Secure flag on cookies (use false for HTTP) | `true` | No |
|
||||||
|
|
||||||
### Password Security
|
### Password Security
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ type (
|
|||||||
Secret string `json:"secret"`
|
Secret string `json:"secret"`
|
||||||
Duration int `json:"duration"`
|
Duration int `json:"duration"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
Secure bool `json:"secure"`
|
||||||
}
|
}
|
||||||
|
|
||||||
passwordConfig struct {
|
passwordConfig struct {
|
||||||
|
|||||||
@@ -27,6 +27,14 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"go.gearno.de/kit/httpclient"
|
||||||
|
"go.gearno.de/kit/httpserver"
|
||||||
|
"go.gearno.de/kit/log"
|
||||||
|
"go.gearno.de/kit/migrator"
|
||||||
|
"go.gearno.de/kit/pg"
|
||||||
|
"go.gearno.de/kit/unit"
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
"go.probo.inc/probo/pkg/agents"
|
"go.probo.inc/probo/pkg/agents"
|
||||||
"go.probo.inc/probo/pkg/auth"
|
"go.probo.inc/probo/pkg/auth"
|
||||||
"go.probo.inc/probo/pkg/authz"
|
"go.probo.inc/probo/pkg/authz"
|
||||||
@@ -48,14 +56,6 @@ import (
|
|||||||
"go.probo.inc/probo/pkg/server/api"
|
"go.probo.inc/probo/pkg/server/api"
|
||||||
"go.probo.inc/probo/pkg/slack"
|
"go.probo.inc/probo/pkg/slack"
|
||||||
"go.probo.inc/probo/pkg/trust"
|
"go.probo.inc/probo/pkg/trust"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
|
||||||
"go.gearno.de/kit/httpclient"
|
|
||||||
"go.gearno.de/kit/httpserver"
|
|
||||||
"go.gearno.de/kit/log"
|
|
||||||
"go.gearno.de/kit/migrator"
|
|
||||||
"go.gearno.de/kit/pg"
|
|
||||||
"go.gearno.de/kit/unit"
|
|
||||||
"go.opentelemetry.io/otel/trace"
|
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -116,6 +116,7 @@ func New() *Implm {
|
|||||||
Secret: "this-is-a-secure-secret-for-cookie-signing-at-least-32-bytes",
|
Secret: "this-is-a-secure-secret-for-cookie-signing-at-least-32-bytes",
|
||||||
Duration: 24,
|
Duration: 24,
|
||||||
Domain: "localhost",
|
Domain: "localhost",
|
||||||
|
Secure: true,
|
||||||
},
|
},
|
||||||
DisableSignup: false,
|
DisableSignup: false,
|
||||||
InvitationConfirmationTokenValidity: 3600,
|
InvitationConfirmationTokenValidity: 3600,
|
||||||
@@ -402,6 +403,7 @@ func (impl *Implm) Run(
|
|||||||
CookieDomain: impl.cfg.Auth.Cookie.Domain,
|
CookieDomain: impl.cfg.Auth.Cookie.Domain,
|
||||||
SessionDuration: time.Duration(impl.cfg.Auth.Cookie.Duration) * time.Hour,
|
SessionDuration: time.Duration(impl.cfg.Auth.Cookie.Duration) * time.Hour,
|
||||||
CookieSecret: impl.cfg.Auth.Cookie.Secret,
|
CookieSecret: impl.cfg.Auth.Cookie.Secret,
|
||||||
|
CookieSecure: impl.cfg.Auth.Cookie.Secure,
|
||||||
},
|
},
|
||||||
TrustAuth: api.TrustAuthConfig{
|
TrustAuth: api.TrustAuthConfig{
|
||||||
CookieName: impl.cfg.TrustAuth.CookieName,
|
CookieName: impl.cfg.TrustAuth.CookieName,
|
||||||
@@ -412,6 +414,7 @@ func (impl *Implm) Run(
|
|||||||
TokenSecret: impl.cfg.TrustAuth.TokenSecret,
|
TokenSecret: impl.cfg.TrustAuth.TokenSecret,
|
||||||
Scope: impl.cfg.TrustAuth.Scope,
|
Scope: impl.cfg.TrustAuth.Scope,
|
||||||
TokenType: impl.cfg.TrustAuth.TokenType,
|
TokenType: impl.cfg.TrustAuth.TokenType,
|
||||||
|
CookieSecure: impl.cfg.Auth.Cookie.Secure,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -59,13 +59,13 @@ type Config struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DefaultConfig returns a default secure cookie configuration
|
// DefaultConfig returns a default secure cookie configuration
|
||||||
func DefaultConfig(name, secret string) Config {
|
func DefaultConfig(name, secret string, secure bool) Config {
|
||||||
return Config{
|
return Config{
|
||||||
Name: name,
|
Name: name,
|
||||||
Secret: secret,
|
Secret: secret,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
MaxAge: 86400 * 30, // 30 days
|
MaxAge: 86400 * 30, // 30 days
|
||||||
Secure: true,
|
Secure: secure,
|
||||||
HTTPOnly: true,
|
HTTPOnly: true,
|
||||||
SameSite: http.SameSiteNoneMode, // None mode required for SAML (cross-site POST from IdP)
|
SameSite: http.SameSiteNoneMode, // None mode required for SAML (cross-site POST from IdP)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ import (
|
|||||||
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/go-chi/cors"
|
||||||
|
"go.gearno.de/kit/httpserver"
|
||||||
|
"go.gearno.de/kit/log"
|
||||||
"go.probo.inc/probo/pkg/auth"
|
"go.probo.inc/probo/pkg/auth"
|
||||||
"go.probo.inc/probo/pkg/authz"
|
"go.probo.inc/probo/pkg/authz"
|
||||||
"go.probo.inc/probo/pkg/connector"
|
"go.probo.inc/probo/pkg/connector"
|
||||||
@@ -28,10 +32,6 @@ import (
|
|||||||
console_v1 "go.probo.inc/probo/pkg/server/api/console/v1"
|
console_v1 "go.probo.inc/probo/pkg/server/api/console/v1"
|
||||||
trust_v1 "go.probo.inc/probo/pkg/server/api/trust/v1"
|
trust_v1 "go.probo.inc/probo/pkg/server/api/trust/v1"
|
||||||
"go.probo.inc/probo/pkg/trust"
|
"go.probo.inc/probo/pkg/trust"
|
||||||
"github.com/go-chi/chi/v5"
|
|
||||||
"github.com/go-chi/cors"
|
|
||||||
"go.gearno.de/kit/httpserver"
|
|
||||||
"go.gearno.de/kit/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -40,6 +40,7 @@ type (
|
|||||||
CookieDomain string
|
CookieDomain string
|
||||||
SessionDuration time.Duration
|
SessionDuration time.Duration
|
||||||
CookieSecret string
|
CookieSecret string
|
||||||
|
CookieSecure bool
|
||||||
}
|
}
|
||||||
|
|
||||||
TrustAuthConfig struct {
|
TrustAuthConfig struct {
|
||||||
@@ -51,6 +52,7 @@ type (
|
|||||||
TokenSecret string
|
TokenSecret string
|
||||||
Scope string
|
Scope string
|
||||||
TokenType string
|
TokenType string
|
||||||
|
CookieSecure bool
|
||||||
}
|
}
|
||||||
|
|
||||||
Config struct {
|
Config struct {
|
||||||
@@ -128,6 +130,7 @@ func NewServer(cfg Config) (*Server, error) {
|
|||||||
CookieDomain: cfg.ConsoleAuth.CookieDomain,
|
CookieDomain: cfg.ConsoleAuth.CookieDomain,
|
||||||
SessionDuration: cfg.ConsoleAuth.SessionDuration,
|
SessionDuration: cfg.ConsoleAuth.SessionDuration,
|
||||||
CookieSecret: cfg.ConsoleAuth.CookieSecret,
|
CookieSecret: cfg.ConsoleAuth.CookieSecret,
|
||||||
|
CookieSecure: cfg.ConsoleAuth.CookieSecure,
|
||||||
},
|
},
|
||||||
trust_v1.TrustAuthConfig{
|
trust_v1.TrustAuthConfig{
|
||||||
CookieName: cfg.TrustAuth.CookieName,
|
CookieName: cfg.TrustAuth.CookieName,
|
||||||
@@ -138,6 +141,7 @@ func NewServer(cfg Config) (*Server, error) {
|
|||||||
TokenSecret: cfg.TrustAuth.TokenSecret,
|
TokenSecret: cfg.TrustAuth.TokenSecret,
|
||||||
Scope: cfg.TrustAuth.Scope,
|
Scope: cfg.TrustAuth.Scope,
|
||||||
TokenType: cfg.TrustAuth.TokenType,
|
TokenType: cfg.TrustAuth.TokenType,
|
||||||
|
CookieSecure: cfg.TrustAuth.CookieSecure,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -191,6 +195,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
CookieDomain: s.cfg.ConsoleAuth.CookieDomain,
|
CookieDomain: s.cfg.ConsoleAuth.CookieDomain,
|
||||||
SessionDuration: s.cfg.ConsoleAuth.SessionDuration,
|
SessionDuration: s.cfg.ConsoleAuth.SessionDuration,
|
||||||
CookieSecret: s.cfg.ConsoleAuth.CookieSecret,
|
CookieSecret: s.cfg.ConsoleAuth.CookieSecret,
|
||||||
|
CookieSecure: s.cfg.ConsoleAuth.CookieSecure,
|
||||||
},
|
},
|
||||||
s.cfg.ConnectorRegistry,
|
s.cfg.ConnectorRegistry,
|
||||||
s.cfg.SafeRedirect,
|
s.cfg.SafeRedirect,
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ type (
|
|||||||
CookieDomain string
|
CookieDomain string
|
||||||
SessionDuration time.Duration
|
SessionDuration time.Duration
|
||||||
CookieSecret string
|
CookieSecret string
|
||||||
|
CookieSecure bool
|
||||||
}
|
}
|
||||||
|
|
||||||
Resolver struct {
|
Resolver struct {
|
||||||
@@ -371,6 +372,7 @@ func WithSession(authSvc *auth.Service, authzSvc *authz.Service, authCfg AuthCon
|
|||||||
sessionAuthCfg := session.AuthConfig{
|
sessionAuthCfg := session.AuthConfig{
|
||||||
CookieName: authCfg.CookieName,
|
CookieName: authCfg.CookieName,
|
||||||
CookieSecret: authCfg.CookieSecret,
|
CookieSecret: authCfg.CookieSecret,
|
||||||
|
CookieSecure: authCfg.CookieSecure,
|
||||||
}
|
}
|
||||||
|
|
||||||
errorHandler := session.ErrorHandler{
|
errorHandler := session.ErrorHandler{
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ type (
|
|||||||
TokenSecret string
|
TokenSecret string
|
||||||
Scope string
|
Scope string
|
||||||
TokenType string
|
TokenType string
|
||||||
|
CookieSecure bool
|
||||||
}
|
}
|
||||||
|
|
||||||
Resolver struct {
|
Resolver struct {
|
||||||
@@ -186,6 +187,7 @@ func trySessionAuth(ctx context.Context, w http.ResponseWriter, r *http.Request,
|
|||||||
sessionAuthCfg := session.AuthConfig{
|
sessionAuthCfg := session.AuthConfig{
|
||||||
CookieName: authCfg.CookieName,
|
CookieName: authCfg.CookieName,
|
||||||
CookieSecret: authCfg.CookieSecret,
|
CookieSecret: authCfg.CookieSecret,
|
||||||
|
CookieSecure: authCfg.CookieSecure,
|
||||||
}
|
}
|
||||||
|
|
||||||
errorHandler := session.ErrorHandler{
|
errorHandler := session.ErrorHandler{
|
||||||
@@ -256,7 +258,7 @@ func clearTokenCookie(w http.ResponseWriter, trustAuthCfg TrustAuthConfig) {
|
|||||||
Domain: trustAuthCfg.CookieDomain,
|
Domain: trustAuthCfg.CookieDomain,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
MaxAge: -1,
|
MaxAge: -1,
|
||||||
Secure: true,
|
Secure: trustAuthCfg.CookieSecure,
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
SameSite: http.SameSiteStrictMode,
|
SameSite: http.SameSiteStrictMode,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ func authTokenHandler(trustSvc *trust.Service, trustAuthCfg TrustAuthConfig) htt
|
|||||||
Domain: cookieDomain,
|
Domain: cookieDomain,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
MaxAge: int(trustAuthCfg.CookieDuration / time.Second),
|
MaxAge: int(trustAuthCfg.CookieDuration / time.Second),
|
||||||
Secure: true,
|
Secure: trustAuthCfg.CookieSecure,
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
SameSite: http.SameSiteStrictMode,
|
SameSite: http.SameSiteStrictMode,
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,7 @@ func trustCenterLogoutHandler(authCfg console_v1.AuthConfig, trustAuthCfg TrustA
|
|||||||
Domain: cookieDomain,
|
Domain: cookieDomain,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
MaxAge: -1,
|
MaxAge: -1,
|
||||||
Secure: true,
|
Secure: trustAuthCfg.CookieSecure,
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
SameSite: http.SameSiteStrictMode,
|
SameSite: http.SameSiteStrictMode,
|
||||||
})
|
})
|
||||||
@@ -167,6 +167,7 @@ func trustCenterLogoutHandler(authCfg console_v1.AuthConfig, trustAuthCfg TrustA
|
|||||||
session.ClearCookie(w, session.AuthConfig{
|
session.ClearCookie(w, session.AuthConfig{
|
||||||
CookieName: authCfg.CookieName,
|
CookieName: authCfg.CookieName,
|
||||||
CookieSecret: authCfg.CookieSecret,
|
CookieSecret: authCfg.CookieSecret,
|
||||||
|
CookieSecure: authCfg.CookieSecure,
|
||||||
})
|
})
|
||||||
|
|
||||||
httpserver.RenderJSON(w, http.StatusOK, map[string]string{
|
httpserver.RenderJSON(w, http.StatusOK, map[string]string{
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"go.gearno.de/kit/httpserver"
|
||||||
authsvc "go.probo.inc/probo/pkg/auth"
|
authsvc "go.probo.inc/probo/pkg/auth"
|
||||||
"go.probo.inc/probo/pkg/authz"
|
"go.probo.inc/probo/pkg/authz"
|
||||||
"go.probo.inc/probo/pkg/gid"
|
"go.probo.inc/probo/pkg/gid"
|
||||||
"go.probo.inc/probo/pkg/server/session"
|
"go.probo.inc/probo/pkg/server/session"
|
||||||
"go.gearno.de/kit/httpserver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -36,13 +36,14 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func AcceptInvitationHandler(authSvc *authsvc.Service, authzSvc *authz.Service, cookieName string, cookieSecret string) http.HandlerFunc {
|
func AcceptInvitationHandler(authSvc *authsvc.Service, authzSvc *authz.Service, cookieName string, cookieSecret string, cookieSecure bool) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
|
|
||||||
sessionAuthCfg := session.AuthConfig{
|
sessionAuthCfg := session.AuthConfig{
|
||||||
CookieName: cookieName,
|
CookieName: cookieName,
|
||||||
CookieSecret: cookieSecret,
|
CookieSecret: cookieSecret,
|
||||||
|
CookieSecure: cookieSecure,
|
||||||
}
|
}
|
||||||
|
|
||||||
errorHandler := session.ErrorHandler{
|
errorHandler := session.ErrorHandler{
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ type Config struct {
|
|||||||
CookieDomain string
|
CookieDomain string
|
||||||
SessionDuration time.Duration
|
SessionDuration time.Duration
|
||||||
CookieSecret string
|
CookieSecret string
|
||||||
|
CookieSecure bool
|
||||||
FileManager *filemanager.Service
|
FileManager *filemanager.Service
|
||||||
Logger *log.Logger
|
Logger *log.Logger
|
||||||
}
|
}
|
||||||
@@ -44,26 +45,26 @@ type Server struct {
|
|||||||
func NewServer(cfg Config) (*Server, error) {
|
func NewServer(cfg Config) (*Server, error) {
|
||||||
router := chi.NewRouter()
|
router := chi.NewRouter()
|
||||||
|
|
||||||
router.Post("/register", SignUpHandler(cfg.Auth, cfg.CookieName, cfg.CookieSecret))
|
router.Post("/register", SignUpHandler(cfg.Auth, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure))
|
||||||
router.Post("/login", SignInHandler(cfg.Auth, cfg.CookieName, cfg.CookieSecret))
|
router.Post("/login", SignInHandler(cfg.Auth, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure))
|
||||||
router.Delete("/logout", SignOutHandler(cfg.Auth, cfg.CookieName, cfg.CookieSecret))
|
router.Delete("/logout", SignOutHandler(cfg.Auth, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure))
|
||||||
router.Post("/signup-from-invitation", SignupFromInvitationHandler(cfg.Auth, cfg.CookieName, cfg.CookieSecret))
|
router.Post("/signup-from-invitation", SignupFromInvitationHandler(cfg.Auth, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure))
|
||||||
router.Post("/forget-password", ForgetPasswordHandler(cfg.Auth))
|
router.Post("/forget-password", ForgetPasswordHandler(cfg.Auth))
|
||||||
router.Post("/reset-password", ResetPasswordHandler(cfg.Auth))
|
router.Post("/reset-password", ResetPasswordHandler(cfg.Auth))
|
||||||
router.Post("/check-sso", SAMLCheckSSOHandler(cfg.Auth, cfg.Logger))
|
router.Post("/check-sso", SAMLCheckSSOHandler(cfg.Auth, cfg.Logger))
|
||||||
router.Get("/organizations", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, ListOrganizationsHandler(cfg.Auth, cfg.Authz)))
|
router.Get("/organizations", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure, ListOrganizationsHandler(cfg.Auth, cfg.Authz)))
|
||||||
router.Get("/organizations/{organizationID}/logo", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, OrganizationLogoHandler(cfg.Auth, cfg.FileManager)))
|
router.Get("/organizations/{organizationID}/logo", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure, OrganizationLogoHandler(cfg.Auth, cfg.FileManager)))
|
||||||
router.Get("/invitations", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, ListInvitationsHandler(cfg.Authz)))
|
router.Get("/invitations", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure, ListInvitationsHandler(cfg.Authz)))
|
||||||
router.Post("/invitations/accept", AcceptInvitationHandler(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret))
|
router.Post("/invitations/accept", AcceptInvitationHandler(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure))
|
||||||
|
|
||||||
router.Get("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, ListUserAPIKeysHandler(cfg.Auth, cfg.Authz)))
|
router.Get("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure, ListUserAPIKeysHandler(cfg.Auth, cfg.Authz)))
|
||||||
router.Post("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, CreateUserAPIKeyHandler(cfg.Auth)))
|
router.Post("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure, CreateUserAPIKeyHandler(cfg.Auth)))
|
||||||
router.Get("/api-keys/{id}", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, GetUserAPIKeyHandler(cfg.Auth)))
|
router.Get("/api-keys/{id}", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure, GetUserAPIKeyHandler(cfg.Auth)))
|
||||||
router.Put("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, UpdateUserAPIKeyHandler(cfg.Auth)))
|
router.Put("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure, UpdateUserAPIKeyHandler(cfg.Auth)))
|
||||||
router.Delete("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, DeleteUserAPIKeyHandler(cfg.Auth)))
|
router.Delete("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure, DeleteUserAPIKeyHandler(cfg.Auth)))
|
||||||
|
|
||||||
router.Get("/saml/login/{samlConfigID}", SAMLLoginHandler(cfg.SAML, cfg.Auth, cfg.Logger))
|
router.Get("/saml/login/{samlConfigID}", SAMLLoginHandler(cfg.SAML, cfg.Auth, cfg.Logger))
|
||||||
router.Post("/saml/consume", SAMLACSHandler(cfg.SAML, cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.SessionDuration, cfg.Logger))
|
router.Post("/saml/consume", SAMLACSHandler(cfg.SAML, cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.CookieSecure, cfg.SessionDuration, cfg.Logger))
|
||||||
router.Get("/saml/metadata", SAMLMetadataHandler(cfg.SAML))
|
router.Get("/saml/metadata", SAMLMetadataHandler(cfg.SAML))
|
||||||
|
|
||||||
return &Server{
|
return &Server{
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"go.gearno.de/kit/httpserver"
|
||||||
authsvc "go.probo.inc/probo/pkg/auth"
|
authsvc "go.probo.inc/probo/pkg/auth"
|
||||||
"go.probo.inc/probo/pkg/authz"
|
"go.probo.inc/probo/pkg/authz"
|
||||||
"go.probo.inc/probo/pkg/coredata"
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
"go.probo.inc/probo/pkg/server/session"
|
"go.probo.inc/probo/pkg/server/session"
|
||||||
"go.gearno.de/kit/httpserver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ctxKey struct{ name string }
|
type ctxKey struct{ name string }
|
||||||
@@ -38,6 +38,7 @@ func RequireAuth(
|
|||||||
authzSvc *authz.Service,
|
authzSvc *authz.Service,
|
||||||
cookieName string,
|
cookieName string,
|
||||||
cookieSecret string,
|
cookieSecret string,
|
||||||
|
cookieSecure bool,
|
||||||
next http.HandlerFunc,
|
next http.HandlerFunc,
|
||||||
) http.HandlerFunc {
|
) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -46,6 +47,7 @@ func RequireAuth(
|
|||||||
sessionAuthCfg := session.AuthConfig{
|
sessionAuthCfg := session.AuthConfig{
|
||||||
CookieName: cookieName,
|
CookieName: cookieName,
|
||||||
CookieSecret: cookieSecret,
|
CookieSecret: cookieSecret,
|
||||||
|
CookieSecure: cookieSecure,
|
||||||
}
|
}
|
||||||
|
|
||||||
errorHandler := session.ErrorHandler{
|
errorHandler := session.ErrorHandler{
|
||||||
|
|||||||
@@ -20,20 +20,21 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"go.gearno.de/kit/log"
|
||||||
authsvc "go.probo.inc/probo/pkg/auth"
|
authsvc "go.probo.inc/probo/pkg/auth"
|
||||||
"go.probo.inc/probo/pkg/authz"
|
"go.probo.inc/probo/pkg/authz"
|
||||||
"go.probo.inc/probo/pkg/coredata"
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
"go.probo.inc/probo/pkg/gid"
|
"go.probo.inc/probo/pkg/gid"
|
||||||
"go.probo.inc/probo/pkg/securecookie"
|
"go.probo.inc/probo/pkg/securecookie"
|
||||||
"go.gearno.de/kit/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func getSessionIDFromCookie(r *http.Request, cookieName string, cookieSecret string) (gid.GID, error) {
|
func getSessionIDFromCookie(r *http.Request, cookieName string, cookieSecret string, cookieSecure bool) (gid.GID, error) {
|
||||||
cookieValue, err := securecookie.Get(
|
cookieValue, err := securecookie.Get(
|
||||||
r,
|
r,
|
||||||
securecookie.DefaultConfig(
|
securecookie.DefaultConfig(
|
||||||
cookieName,
|
cookieName,
|
||||||
cookieSecret,
|
cookieSecret,
|
||||||
|
cookieSecure,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -43,7 +44,7 @@ func getSessionIDFromCookie(r *http.Request, cookieName string, cookieSecret str
|
|||||||
return gid.ParseGID(cookieValue)
|
return gid.ParseGID(cookieValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SAMLACSHandler(samlSvc *authsvc.SAMLService, authSvc *authsvc.Service, authzSvc *authz.Service, cookieName string, cookieSecret string, sessionDuration time.Duration, logger *log.Logger) http.HandlerFunc {
|
func SAMLACSHandler(samlSvc *authsvc.SAMLService, authSvc *authsvc.Service, authzSvc *authz.Service, cookieName string, cookieSecret string, cookieSecure bool, sessionDuration time.Duration, logger *log.Logger) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
|
|
||||||
@@ -73,7 +74,7 @@ func SAMLACSHandler(samlSvc *authsvc.SAMLService, authSvc *authsvc.Service, auth
|
|||||||
}
|
}
|
||||||
|
|
||||||
var existingSession *coredata.Session
|
var existingSession *coredata.Session
|
||||||
if existingSessionID, err := getSessionIDFromCookie(r, cookieName, cookieSecret); err == nil {
|
if existingSessionID, err := getSessionIDFromCookie(r, cookieName, cookieSecret, cookieSecure); err == nil {
|
||||||
if session, err := authSvc.GetSession(ctx, existingSessionID); err == nil {
|
if session, err := authSvc.GetSession(ctx, existingSessionID); err == nil {
|
||||||
existingSession = session
|
existingSession = session
|
||||||
}
|
}
|
||||||
@@ -114,6 +115,7 @@ func SAMLACSHandler(samlSvc *authsvc.SAMLService, authSvc *authsvc.Service, auth
|
|||||||
securecookie.DefaultConfig(
|
securecookie.DefaultConfig(
|
||||||
cookieName,
|
cookieName,
|
||||||
cookieSecret,
|
cookieSecret,
|
||||||
|
cookieSecure,
|
||||||
),
|
),
|
||||||
session.ID.String(),
|
session.ID.String(),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"go.gearno.de/kit/httpserver"
|
||||||
authsvc "go.probo.inc/probo/pkg/auth"
|
authsvc "go.probo.inc/probo/pkg/auth"
|
||||||
"go.probo.inc/probo/pkg/coredata"
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
"go.probo.inc/probo/pkg/gid"
|
"go.probo.inc/probo/pkg/gid"
|
||||||
"go.probo.inc/probo/pkg/securecookie"
|
"go.probo.inc/probo/pkg/securecookie"
|
||||||
"go.gearno.de/kit/httpserver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -47,7 +47,7 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func SignInHandler(authSvc *authsvc.Service, cookieName string, cookieSecret string) http.HandlerFunc {
|
func SignInHandler(authSvc *authsvc.Service, cookieName string, cookieSecret string, cookieSecure bool) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
var req SignInRequest
|
var req SignInRequest
|
||||||
@@ -57,7 +57,7 @@ func SignInHandler(authSvc *authsvc.Service, cookieName string, cookieSecret str
|
|||||||
}
|
}
|
||||||
|
|
||||||
var existingSession *coredata.Session
|
var existingSession *coredata.Session
|
||||||
if existingSessionID, err := getSessionIDFromCookie(r, cookieName, cookieSecret); err == nil {
|
if existingSessionID, err := getSessionIDFromCookie(r, cookieName, cookieSecret, cookieSecure); err == nil {
|
||||||
if session, err := authSvc.GetSession(r.Context(), existingSessionID); err == nil {
|
if session, err := authSvc.GetSession(r.Context(), existingSessionID); err == nil {
|
||||||
existingSession = session
|
existingSession = session
|
||||||
}
|
}
|
||||||
@@ -79,6 +79,7 @@ func SignInHandler(authSvc *authsvc.Service, cookieName string, cookieSecret str
|
|||||||
securecookie.DefaultConfig(
|
securecookie.DefaultConfig(
|
||||||
cookieName,
|
cookieName,
|
||||||
cookieSecret,
|
cookieSecret,
|
||||||
|
cookieSecure,
|
||||||
),
|
),
|
||||||
session.ID.String(),
|
session.ID.String(),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -18,18 +18,19 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"go.gearno.de/kit/httpserver"
|
||||||
|
authsvc "go.probo.inc/probo/pkg/auth"
|
||||||
"go.probo.inc/probo/pkg/gid"
|
"go.probo.inc/probo/pkg/gid"
|
||||||
"go.probo.inc/probo/pkg/securecookie"
|
"go.probo.inc/probo/pkg/securecookie"
|
||||||
authsvc "go.probo.inc/probo/pkg/auth"
|
|
||||||
"go.gearno.de/kit/httpserver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func SignOutHandler(authSvc *authsvc.Service, cookieName string, cookieSecret string) http.HandlerFunc {
|
func SignOutHandler(authSvc *authsvc.Service, cookieName string, cookieSecret string, cookieSecure bool) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
sessionID, err := securecookie.Get(r, securecookie.DefaultConfig(
|
sessionID, err := securecookie.Get(r, securecookie.DefaultConfig(
|
||||||
cookieName,
|
cookieName,
|
||||||
cookieSecret,
|
cookieSecret,
|
||||||
|
cookieSecure,
|
||||||
))
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpserver.RenderError(w, http.StatusBadRequest, err)
|
httpserver.RenderError(w, http.StatusBadRequest, err)
|
||||||
@@ -50,6 +51,7 @@ func SignOutHandler(authSvc *authsvc.Service, cookieName string, cookieSecret st
|
|||||||
securecookie.Clear(w, securecookie.DefaultConfig(
|
securecookie.Clear(w, securecookie.DefaultConfig(
|
||||||
cookieName,
|
cookieName,
|
||||||
cookieSecret,
|
cookieSecret,
|
||||||
|
cookieSecure,
|
||||||
))
|
))
|
||||||
|
|
||||||
w.Header().Set("Clear-Site-Data", "*")
|
w.Header().Set("Clear-Site-Data", "*")
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"go.gearno.de/kit/httpserver"
|
||||||
authsvc "go.probo.inc/probo/pkg/auth"
|
authsvc "go.probo.inc/probo/pkg/auth"
|
||||||
"go.probo.inc/probo/pkg/securecookie"
|
"go.probo.inc/probo/pkg/securecookie"
|
||||||
"go.gearno.de/kit/httpserver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -37,7 +37,7 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func SignUpHandler(authSvc *authsvc.Service, cookieName string, cookieSecret string) http.HandlerFunc {
|
func SignUpHandler(authSvc *authsvc.Service, cookieName string, cookieSecret string, cookieSecure bool) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var req SignUpRequest
|
var req SignUpRequest
|
||||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||||
@@ -72,6 +72,7 @@ func SignUpHandler(authSvc *authsvc.Service, cookieName string, cookieSecret str
|
|||||||
securecookie.DefaultConfig(
|
securecookie.DefaultConfig(
|
||||||
cookieName,
|
cookieName,
|
||||||
cookieSecret,
|
cookieSecret,
|
||||||
|
cookieSecure,
|
||||||
),
|
),
|
||||||
session.ID.String(),
|
session.ID.String(),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"go.gearno.de/kit/httpserver"
|
||||||
authsvc "go.probo.inc/probo/pkg/auth"
|
authsvc "go.probo.inc/probo/pkg/auth"
|
||||||
"go.probo.inc/probo/pkg/securecookie"
|
"go.probo.inc/probo/pkg/securecookie"
|
||||||
"go.gearno.de/kit/httpserver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -35,7 +35,7 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func SignupFromInvitationHandler(authSvc *authsvc.Service, cookieName string, cookieSecret string) http.HandlerFunc {
|
func SignupFromInvitationHandler(authSvc *authsvc.Service, cookieName string, cookieSecret string, cookieSecure bool) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var req SignupFromInvitationRequest
|
var req SignupFromInvitationRequest
|
||||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||||
@@ -54,6 +54,7 @@ func SignupFromInvitationHandler(authSvc *authsvc.Service, cookieName string, co
|
|||||||
securecookie.DefaultConfig(
|
securecookie.DefaultConfig(
|
||||||
cookieName,
|
cookieName,
|
||||||
cookieSecret,
|
cookieSecret,
|
||||||
|
cookieSecure,
|
||||||
),
|
),
|
||||||
session.ID.String(),
|
session.ID.String(),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
"go.gearno.de/kit/httpserver"
|
||||||
|
"go.gearno.de/kit/log"
|
||||||
|
"go.gearno.de/kit/pg"
|
||||||
"go.probo.inc/probo/pkg/agents"
|
"go.probo.inc/probo/pkg/agents"
|
||||||
"go.probo.inc/probo/pkg/auth"
|
"go.probo.inc/probo/pkg/auth"
|
||||||
"go.probo.inc/probo/pkg/authz"
|
"go.probo.inc/probo/pkg/authz"
|
||||||
@@ -29,15 +33,11 @@ import (
|
|||||||
"go.probo.inc/probo/pkg/probo"
|
"go.probo.inc/probo/pkg/probo"
|
||||||
"go.probo.inc/probo/pkg/saferedirect"
|
"go.probo.inc/probo/pkg/saferedirect"
|
||||||
"go.probo.inc/probo/pkg/server/api"
|
"go.probo.inc/probo/pkg/server/api"
|
||||||
auth_server "go.probo.inc/probo/pkg/server/auth"
|
|
||||||
trust_v1 "go.probo.inc/probo/pkg/server/api/trust/v1"
|
trust_v1 "go.probo.inc/probo/pkg/server/api/trust/v1"
|
||||||
|
auth_server "go.probo.inc/probo/pkg/server/auth"
|
||||||
"go.probo.inc/probo/pkg/server/trust"
|
"go.probo.inc/probo/pkg/server/trust"
|
||||||
"go.probo.inc/probo/pkg/server/web"
|
"go.probo.inc/probo/pkg/server/web"
|
||||||
trust_pkg "go.probo.inc/probo/pkg/trust"
|
trust_pkg "go.probo.inc/probo/pkg/trust"
|
||||||
"github.com/go-chi/chi/v5"
|
|
||||||
"go.gearno.de/kit/httpserver"
|
|
||||||
"go.gearno.de/kit/log"
|
|
||||||
"go.gearno.de/kit/pg"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
@@ -108,6 +108,7 @@ func NewServer(cfg Config) (*Server, error) {
|
|||||||
CookieDomain: cfg.ConsoleAuth.CookieDomain,
|
CookieDomain: cfg.ConsoleAuth.CookieDomain,
|
||||||
SessionDuration: cfg.ConsoleAuth.SessionDuration,
|
SessionDuration: cfg.ConsoleAuth.SessionDuration,
|
||||||
CookieSecret: cfg.ConsoleAuth.CookieSecret,
|
CookieSecret: cfg.ConsoleAuth.CookieSecret,
|
||||||
|
CookieSecure: cfg.ConsoleAuth.CookieSecure,
|
||||||
FileManager: cfg.FileManager,
|
FileManager: cfg.FileManager,
|
||||||
Logger: cfg.Logger.Named("auth"),
|
Logger: cfg.Logger.Named("auth"),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -19,16 +19,17 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"go.probo.inc/probo/pkg/auth"
|
||||||
"go.probo.inc/probo/pkg/authz"
|
"go.probo.inc/probo/pkg/authz"
|
||||||
"go.probo.inc/probo/pkg/coredata"
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
"go.probo.inc/probo/pkg/gid"
|
"go.probo.inc/probo/pkg/gid"
|
||||||
"go.probo.inc/probo/pkg/securecookie"
|
"go.probo.inc/probo/pkg/securecookie"
|
||||||
"go.probo.inc/probo/pkg/auth"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AuthConfig struct {
|
type AuthConfig struct {
|
||||||
CookieName string
|
CookieName string
|
||||||
CookieSecret string
|
CookieSecret string
|
||||||
|
CookieSecure bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthResult struct {
|
type AuthResult struct {
|
||||||
@@ -58,6 +59,7 @@ func TryAuth(
|
|||||||
cookieValue, err := securecookie.Get(r, securecookie.DefaultConfig(
|
cookieValue, err := securecookie.Get(r, securecookie.DefaultConfig(
|
||||||
authCfg.CookieName,
|
authCfg.CookieName,
|
||||||
authCfg.CookieSecret,
|
authCfg.CookieSecret,
|
||||||
|
authCfg.CookieSecure,
|
||||||
))
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, securecookie.ErrCookieNotFound) && errorHandler.OnCookieError != nil {
|
if !errors.Is(err, securecookie.ErrCookieNotFound) && errorHandler.OnCookieError != nil {
|
||||||
@@ -142,5 +144,6 @@ func ClearCookie(w http.ResponseWriter, authCfg AuthConfig) {
|
|||||||
securecookie.Clear(w, securecookie.DefaultConfig(
|
securecookie.Clear(w, securecookie.DefaultConfig(
|
||||||
authCfg.CookieName,
|
authCfg.CookieName,
|
||||||
authCfg.CookieSecret,
|
authCfg.CookieSecret,
|
||||||
|
authCfg.CookieSecure,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user