Compare commits

..

29 Commits

Author SHA1 Message Date
Stavros
97b0d3e350 fix: use axios error instead of generic error in login page 2025-05-20 17:16:08 +03:00
Stavros
e8190456c3 feat: validate api response against zod schema 2025-05-20 17:12:39 +03:00
Stavros
02f83baa4d chore: formatting 2025-05-20 17:02:10 +03:00
Stavros
d59f35467e Merge branch 'main' into feat/new-ui 2025-05-20 16:49:19 +03:00
Stavros
00fbbfc4f2 chore: remove translations cdn 2025-05-15 16:07:38 +03:00
Stavros
76346fe835 fix: fix hook rendering 2025-05-15 16:05:21 +03:00
Stavros
03f193090d fix: fix dockerfiles 2025-05-15 15:57:12 +03:00
Stavros
3612ac0740 refactor: change select color 2025-05-15 15:50:34 +03:00
Stavros
00203722f8 fix: run oauth auto redirect only when there is a redirect URI 2025-05-14 21:00:06 +03:00
Stavros
60093997dc fix: correctly redirect to app and check for untrusted redirects 2025-05-14 20:56:24 +03:00
Stavros
ada21776bc refactor: bot suggestions 2025-05-14 20:43:18 +03:00
Stavros
b12d0655d4 chore: fix dependabot config 2025-05-14 20:26:38 +03:00
Stavros
2246ca0c13 Merge branch 'main' into feat/new-ui 2025-05-14 20:21:37 +03:00
Stavros
10dc228f6c feat: sanitize redirect URL on check 2025-05-14 20:08:48 +03:00
Stavros
28eea8d40c feat: sanitize redirect URL 2025-05-14 20:08:04 +03:00
Stavros
a4224e6771 chore: add acknowledgements for background image 2025-05-14 19:50:44 +03:00
Stavros
003f55b9ff feat: custom background image config option 2025-05-14 19:47:56 +03:00
Stavros
dbc460144e feat: favicons 2025-05-14 19:36:57 +03:00
Stavros
f05181b05d chore: rename docs back to assets 2025-05-14 19:29:28 +03:00
Stavros
28ef893456 chore: update readme and assets 2025-05-12 23:16:17 +03:00
Stavros
a488b70bbe feat: add oauth logic 2025-05-12 23:03:14 +03:00
Stavros
4e91e567b2 fix: use correct tab order in login form 2025-05-09 23:17:53 +03:00
Stavros
6453edede6 feat: finalize username login 2025-05-09 22:55:52 +03:00
Stavros
41c63e5b49 feat: user context 2025-05-09 17:39:14 +03:00
Stavros
31a7b0ff06 feat: app context 2025-05-09 16:49:54 +03:00
Stavros
0880152b48 chore: remove unused translations 2025-05-09 16:26:26 +03:00
Stavros
51532350cc feat: finalize pages 2025-05-09 16:25:12 +03:00
Stavros
56ae246ff4 feat: make forms functional 2025-05-08 18:08:56 +03:00
Stavros
fd96f39d3a wip 2025-04-29 22:36:48 +03:00
9 changed files with 35 additions and 85 deletions

View File

