# authentic_kate Package kate provides secure cookie-based authentication for HTTP applications. This package implements encrypted cookies with authenticated encryption. It supports generic types to allow storage of any serializable data in encrypted HTTP cookies. ## Key features - Type-safe authentication data storage using Go generics - Authenticated encryption for secure cookie storage - HTTP middlewares for required and optional authentication - Ready-to-use login handlers for password, oauth, and magic link authentication - Configurable cookie properties (domain, path, HTTPS-only, max age) - Secure password hashing with industry-standard algorithms ## Example usage ```go type UserData struct { ID int Name string } // Implement SerDes interface for UserData type UserSerDes struct{} func (s UserSerDes) Serialize(w io.Writer, data UserData) error { /* ... */ } func (s UserSerDes) Deserialize(r io.Reader, data *UserData) error { /* ... */ } // Create authentication instance auth := kate.New("hex-encoded-32-byte-key", kate.AuthConfig[UserData]{ SerDes: UserSerDes{}, CookieName: "session", HTTPSOnly: true, MaxAge: 24 * time.Hour, }) // Use as middleware http.Handle("GET /protected", auth.Required(protectedHandler)) // Set authentication cookie user := UserData{ID: 123, Name: "John"} auth.Set(w, user) // Get authenticated data user, ok := auth.Get(r.Context()) ``` ## Login handlers The package provides ready-to-use HTTP handlers for several authentication methods: ### Password-based login ```go type User struct { Username string Hash string ID int } // Implement PasswordUserDataStore interface type UserStore struct{} func (us UserStore) Fetch(username string) (User, bool, error) { // Look up user in your database user, exists := database.FindUser(username) return user, exists, nil } func (us UserStore) GetPassHash(user User) string { return user.Hash } // Configure password login passwordConfig := kate.PasswordLoginConfig[User]{ UserData: UserStore{}, Redirects: kate.Redirects{ Default: "/dashboard", AllowedPrefixes: []string{"/app/", "/admin/"}, FieldName: "redirect", }, } // Create handler http.Handle("POST /login", auth.PasswordLoginHandler(passwordConfig)) ``` ### Magic link authentication ```go // Implement MagicLinkMailer interface type UserMailer struct{} func (um UserMailer) Fetch(email string) (User, bool, error) { // Look up user by email user, exists := database.FindUserByEmail(email) return user, exists, nil } func (um UserMailer) SendEmail(user User, token string) error { // Send magic link email with the token return emailService.SendMagicLink(user.Email, token) } // Configure magic link login magicConfig := kate.MagicLinkConfig[User]{ Mailer: UserMailer{}, Redirects: kate.Redirects{ Default: "/dashboard" }, TokenExpiry: 15 * time.Minute, TokenLocation: kate.TokenLocationQuery, // or TokenLocationPath } // Create handlers http.Handle("POST /magic-link", auth.MagicLinkLoginHandler(magicConfig)) http.Handle("GET /verify", auth.MagicLinkVerifyHandler(magicConfig)) ``` ### OAuth2 authentication ```go // Implement the OAuthDataStore interface type UserDataStore struct{} func (ds UserDataStore) GetOrCreateUser(email string) (User, error) { // Look up user by email, create if doesn't exist if user, exists := database.FindUserByEmail(email); exists { return user, nil } return database.CreateUser(email) } func (ds UserDataStore) StoreState(state kate.OAuthState) (string, error) { // Generate unique state ID and store temporarily id := generateUniqueID() return id, cache.Set(id, state, 10*time.Minute) } func (ds UserDataStore) GetAndClearState(id string) (*kate.OAuthState, error) { // Retrieve and delete state data var state kate.OAuthState exists, err := cache.GetAndDelete(id, &state) if !exists { return nil, err } return &state, err } // Configure Google OAuth2 login oauthConfig := kate.GoogleOAuthConfig[User]( "your-google-client-id", "your-google-client-secret", "https://yourapp.com/auth/callback", UserDataStore{}, ) // Customize redirects and security settings oauthConfig.Redirects = kate.Redirects{ Default: "/dashboard", AllowedPrefixes: []string{"/app/", "/admin/"}, FieldName: "redirect", } // Create handlers http.Handle("GET /auth/login", auth.OAuthLoginHandler(oauthConfig)) http.Handle("GET /auth/callback", auth.OAuthCallbackHandler(oauthConfig)) // GitHub OAuth2 is also supported githubConfig := kate.GitHubOAuthConfig[User]( "your-github-client-id", "your-github-client-secret", "https://yourapp.com/auth/github/callback", UserDataStore{}, ) ``` ## Password hashing The package provides secure password hashing functions using Argon2id: ```go // Hash a password with secure defaults hash, err := kate.HashPassword("user-password", nil) if err != nil { // Handle error } // Verify a password match, err := kate.ComparePassword("user-password", hash) if err != nil { // Handle malformed hash error } if match { // Password is correct } ``` ## Cryptographic algorithms This package uses the following cryptographic algorithms: - **Token encryption**: XSalsa20 stream cipher with Poly1305 MAC for authenticated encryption (compatible with libsodium secretbox) - **Password hashing**: Argon2id with secure default parameters and PHC format storage