mirror of
				https://github.com/steveiliop56/tinyauth.git
				synced 2025-10-30 21:55:43 +00:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
			v4.0.1
			...
			fix/sessio
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | acc3ad97cd | ||
|   | 5409aa5f7f | ||
|   | ebcf6e6aa6 | 
							
								
								
									
										12
									
								
								cmd/root.go
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								cmd/root.go
									
									
									
									
									
								
							| @@ -74,6 +74,15 @@ var rootCmd = &cobra.Command{ | |||||||
| 		csrfCookieName := fmt.Sprintf("%s-%s", constants.CsrfCookieName, cookieId) | 		csrfCookieName := fmt.Sprintf("%s-%s", constants.CsrfCookieName, cookieId) | ||||||
| 		redirectCookieName := fmt.Sprintf("%s-%s", constants.RedirectCookieName, cookieId) | 		redirectCookieName := fmt.Sprintf("%s-%s", constants.RedirectCookieName, cookieId) | ||||||
|  |  | ||||||
|  | 		// Generate HMAC and encryption secrets | ||||||
|  | 		log.Debug().Msg("Deriving HMAC and encryption secrets") | ||||||
|  |  | ||||||
|  | 		hmacSecret, err := utils.DeriveKey(config.Secret, "hmac") | ||||||
|  | 		HandleError(err, "Failed to derive HMAC secret") | ||||||
|  |  | ||||||
|  | 		encryptionSecret, err := utils.DeriveKey(config.Secret, "encryption") | ||||||
|  | 		HandleError(err, "Failed to derive encryption secret") | ||||||
|  |  | ||||||
| 		// Create OAuth config | 		// Create OAuth config | ||||||
| 		oauthConfig := types.OAuthConfig{ | 		oauthConfig := types.OAuthConfig{ | ||||||
| 			GithubClientId:      config.GithubClientId, | 			GithubClientId:      config.GithubClientId, | ||||||
| @@ -115,13 +124,14 @@ var rootCmd = &cobra.Command{ | |||||||
| 		authConfig := types.AuthConfig{ | 		authConfig := types.AuthConfig{ | ||||||
| 			Users:             users, | 			Users:             users, | ||||||
| 			OauthWhitelist:    config.OAuthWhitelist, | 			OauthWhitelist:    config.OAuthWhitelist, | ||||||
| 			Secret:            config.Secret, |  | ||||||
| 			CookieSecure:      config.CookieSecure, | 			CookieSecure:      config.CookieSecure, | ||||||
| 			SessionExpiry:     config.SessionExpiry, | 			SessionExpiry:     config.SessionExpiry, | ||||||
| 			Domain:            domain, | 			Domain:            domain, | ||||||
| 			LoginTimeout:      config.LoginTimeout, | 			LoginTimeout:      config.LoginTimeout, | ||||||
| 			LoginMaxRetries:   config.LoginMaxRetries, | 			LoginMaxRetries:   config.LoginMaxRetries, | ||||||
| 			SessionCookieName: sessionCookieName, | 			SessionCookieName: sessionCookieName, | ||||||
|  | 			HMACSecret:        hmacSecret, | ||||||
|  | 			EncryptionSecret:  encryptionSecret, | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// Create hooks config | 		// Create hooks config | ||||||
|   | |||||||
| @@ -44,7 +44,8 @@ var handlersConfig = types.HandlersConfig{ | |||||||
| var authConfig = types.AuthConfig{ | var authConfig = types.AuthConfig{ | ||||||
| 	Users:             types.Users{}, | 	Users:             types.Users{}, | ||||||
| 	OauthWhitelist:    "", | 	OauthWhitelist:    "", | ||||||
| 	Secret:            "super-secret-api-thing-for-tests", // It is 32 chars long | 	HMACSecret:        "super-secret-api-thing-for-test1", | ||||||
|  | 	EncryptionSecret:  "super-secret-api-thing-for-test2", | ||||||
| 	CookieSecure:      false, | 	CookieSecure:      false, | ||||||
| 	SessionExpiry:     3600, | 	SessionExpiry:     3600, | ||||||
| 	LoginTimeout:      0, | 	LoginTimeout:      0, | ||||||
|   | |||||||
| @@ -33,7 +33,7 @@ type Auth struct { | |||||||
|  |  | ||||||
| func (auth *Auth) GetSession(c *gin.Context) (*sessions.Session, error) { | func (auth *Auth) GetSession(c *gin.Context) (*sessions.Session, error) { | ||||||
| 	// Create cookie store | 	// Create cookie store | ||||||
| 	store := sessions.NewCookieStore([]byte(auth.Config.Secret)) | 	store := sessions.NewCookieStore([]byte(auth.Config.HMACSecret), []byte(auth.Config.EncryptionSecret)) | ||||||
|  |  | ||||||
| 	// Configure cookie store | 	// Configure cookie store | ||||||
| 	store.Options = &sessions.Options{ | 	store.Options = &sessions.Options{ | ||||||
| @@ -46,9 +46,21 @@ func (auth *Auth) GetSession(c *gin.Context) (*sessions.Session, error) { | |||||||
|  |  | ||||||
| 	// Get session | 	// Get session | ||||||
| 	session, err := store.Get(c.Request, auth.Config.SessionCookieName) | 	session, err := store.Get(c.Request, auth.Config.SessionCookieName) | ||||||
|  |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Error().Err(err).Msg("Failed to get session") | 		log.Warn().Err(err).Msg("Invalid session, clearing cookie and retrying") | ||||||
| 		return nil, err |  | ||||||
|  | 		// Delete the session cookie if there is an error | ||||||
|  | 		c.SetCookie(auth.Config.SessionCookieName, "", -1, "/", fmt.Sprintf(".%s", auth.Config.Domain), auth.Config.CookieSecure, true) | ||||||
|  |  | ||||||
|  | 		// Try to get the session again | ||||||
|  | 		session, err = store.Get(c.Request, auth.Config.SessionCookieName) | ||||||
|  |  | ||||||
|  | 		if err != nil { | ||||||
|  | 			// If we still can't get the session, log the error and return nil | ||||||
|  | 			log.Error().Err(err).Msg("Failed to get session") | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return session, nil | 	return session, nil | ||||||
|   | |||||||
| @@ -80,12 +80,13 @@ type AuthConfig struct { | |||||||
| 	Users             Users | 	Users             Users | ||||||
| 	OauthWhitelist    string | 	OauthWhitelist    string | ||||||
| 	SessionExpiry     int | 	SessionExpiry     int | ||||||
| 	Secret            string |  | ||||||
| 	CookieSecure      bool | 	CookieSecure      bool | ||||||
| 	Domain            string | 	Domain            string | ||||||
| 	LoginTimeout      int | 	LoginTimeout      int | ||||||
| 	LoginMaxRetries   int | 	LoginMaxRetries   int | ||||||
| 	SessionCookieName string | 	SessionCookieName string | ||||||
|  | 	HMACSecret        string | ||||||
|  | 	EncryptionSecret  string | ||||||
| } | } | ||||||
|  |  | ||||||
| // HooksConfig is the configuration for the hooks service | // HooksConfig is the configuration for the hooks service | ||||||
|   | |||||||
| @@ -1,8 +1,11 @@ | |||||||
| package utils | package utils | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"crypto/sha256" | ||||||
| 	"encoding/base64" | 	"encoding/base64" | ||||||
| 	"errors" | 	"errors" | ||||||
|  | 	"io" | ||||||
| 	"net" | 	"net" | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 	"os" | 	"os" | ||||||
| @@ -11,6 +14,7 @@ import ( | |||||||
| 	"tinyauth/internal/types" | 	"tinyauth/internal/types" | ||||||
|  |  | ||||||
| 	"github.com/traefik/paerser/parser" | 	"github.com/traefik/paerser/parser" | ||||||
|  | 	"golang.org/x/crypto/hkdf" | ||||||
|  |  | ||||||
| 	"github.com/google/uuid" | 	"github.com/google/uuid" | ||||||
| 	"github.com/rs/zerolog/log" | 	"github.com/rs/zerolog/log" | ||||||
| @@ -405,3 +409,32 @@ func FilterIP(filter string, ip string) (bool, error) { | |||||||
| 	// If the filter is not a CIDR range or a single IP, return false | 	// If the filter is not a CIDR range or a single IP, return false | ||||||
| 	return false, nil | 	return false, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func DeriveKey(secret string, info string) (string, error) { | ||||||
|  | 	// Create hashing function | ||||||
|  | 	hash := sha256.New | ||||||
|  |  | ||||||
|  | 	// Create a new key using the secret and info | ||||||
|  | 	hkdf := hkdf.New(hash, []byte(secret), nil, []byte(info)) // I am not using a salt because I just want two different keys from one secret, maybe bad practice | ||||||
|  |  | ||||||
|  | 	// Create a new key | ||||||
|  | 	key := make([]byte, 24) | ||||||
|  |  | ||||||
|  | 	// Read the key from the HKDF | ||||||
|  | 	_, err := io.ReadFull(hkdf, key) | ||||||
|  |  | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Verify the key is not empty | ||||||
|  | 	if bytes.Equal(key, make([]byte, 24)) { | ||||||
|  | 		return "", errors.New("derived key is empty") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Encode the key to base64 | ||||||
|  | 	encodedKey := base64.StdEncoding.EncodeToString(key) | ||||||
|  |  | ||||||
|  | 	// Return the key as a base64 encoded string | ||||||
|  | 	return encodedKey, nil | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user