@@ -24,22 +24,18 @@ Tinyauth is a simple authentication middleware that adds simple username/passwor
> [!NOTE]
> Tinyauth is intended for homelab use only and it is not made for production use cases. If you are looking for something production ready please use [authentik](https://goauthentik.io) instead.
## Discord
I just made a Discord server for tinyauth! It is not only for tinyauth but general self-hosting and homelabbing. [See you there!](https://discord.gg/eHzVaCzRRd).
## Getting Started
You can easily get started with tinyauth by following the guide in the [documentation](https://tinyauth.app/docs/getting-started.html). There is also an available [docker compose file](./docker-compose.example.yml) that has traefik, whoami and tinyauth to demonstrate its capabilities.
## Demo
If you are still not sure if tinyauth suits your needs you can try out the [demo](https://demo.tinyauth.app). The default username is `user` and the default password is `password`.
## Documentation
You can find documentation and guides on all of the available configuration of tinyauth in the [website](https://tinyauth.app).
## Discord
I just made a Discord server for tinyauth! It is not only for tinyauth but general self-hosting and homelabbing. [See you there!](https://discord.gg/eHzVaCzRRd).
## Contributing
All contributions to the codebase are welcome! If you have any recommendations on how to improve security or find a security issue in tinyauth please open an issue or pull request so it can be fixed as soon as possible!

View File

@@ -2,7 +2,6 @@ package cmd
import (
"errors"
"fmt"
"os"
"strings"
"time"
@@ -68,12 +67,6 @@ var rootCmd = &cobra.Command{
HandleError(err, "Failed to get upper domain")
log.Info().Str("domain", domain).Msg("Using domain for cookie store")
// Generate cookie name
cookieId := utils.GenerateIdentifier(strings.Split(domain, ".")[0])
sessionCookieName := fmt.Sprintf("%s-%s", constants.SessionCookieName, cookieId)
csrfCookieName := fmt.Sprintf("%s-%s", constants.CsrfCookieName, cookieId)
redirectCookieName := fmt.Sprintf("%s-%s", constants.RedirectCookieName, cookieId)
// Create OAuth config
oauthConfig := types.OAuthConfig{
GithubClientId: config.GithubClientId,
@@ -100,8 +93,6 @@ var rootCmd = &cobra.Command{
ForgotPasswordMessage: config.FogotPasswordMessage,
BackgroundImage: config.BackgroundImage,
OAuthAutoRedirect: config.OAuthAutoRedirect,
CsrfCookieName: csrfCookieName,
RedirectCookieName: redirectCookieName,
}
// Create api config
@@ -120,7 +111,6 @@ var rootCmd = &cobra.Command{
Domain: domain,
LoginTimeout: config.LoginTimeout,
LoginMaxRetries: config.LoginMaxRetries,
SessionCookieName: sessionCookieName,
}
// Create hooks config

1
go.mod
View File

@@ -6,7 +6,6 @@ require (
github.com/gin-gonic/gin v1.10.0
github.com/go-playground/validator/v10 v10.26.0
github.com/google/go-querystring v1.1.0
github.com/google/uuid v1.6.0
github.com/mdp/qrterminal/v3 v3.2.1
github.com/rs/zerolog v1.34.0
github.com/spf13/cobra v1.9.1

View File

@@ -28,16 +28,10 @@ var apiConfig = types.APIConfig{
// Simple handlers config for tests
var handlersConfig = types.HandlersConfig{
AppURL: "http://localhost:8080",
Domain: "localhost",
DisableContinue: false,
CookieSecure: false,
Title: "Tinyauth",
GenericName: "Generic",
ForgotPasswordMessage: "Some message",
CsrfCookieName: "tinyauth-csrf",
RedirectCookieName: "tinyauth-redirect",
BackgroundImage: "https://example.com/image.png",
OAuthAutoRedirect: "none",
}
// Simple auth config for tests
@@ -49,8 +43,6 @@ var authConfig = types.AuthConfig{
SessionExpiry: 3600,
LoginTimeout: 0,
LoginMaxRetries: 0,
SessionCookieName: "tinyauth-session",
Domain: "localhost",
}
// Simple hooks config for tests
@@ -214,9 +206,6 @@ func TestAppContext(t *testing.T) {
Title: "Tinyauth",
GenericName: "Generic",
ForgotPasswordMessage: "Some message",
BackgroundImage: "https://example.com/image.png",
OAuthAutoRedirect: "none",
Domain: "localhost",
}
// We should get the username back
@@ -245,7 +234,7 @@ func TestUserContext(t *testing.T) {
// Set the cookie
req.AddCookie(&http.Cookie{
Name: "tinyauth-session",
Name: "tinyauth",
Value: cookie,
})

View File

@@ -45,7 +45,7 @@ func (auth *Auth) GetSession(c *gin.Context) (*sessions.Session, error) {
}
// Get session
session, err := store.Get(c.Request, auth.Config.SessionCookieName)
session, err := store.Get(c.Request, "tinyauth")
if err != nil {
log.Error().Err(err).Msg("Failed to get session")
return nil, err

View File

@@ -21,8 +21,3 @@ type Claims struct {
var Version = "development"
var CommitHash = "n/a"
var BuildTimestamp = "n/a"
// Cookie names
var SessionCookieName = "tinyauth-session"
var CsrfCookieName = "tinyauth-csrf"
var RedirectCookieName = "tinyauth-redirect"

View File

@@ -581,7 +581,7 @@ func (h *Handlers) OauthUrlHandler(c *gin.Context) {
log.Debug().Msg("Got auth URL")
// Set CSRF cookie
c.SetCookie(h.Config.CsrfCookieName, state, int(time.Hour.Seconds()), "/", "", h.Config.CookieSecure, true)
c.SetCookie("tinyauth-csrf", state, int(time.Hour.Seconds()), "/", "", h.Config.CookieSecure, true)
// Get redirect URI
redirectURI := c.Query("redirect_uri")
@@ -589,7 +589,7 @@ func (h *Handlers) OauthUrlHandler(c *gin.Context) {
// Set redirect cookie if redirect URI is provided
if redirectURI != "" {
log.Debug().Str("redirectURI", redirectURI).Msg("Setting redirect cookie")
c.SetCookie(h.Config.RedirectCookieName, redirectURI, int(time.Hour.Seconds()), "/", "", h.Config.CookieSecure, true)
c.SetCookie("tinyauth-redirect", redirectURI, int(time.Hour.Seconds()), "/", "", h.Config.CookieSecure, true)
}
// Return auth URL
@@ -620,7 +620,7 @@ func (h *Handlers) OauthCallbackHandler(c *gin.Context) {
state := c.Query("state")
// Get CSRF cookie
csrfCookie, err := c.Cookie(h.Config.CsrfCookieName)
csrfCookie, err := c.Cookie("tinyauth-csrf")
if err != nil {
log.Debug().Msg("No CSRF cookie")
@@ -638,7 +638,7 @@ func (h *Handlers) OauthCallbackHandler(c *gin.Context) {
}
// Clean up CSRF cookie
c.SetCookie(h.Config.CsrfCookieName, "", -1, "/", "", h.Config.CookieSecure, true)
c.SetCookie("tinyauth-csrf", "", -1, "/", "", h.Config.CookieSecure, true)
// Get code
code := c.Query("code")
@@ -737,7 +737,7 @@ func (h *Handlers) OauthCallbackHandler(c *gin.Context) {
})
// Check if we have a redirect URI
redirectCookie, err := c.Cookie(h.Config.RedirectCookieName)
redirectCookie, err := c.Cookie("tinyauth-redirect")
if err != nil {
log.Debug().Msg("No redirect cookie")
@@ -762,7 +762,7 @@ func (h *Handlers) OauthCallbackHandler(c *gin.Context) {
}
// Clean up redirect cookie
c.SetCookie(h.Config.RedirectCookieName, "", -1, "/", "", h.Config.CookieSecure, true)
c.SetCookie("tinyauth-redirect", "", -1, "/", "", h.Config.CookieSecure, true)
// Redirect to continue with the redirect URI
c.Redirect(http.StatusPermanentRedirect, fmt.Sprintf("%s/continue?%s", h.Config.AppURL, queries.Encode()))

View File

@@ -48,8 +48,6 @@ type HandlersConfig struct {
ForgotPasswordMessage string
BackgroundImage string
OAuthAutoRedirect string
CsrfCookieName string
RedirectCookieName string
}
// OAuthConfig is the configuration for the providers
@@ -83,7 +81,6 @@ type AuthConfig struct {
Domain string
LoginTimeout int
LoginMaxRetries int
SessionCookieName string
}
// HooksConfig is the configuration for the hooks service

View File

@@ -10,7 +10,6 @@ import (
"tinyauth/internal/constants"
"tinyauth/internal/types"
"github.com/google/uuid"
"github.com/rs/zerolog/log"
)
@@ -345,18 +344,3 @@ func SanitizeHeader(header string) string {
return -1
}, header)
}
// Generate a static identifier from a string
func GenerateIdentifier(str string) string {
// Create a new UUID
uuid := uuid.NewSHA1(uuid.NameSpaceURL, []byte(str))
// Convert the UUID to a string
uuidString := uuid.String()
// Show the UUID
log.Debug().Str("uuid", uuidString).Msg("Generated UUID")
// Convert the UUID to a string
return strings.Split(uuidString, "-")[0]
}