feat(backend): let cookie name be configurable through config

This commit is contained in:
Frederic Jahn
2023-07-03 15:14:57 +02:00
parent d97a1adde7
commit f944abcd63
5 changed files with 34 additions and 11 deletions

View File

@ -216,12 +216,21 @@ type Password struct {
} }
type Cookie struct { type Cookie struct {
Name string `yaml:"name" json:"name" koanf:"name"`
Domain string `yaml:"domain" json:"domain" koanf:"domain"` Domain string `yaml:"domain" json:"domain" koanf:"domain"`
HttpOnly bool `yaml:"http_only" json:"http_only" koanf:"http_only" split_words:"true"` HttpOnly bool `yaml:"http_only" json:"http_only" koanf:"http_only" split_words:"true"`
SameSite string `yaml:"same_site" json:"same_site" koanf:"same_site" split_words:"true"` SameSite string `yaml:"same_site" json:"same_site" koanf:"same_site" split_words:"true"`
Secure bool `yaml:"secure" json:"secure" koanf:"secure"` Secure bool `yaml:"secure" json:"secure" koanf:"secure"`
} }
func (c *Cookie) GetName() string {
if c.Name != "" {
return c.Name
}
return "hanko"
}
type ServerSettings struct { type ServerSettings struct {
// The Address to listen on in the form of host:port // The Address to listen on in the form of host:port
// See net.Dial for details of the address format. // See net.Dial for details of the address format.

View File

@ -166,6 +166,13 @@ session:
# Default value: true # Default value: true
# #
secure: true secure: true
## name ##
#
# Sets the name of the cookie.
#
# Default value: hanko
#
name: true
## enable_auth_token_header ## ## enable_auth_token_header ##
# #
# The JWT will be transmitted via the X-Auth-Token header. Enable during cross-domain operations. # The JWT will be transmitted via the X-Auth-Token header. Enable during cross-domain operations.

View File

@ -59,6 +59,8 @@ func NewPublicRouter(cfg *config.Config, persister persistence.Persister, promet
panic(fmt.Errorf("failed to create session generator: %w", err)) panic(fmt.Errorf("failed to create session generator: %w", err))
} }
sessionMiddleware := hankoMiddleware.Session(cfg, sessionManager)
mailer, err := mail.NewMailer(cfg.Passcode.Smtp) mailer, err := mail.NewMailer(cfg.Passcode.Smtp)
if err != nil { if err != nil {
panic(fmt.Errorf("failed to create mailer: %w", err)) panic(fmt.Errorf("failed to create mailer: %w", err))
@ -70,23 +72,23 @@ func NewPublicRouter(cfg *config.Config, persister persistence.Persister, promet
passwordHandler := NewPasswordHandler(persister, sessionManager, cfg, auditLogger) passwordHandler := NewPasswordHandler(persister, sessionManager, cfg, auditLogger)
password := e.Group("/password") password := e.Group("/password")
password.PUT("", passwordHandler.Set, hankoMiddleware.Session(sessionManager)) password.PUT("", passwordHandler.Set, sessionMiddleware)
password.POST("/login", passwordHandler.Login) password.POST("/login", passwordHandler.Login)
} }
userHandler := NewUserHandler(cfg, persister, sessionManager, auditLogger) userHandler := NewUserHandler(cfg, persister, sessionManager, auditLogger)
e.GET("/me", userHandler.Me, hankoMiddleware.Session(sessionManager)) e.GET("/me", userHandler.Me, sessionMiddleware)
user := e.Group("/users") user := e.Group("/users")
user.POST("", userHandler.Create) user.POST("", userHandler.Create)
user.GET("/:id", userHandler.Get, hankoMiddleware.Session(sessionManager)) user.GET("/:id", userHandler.Get, sessionMiddleware)
e.POST("/user", userHandler.GetUserIdByEmail) e.POST("/user", userHandler.GetUserIdByEmail)
e.POST("/logout", userHandler.Logout, hankoMiddleware.Session(sessionManager)) e.POST("/logout", userHandler.Logout, sessionMiddleware)
if cfg.Account.AllowDeletion { if cfg.Account.AllowDeletion {
e.DELETE("/user", userHandler.Delete, hankoMiddleware.Session(sessionManager)) e.DELETE("/user", userHandler.Delete, sessionMiddleware)
} }
healthHandler := NewHealthHandler() healthHandler := NewHealthHandler()
@ -117,7 +119,7 @@ func NewPublicRouter(cfg *config.Config, persister persistence.Persister, promet
} }
webauthn := e.Group("/webauthn") webauthn := e.Group("/webauthn")
webauthnRegistration := webauthn.Group("/registration", hankoMiddleware.Session(sessionManager)) webauthnRegistration := webauthn.Group("/registration", sessionMiddleware)
webauthnRegistration.POST("/initialize", webauthnHandler.BeginRegistration) webauthnRegistration.POST("/initialize", webauthnHandler.BeginRegistration)
webauthnRegistration.POST("/finalize", webauthnHandler.FinishRegistration) webauthnRegistration.POST("/finalize", webauthnHandler.FinishRegistration)
@ -125,7 +127,7 @@ func NewPublicRouter(cfg *config.Config, persister persistence.Persister, promet
webauthnLogin.POST("/initialize", webauthnHandler.BeginAuthentication) webauthnLogin.POST("/initialize", webauthnHandler.BeginAuthentication)
webauthnLogin.POST("/finalize", webauthnHandler.FinishAuthentication) webauthnLogin.POST("/finalize", webauthnHandler.FinishAuthentication)
webauthnCredentials := webauthn.Group("/credentials", hankoMiddleware.Session(sessionManager)) webauthnCredentials := webauthn.Group("/credentials", sessionMiddleware)
webauthnCredentials.GET("", webauthnHandler.ListCredentials) webauthnCredentials.GET("", webauthnHandler.ListCredentials)
webauthnCredentials.PATCH("/:id", webauthnHandler.UpdateCredential) webauthnCredentials.PATCH("/:id", webauthnHandler.UpdateCredential)
webauthnCredentials.DELETE("/:id", webauthnHandler.DeleteCredential) webauthnCredentials.DELETE("/:id", webauthnHandler.DeleteCredential)
@ -135,7 +137,7 @@ func NewPublicRouter(cfg *config.Config, persister persistence.Persister, promet
passcodeLogin.POST("/initialize", passcodeHandler.Init) passcodeLogin.POST("/initialize", passcodeHandler.Init)
passcodeLogin.POST("/finalize", passcodeHandler.Finish) passcodeLogin.POST("/finalize", passcodeHandler.Finish)
email := e.Group("/emails", hankoMiddleware.Session(sessionManager)) email := e.Group("/emails", sessionMiddleware)
email.GET("", emailHandler.List) email.GET("", emailHandler.List)
email.POST("", emailHandler.Create) email.POST("", emailHandler.Create)
email.DELETE("/:id", emailHandler.Delete) email.DELETE("/:id", emailHandler.Delete)

View File

@ -1,17 +1,19 @@
package middleware package middleware
import ( import (
"fmt"
echojwt "github.com/labstack/echo-jwt/v4" echojwt "github.com/labstack/echo-jwt/v4"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/teamhanko/hanko/backend/config"
"github.com/teamhanko/hanko/backend/session" "github.com/teamhanko/hanko/backend/session"
"net/http" "net/http"
) )
// Session is a convenience function to create a middleware.JWT with custom JWT verification // Session is a convenience function to create a middleware.JWT with custom JWT verification
func Session(generator session.Manager) echo.MiddlewareFunc { func Session(cfg *config.Config, generator session.Manager) echo.MiddlewareFunc {
c := echojwt.Config{ c := echojwt.Config{
ContextKey: "session", ContextKey: "session",
TokenLookup: "header:Authorization:Bearer,cookie:hanko", TokenLookup: fmt.Sprintf("header:Authorization:Bearer,cookie:%s", cfg.Session.Cookie.GetName()),
ParseTokenFunc: parseToken(generator), ParseTokenFunc: parseToken(generator),
ErrorHandler: func(c echo.Context, err error) error { ErrorHandler: func(c echo.Context, err error) error {
return echo.NewHTTPError(http.StatusUnauthorized).SetInternal(err) return echo.NewHTTPError(http.StatusUnauthorized).SetInternal(err)

View File

@ -28,6 +28,7 @@ type manager struct {
} }
type cookieConfig struct { type cookieConfig struct {
Name string
Domain string Domain string
HttpOnly bool HttpOnly bool
SameSite http.SameSite SameSite http.SameSite
@ -67,11 +68,13 @@ func NewManager(jwkManager hankoJwk.Manager, config config.Config) (Manager, err
} else { } else {
audience = []string{config.Webauthn.RelyingParty.Id} audience = []string{config.Webauthn.RelyingParty.Id}
} }
return &manager{ return &manager{
jwtGenerator: g, jwtGenerator: g,
sessionLength: duration, sessionLength: duration,
issuer: config.Session.Issuer, issuer: config.Session.Issuer,
cookieConfig: cookieConfig{ cookieConfig: cookieConfig{
Name: config.Session.Cookie.GetName(),
Domain: config.Session.Cookie.Domain, Domain: config.Session.Cookie.Domain,
HttpOnly: config.Session.Cookie.HttpOnly, HttpOnly: config.Session.Cookie.HttpOnly,
SameSite: sameSite, SameSite: sameSite,
@ -116,7 +119,7 @@ func (m *manager) Verify(token string) (jwt.Token, error) {
// GenerateCookie creates a new session cookie for the given user // GenerateCookie creates a new session cookie for the given user
func (m *manager) GenerateCookie(token string) (*http.Cookie, error) { func (m *manager) GenerateCookie(token string) (*http.Cookie, error) {
return &http.Cookie{ return &http.Cookie{
Name: "hanko", Name: m.cookieConfig.Name,
Value: token, Value: token,
Domain: m.cookieConfig.Domain, Domain: m.cookieConfig.Domain,
Path: "/", Path: "/",