Compare commits

...

2 Commits

Author SHA1 Message Date
Stavros
df10eb65ce chore: tidy go mod 2025-04-03 15:45:03 +03:00
Stavros
8bf5a6067e wip 2025-04-03 15:44:47 +03:00
13 changed files with 267 additions and 218 deletions

View File

@@ -105,12 +105,8 @@ var rootCmd = &cobra.Command{
// Create api config // Create api config
apiConfig := types.APIConfig{ apiConfig := types.APIConfig{
Port: config.Port, Port: config.Port,
Address: config.Address, Address: config.Address,
Secret: config.Secret,
CookieSecure: config.CookieSecure,
SessionExpiry: config.SessionExpiry,
Domain: domain,
} }
// Create docker service // Create docker service
@@ -121,7 +117,14 @@ var rootCmd = &cobra.Command{
HandleError(err, "Failed to initialize docker") HandleError(err, "Failed to initialize docker")
// Create auth service // Create auth service
auth := auth.NewAuth(docker, users, oauthWhitelist, config.SessionExpiry) auth := auth.NewAuth(types.AuthConfig{
Domain: domain,
Secret: config.Secret,
SessionExpiry: config.SessionExpiry,
CookieSecure: config.CookieSecure,
Users: users,
OAuthWhitelist: oauthWhitelist,
}, docker)
// Create OAuth providers service // Create OAuth providers service
providers := providers.NewProviders(oauthConfig) providers := providers.NewProviders(oauthConfig)

4
go.mod
View File

@@ -3,7 +3,6 @@ module tinyauth
go 1.23.2 go 1.23.2
require ( require (
github.com/gin-contrib/sessions v1.0.2
github.com/gin-gonic/gin v1.10.0 github.com/gin-gonic/gin v1.10.0
github.com/go-playground/validator/v10 v10.24.0 github.com/go-playground/validator/v10 v10.24.0
github.com/google/go-querystring v1.1.0 github.com/google/go-querystring v1.1.0
@@ -58,9 +57,8 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/goccy/go-json v0.10.4 // indirect github.com/goccy/go-json v0.10.4 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/gorilla/context v1.1.2 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/securecookie v1.1.2 // indirect
github.com/gorilla/sessions v1.2.2 // indirect github.com/gorilla/sessions v1.2.2
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect

4
go.sum
View File

@@ -65,8 +65,6 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/gin-contrib/sessions v1.0.2 h1:UaIjUvTH1cMeOdj3in6dl+Xb6It8RiKRF9Z1anbUyCA=
github.com/gin-contrib/sessions v1.0.2/go.mod h1:KxKxWqWP5LJVDCInulOl4WbLzK2KSPlLesfZ66wRvMs=
github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E= github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0= github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
@@ -99,8 +97,6 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o=
github.com/gorilla/context v1.1.2/go.mod h1:KDPwT9i/MeWHiLl90fuTgrt4/wPcv75vFAZLaOOcbxM=
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY= github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=

View File

@@ -11,23 +11,21 @@ import (
"tinyauth/internal/handlers" "tinyauth/internal/handlers"
"tinyauth/internal/types" "tinyauth/internal/types"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
func NewAPI(config types.APIConfig, handlers *handlers.Handlers) *API { func NewAPI(config types.APIConfig, handlers *handlers.Handlers) *API {
return &API{ return &API{
Config: config,
Handlers: handlers, Handlers: handlers,
Config: config,
} }
} }
type API struct { type API struct {
Config types.APIConfig
Router *gin.Engine Router *gin.Engine
Handlers *handlers.Handlers Handlers *handlers.Handlers
Config types.APIConfig
} }
func (api *API) Init() { func (api *API) Init() {
@@ -51,21 +49,6 @@ func (api *API) Init() {
log.Debug().Msg("Setting up file server") log.Debug().Msg("Setting up file server")
fileServer := http.FileServer(http.FS(dist)) fileServer := http.FileServer(http.FS(dist))
// Setup cookie store
log.Debug().Msg("Setting up cookie store")
store := cookie.NewStore([]byte(api.Config.Secret))
// Use session middleware
store.Options(sessions.Options{
Domain: api.Config.Domain,
Path: "/",
HttpOnly: true,
Secure: api.Config.CookieSecure,
MaxAge: api.Config.SessionExpiry,
})
router.Use(sessions.Sessions("tinyauth", store))
// UI middleware // UI middleware
router.Use(func(c *gin.Context) { router.Use(func(c *gin.Context) {
// If not an API request, serve the UI // If not an API request, serve the UI

View File

@@ -19,13 +19,16 @@ import (
"github.com/magiconair/properties/assert" "github.com/magiconair/properties/assert"
) )
// User
var User = types.User{
Username: "user",
Password: "$2a$10$AvGHLTYv3xiRJ0xV9xs3XeVIlkGTygI9nqIamFYB5Xu.5.0UWF7B6", // pass
}
// Simple API config for tests // Simple API config for tests
var apiConfig = types.APIConfig{ var apiConfig = types.APIConfig{
Port: 8080, Port: 8080,
Address: "0.0.0.0", Address: "0.0.0.0",
Secret: "super-secret-api-thing-for-tests", // It is 32 chars long
CookieSecure: false,
SessionExpiry: 3600,
} }
// Simple handlers config for tests // Simple handlers config for tests
@@ -38,15 +41,21 @@ var handlersConfig = types.HandlersConfig{
GenericName: "Generic", GenericName: "Generic",
} }
// Simple auth config for tests
var authConfig = types.AuthConfig{
Domain: "localhost",
Secret: "super-secret-api-thing-for-tests", // It is 32 chars long
CookieSecure: false,
SessionExpiry: 3600,
Users: types.Users{
User,
},
OAuthWhitelist: []string{},
}
// Cookie // Cookie
var cookie string var cookie string
// User
var user = types.User{
Username: "user",
Password: "$2a$10$AvGHLTYv3xiRJ0xV9xs3XeVIlkGTygI9nqIamFYB5Xu.5.0UWF7B6", // pass
}
// We need all this to be able to test the API // We need all this to be able to test the API
func getAPI(t *testing.T) *api.API { func getAPI(t *testing.T) *api.API {
// Create docker service // Create docker service
@@ -61,12 +70,7 @@ func getAPI(t *testing.T) *api.API {
} }
// Create auth service // Create auth service
auth := auth.NewAuth(docker, types.Users{ auth := auth.NewAuth(authConfig, docker)
{
Username: user.Username,
Password: user.Password,
},
}, nil, apiConfig.SessionExpiry)
// Create providers service // Create providers service
providers := providers.NewProviders(types.OAuthConfig{}) providers := providers.NewProviders(types.OAuthConfig{})

View File

@@ -1,6 +1,7 @@
package auth package auth
import ( import (
"fmt"
"regexp" "regexp"
"slices" "slices"
"strings" "strings"
@@ -8,31 +9,27 @@ import (
"tinyauth/internal/docker" "tinyauth/internal/docker"
"tinyauth/internal/types" "tinyauth/internal/types"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/gorilla/sessions"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
) )
func NewAuth(docker *docker.Docker, userList types.Users, oauthWhitelist []string, sessionExpiry int) *Auth { func NewAuth(config types.AuthConfig, docker *docker.Docker) *Auth {
return &Auth{ return &Auth{
Docker: docker, Docker: docker,
Users: userList, Config: config,
OAuthWhitelist: oauthWhitelist,
SessionExpiry: sessionExpiry,
} }
} }
type Auth struct { type Auth struct {
Users types.Users Docker *docker.Docker
Docker *docker.Docker Config types.AuthConfig
OAuthWhitelist []string
SessionExpiry int
} }
func (auth *Auth) GetUser(username string) *types.User { func (auth *Auth) GetUser(username string) *types.User {
// Loop through users and return the user if the username matches // Loop through users and return the user if the username matches
for _, user := range auth.Users { for _, user := range auth.Config.Users {
if user.Username == username { if user.Username == username {
return &user return &user
} }
@@ -47,12 +44,12 @@ func (auth *Auth) CheckPassword(user types.User, password string) bool {
func (auth *Auth) EmailWhitelisted(emailSrc string) bool { func (auth *Auth) EmailWhitelisted(emailSrc string) bool {
// If the whitelist is empty, allow all emails // If the whitelist is empty, allow all emails
if len(auth.OAuthWhitelist) == 0 { if len(auth.Config.OAuthWhitelist) == 0 {
return true return true
} }
// Loop through the whitelist and return true if the email matches // Loop through the whitelist and return true if the email matches
for _, email := range auth.OAuthWhitelist { for _, email := range auth.Config.OAuthWhitelist {
if email == emailSrc { if email == emailSrc {
return true return true
} }
@@ -62,11 +59,35 @@ func (auth *Auth) EmailWhitelisted(emailSrc string) bool {
return false return false
} }
func (auth *Auth) CreateSessionCookie(c *gin.Context, data *types.SessionCookie) { func (auth *Auth) GetCookieStore() *sessions.CookieStore {
// Create a new cookie store
store := sessions.NewCookieStore([]byte(auth.Config.Secret))
// Configure the cookie store
store.Options = &sessions.Options{
Path: "/",
Domain: fmt.Sprintf(".%s", auth.Config.Domain),
Secure: auth.Config.CookieSecure,
MaxAge: auth.Config.SessionExpiry,
HttpOnly: true,
}
// Set the cookie store
return store
}
func (auth *Auth) CreateSessionCookie(c *gin.Context, data *types.SessionCookie) error {
log.Debug().Msg("Creating session cookie") log.Debug().Msg("Creating session cookie")
// Get cookie store
store := auth.GetCookieStore()
// Get session // Get session
sessions := sessions.Default(c) sessions, err := store.Get(c.Request, "tinyauth")
if err != nil {
return err
}
log.Debug().Msg("Setting session cookie") log.Debug().Msg("Setting session cookie")
@@ -76,43 +97,73 @@ func (auth *Auth) CreateSessionCookie(c *gin.Context, data *types.SessionCookie)
if data.TotpPending { if data.TotpPending {
sessionExpiry = 3600 sessionExpiry = 3600
} else { } else {
sessionExpiry = auth.SessionExpiry sessionExpiry = auth.Config.SessionExpiry
} }
// Set data // Set data
sessions.Set("username", data.Username) sessions.Values["username"] = data.Username
sessions.Set("provider", data.Provider) sessions.Values["provider"] = data.Provider
sessions.Set("expiry", time.Now().Add(time.Duration(sessionExpiry)*time.Second).Unix()) sessions.Values["expiry"] = time.Now().Add(time.Duration(sessionExpiry) * time.Second).Unix()
sessions.Set("totpPending", data.TotpPending) sessions.Values["totpPending"] = data.TotpPending
// Save session // Save session
sessions.Save() err = sessions.Save(c.Request, c.Writer)
if err != nil {
return err
}
// Return nil
return nil
} }
func (auth *Auth) DeleteSessionCookie(c *gin.Context) { func (auth *Auth) DeleteSessionCookie(c *gin.Context) error {
log.Debug().Msg("Deleting session cookie") log.Debug().Msg("Deleting session cookie")
// Get cookie store
store := auth.GetCookieStore()
// Get session // Get session
sessions := sessions.Default(c) sessions, err := store.Get(c.Request, "tinyauth")
if err != nil {
return err
}
// Clear session // Clear session
sessions.Clear() for key := range sessions.Values {
delete(sessions.Values, key)
}
// Save session // Save session
sessions.Save() err = sessions.Save(c.Request, c.Writer)
if err != nil {
return err
}
// Return nil
return nil
} }
func (auth *Auth) GetSessionCookie(c *gin.Context) types.SessionCookie { func (auth *Auth) GetSessionCookie(c *gin.Context) (types.SessionCookie, error) {
log.Debug().Msg("Getting session cookie") log.Debug().Msg("Getting session cookie")
// Get cookie store
store := auth.GetCookieStore()
// Get session // Get session
sessions := sessions.Default(c) sessions, err := store.Get(c.Request, "tinyauth")
if err != nil {
return types.SessionCookie{}, err
}
// Get data // Get data
cookieUsername := sessions.Get("username") cookieUsername := sessions.Values["username"]
cookieProvider := sessions.Get("provider") cookieProvider := sessions.Values["provider"]
cookieExpiry := sessions.Get("expiry") cookieExpiry := sessions.Values["expiry"]
cookieTotpPending := sessions.Get("totpPending") cookieTotpPending := sessions.Values["totpPending"]
// Convert interfaces to correct types // Convert interfaces to correct types
username, usernameOk := cookieUsername.(string) username, usernameOk := cookieUsername.(string)
@@ -123,7 +174,7 @@ func (auth *Auth) GetSessionCookie(c *gin.Context) types.SessionCookie {
// Check if the cookie is invalid // Check if the cookie is invalid
if !usernameOk || !providerOk || !expiryOk || !totpPendingOk { if !usernameOk || !providerOk || !expiryOk || !totpPendingOk {
log.Warn().Msg("Session cookie invalid") log.Warn().Msg("Session cookie invalid")
return types.SessionCookie{} return types.SessionCookie{}, nil
} }
// Check if the cookie has expired // Check if the cookie has expired
@@ -134,7 +185,7 @@ func (auth *Auth) GetSessionCookie(c *gin.Context) types.SessionCookie {
auth.DeleteSessionCookie(c) auth.DeleteSessionCookie(c)
// Return empty cookie // Return empty cookie
return types.SessionCookie{} return types.SessionCookie{}, nil
} }
log.Debug().Str("username", username).Str("provider", provider).Int64("expiry", expiry).Bool("totpPending", totpPending).Msg("Parsed cookie") log.Debug().Str("username", username).Str("provider", provider).Int64("expiry", expiry).Bool("totpPending", totpPending).Msg("Parsed cookie")
@@ -144,12 +195,12 @@ func (auth *Auth) GetSessionCookie(c *gin.Context) types.SessionCookie {
Username: username, Username: username,
Provider: provider, Provider: provider,
TotpPending: totpPending, TotpPending: totpPending,
} }, nil
} }
func (auth *Auth) UserAuthConfigured() bool { func (auth *Auth) UserAuthConfigured() bool {
// If there are users, return true // If there are users, return true
return len(auth.Users) > 0 return len(auth.Config.Users) > 0
} }
func (auth *Auth) ResourceAllowed(c *gin.Context, context types.UserContext) (bool, error) { func (auth *Auth) ResourceAllowed(c *gin.Context, context types.UserContext) (bool, error) {

View File

@@ -19,20 +19,20 @@ import (
func NewHandlers(config types.HandlersConfig, auth *auth.Auth, hooks *hooks.Hooks, providers *providers.Providers, docker *docker.Docker) *Handlers { func NewHandlers(config types.HandlersConfig, auth *auth.Auth, hooks *hooks.Hooks, providers *providers.Providers, docker *docker.Docker) *Handlers {
return &Handlers{ return &Handlers{
Config: config,
Auth: auth, Auth: auth,
Hooks: hooks, Hooks: hooks,
Providers: providers, Providers: providers,
Docker: docker, Docker: docker,
Config: config,
} }
} }
type Handlers struct { type Handlers struct {
Config types.HandlersConfig
Auth *auth.Auth Auth *auth.Auth
Hooks *hooks.Hooks Hooks *hooks.Hooks
Providers *providers.Providers Providers *providers.Providers
Docker *docker.Docker Docker *docker.Docker
Config types.HandlersConfig
} }
func (h *Handlers) AuthHandler(c *gin.Context) { func (h *Handlers) AuthHandler(c *gin.Context) {

View File

@@ -23,7 +23,13 @@ type Hooks struct {
func (hooks *Hooks) UseUserContext(c *gin.Context) types.UserContext { func (hooks *Hooks) UseUserContext(c *gin.Context) types.UserContext {
// Get session cookie and basic auth // Get session cookie and basic auth
cookie := hooks.Auth.GetSessionCookie(c) cookie, err := hooks.Auth.GetSessionCookie(c)
if err != nil {
log.Error().Err(err).Msg("Failed to get session cookie")
return types.UserContext{}
}
basic := hooks.Auth.GetBasicAuth(c) basic := hooks.Auth.GetBasicAuth(c)
// Check if basic auth is set // Check if basic auth is set

View File

@@ -14,10 +14,10 @@ func NewOAuth(config oauth2.Config) *OAuth {
} }
type OAuth struct { type OAuth struct {
Config oauth2.Config Verifier string
Context context.Context Context context.Context
Token *oauth2.Token Token *oauth2.Token
Verifier string Config oauth2.Config
} }
func (oauth *OAuth) Init() { func (oauth *OAuth) Init() {

View File

@@ -17,11 +17,11 @@ func NewProviders(config types.OAuthConfig) *Providers {
} }
type Providers struct { type Providers struct {
Config types.OAuthConfig
Github *oauth.OAuth Github *oauth.OAuth
Google *oauth.OAuth Google *oauth.OAuth
Tailscale *oauth.OAuth Tailscale *oauth.OAuth
Generic *oauth.OAuth Generic *oauth.OAuth
Config types.OAuthConfig
} }
func (providers *Providers) Init() { func (providers *Providers) Init() {

49
internal/types/api.go Normal file
View File

@@ -0,0 +1,49 @@
package types
// LoginQuery is the query parameters for the login endpoint
type LoginQuery struct {
RedirectURI string `url:"redirect_uri"`
}
// LoginRequest is the request body for the login endpoint
type LoginRequest struct {
Username string `json:"username"`
Password string `json:"password"`
}
// OAuthRequest is the request for the OAuth endpoint
type OAuthRequest struct {
Provider string `uri:"provider" binding:"required"`
}
// UnauthorizedQuery is the query parameters for the unauthorized endpoint
type UnauthorizedQuery struct {
Username string `url:"username"`
Resource string `url:"resource"`
}
// TailscaleQuery is the query parameters for the tailscale endpoint
type TailscaleQuery struct {
Code int `url:"code"`
}
// Proxy is the uri parameters for the proxy endpoint
type Proxy struct {
Proxy string `uri:"proxy" binding:"required"`
}
// User Context response is the response for the user context endpoint
type UserContextResponse struct {
Status int `json:"status"`
Message string `json:"message"`
IsLoggedIn bool `json:"isLoggedIn"`
Username string `json:"username"`
Provider string `json:"provider"`
Oauth bool `json:"oauth"`
TotpPending bool `json:"totpPending"`
}
// Totp request is the request for the totp endpoint
type TotpRequest struct {
Code string `json:"code"`
}

79
internal/types/config.go Normal file
View File

@@ -0,0 +1,79 @@
package types
// Config is the configuration for the tinyauth server
type Config struct {
Port int `mapstructure:"port" validate:"required"`
Address string `validate:"required,ip4_addr" mapstructure:"address"`
Secret string `validate:"required,len=32" mapstructure:"secret"`
SecretFile string `mapstructure:"secret-file"`
AppURL string `validate:"required,url" mapstructure:"app-url"`
Users string `mapstructure:"users"`
UsersFile string `mapstructure:"users-file"`
CookieSecure bool `mapstructure:"cookie-secure"`
GithubClientId string `mapstructure:"github-client-id"`
GithubClientSecret string `mapstructure:"github-client-secret"`
GithubClientSecretFile string `mapstructure:"github-client-secret-file"`
GoogleClientId string `mapstructure:"google-client-id"`
GoogleClientSecret string `mapstructure:"google-client-secret"`
GoogleClientSecretFile string `mapstructure:"google-client-secret-file"`
TailscaleClientId string `mapstructure:"tailscale-client-id"`
TailscaleClientSecret string `mapstructure:"tailscale-client-secret"`
TailscaleClientSecretFile string `mapstructure:"tailscale-client-secret-file"`
GenericClientId string `mapstructure:"generic-client-id"`
GenericClientSecret string `mapstructure:"generic-client-secret"`
GenericClientSecretFile string `mapstructure:"generic-client-secret-file"`
GenericScopes string `mapstructure:"generic-scopes"`
GenericAuthURL string `mapstructure:"generic-auth-url"`
GenericTokenURL string `mapstructure:"generic-token-url"`
GenericUserURL string `mapstructure:"generic-user-url"`
GenericName string `mapstructure:"generic-name"`
DisableContinue bool `mapstructure:"disable-continue"`
OAuthWhitelist string `mapstructure:"oauth-whitelist"`
SessionExpiry int `mapstructure:"session-expiry"`
LogLevel int8 `mapstructure:"log-level" validate:"min=-1,max=5"`
Title string `mapstructure:"app-title"`
EnvFile string `mapstructure:"env-file"`
}
// APIConfig is the configuration for the API
type APIConfig struct {
Port int
Address string
}
// OAuthConfig is the configuration for the providers
type OAuthConfig struct {
GithubClientId string
GithubClientSecret string
GoogleClientId string
GoogleClientSecret string
TailscaleClientId string
TailscaleClientSecret string
GenericClientId string
GenericClientSecret string
GenericScopes []string
GenericAuthURL string
GenericTokenURL string
GenericUserURL string
AppURL string
}
// Server configuration
type HandlersConfig struct {
AppURL string
Domain string
CookieSecure bool
DisableContinue bool
GenericName string
Title string
}
// Auth configuration
type AuthConfig struct {
Domain string
Secret string
CookieSecure bool
SessionExpiry int
Users Users
OAuthWhitelist []string
}

View File

@@ -2,17 +2,6 @@ package types
import "tinyauth/internal/oauth" import "tinyauth/internal/oauth"
// LoginQuery is the query parameters for the login endpoint
type LoginQuery struct {
RedirectURI string `url:"redirect_uri"`
}
// LoginRequest is the request body for the login endpoint
type LoginRequest struct {
Username string `json:"username"`
Password string `json:"password"`
}
// User is the struct for a user // User is the struct for a user
type User struct { type User struct {
Username string Username string
@@ -23,82 +12,6 @@ type User struct {
// Users is a list of users // Users is a list of users
type Users []User type Users []User
// Config is the configuration for the tinyauth server
type Config struct {
Port int `mapstructure:"port" validate:"required"`
Address string `validate:"required,ip4_addr" mapstructure:"address"`
Secret string `validate:"required,len=32" mapstructure:"secret"`
SecretFile string `mapstructure:"secret-file"`
AppURL string `validate:"required,url" mapstructure:"app-url"`
Users string `mapstructure:"users"`
UsersFile string `mapstructure:"users-file"`
CookieSecure bool `mapstructure:"cookie-secure"`
GithubClientId string `mapstructure:"github-client-id"`
GithubClientSecret string `mapstructure:"github-client-secret"`
GithubClientSecretFile string `mapstructure:"github-client-secret-file"`
GoogleClientId string `mapstructure:"google-client-id"`
GoogleClientSecret string `mapstructure:"google-client-secret"`
GoogleClientSecretFile string `mapstructure:"google-client-secret-file"`
TailscaleClientId string `mapstructure:"tailscale-client-id"`
TailscaleClientSecret string `mapstructure:"tailscale-client-secret"`
TailscaleClientSecretFile string `mapstructure:"tailscale-client-secret-file"`
GenericClientId string `mapstructure:"generic-client-id"`
GenericClientSecret string `mapstructure:"generic-client-secret"`
GenericClientSecretFile string `mapstructure:"generic-client-secret-file"`
GenericScopes string `mapstructure:"generic-scopes"`
GenericAuthURL string `mapstructure:"generic-auth-url"`
GenericTokenURL string `mapstructure:"generic-token-url"`
GenericUserURL string `mapstructure:"generic-user-url"`
GenericName string `mapstructure:"generic-name"`
DisableContinue bool `mapstructure:"disable-continue"`
OAuthWhitelist string `mapstructure:"oauth-whitelist"`
SessionExpiry int `mapstructure:"session-expiry"`
LogLevel int8 `mapstructure:"log-level" validate:"min=-1,max=5"`
Title string `mapstructure:"app-title"`
EnvFile string `mapstructure:"env-file"`
}
// UserContext is the context for the user
type UserContext struct {
Username string
IsLoggedIn bool
OAuth bool
Provider string
TotpPending bool
}
// APIConfig is the configuration for the API
type APIConfig struct {
Port int
Address string
Secret string
CookieSecure bool
SessionExpiry int
Domain string
}
// OAuthConfig is the configuration for the providers
type OAuthConfig struct {
GithubClientId string
GithubClientSecret string
GoogleClientId string
GoogleClientSecret string
TailscaleClientId string
TailscaleClientSecret string
GenericClientId string
GenericClientSecret string
GenericScopes []string
GenericAuthURL string
GenericTokenURL string
GenericUserURL string
AppURL string
}
// OAuthRequest is the request for the OAuth endpoint
type OAuthRequest struct {
Provider string `uri:"provider" binding:"required"`
}
// OAuthProviders is the struct for the OAuth providers // OAuthProviders is the struct for the OAuth providers
type OAuthProviders struct { type OAuthProviders struct {
Github *oauth.OAuth Github *oauth.OAuth
@@ -106,12 +19,6 @@ type OAuthProviders struct {
Microsoft *oauth.OAuth Microsoft *oauth.OAuth
} }
// UnauthorizedQuery is the query parameters for the unauthorized endpoint
type UnauthorizedQuery struct {
Username string `url:"username"`
Resource string `url:"resource"`
}
// SessionCookie is the cookie for the session (exculding the expiry) // SessionCookie is the cookie for the session (exculding the expiry)
type SessionCookie struct { type SessionCookie struct {
Username string Username string
@@ -127,25 +34,13 @@ type TinyauthLabels struct {
Headers map[string]string Headers map[string]string
} }
// TailscaleQuery is the query parameters for the tailscale endpoint // UserContext is the context for the user
type TailscaleQuery struct { type UserContext struct {
Code int `url:"code"` Username string
} IsLoggedIn bool
OAuth bool
// Proxy is the uri parameters for the proxy endpoint Provider string
type Proxy struct { TotpPending bool
Proxy string `uri:"proxy" binding:"required"`
}
// User Context response is the response for the user context endpoint
type UserContextResponse struct {
Status int `json:"status"`
Message string `json:"message"`
IsLoggedIn bool `json:"isLoggedIn"`
Username string `json:"username"`
Provider string `json:"provider"`
Oauth bool `json:"oauth"`
TotpPending bool `json:"totpPending"`
} }
// App Context is the response for the app context endpoint // App Context is the response for the app context endpoint
@@ -157,18 +52,3 @@ type AppContext struct {
Title string `json:"title"` Title string `json:"title"`
GenericName string `json:"genericName"` GenericName string `json:"genericName"`
} }
// Totp request is the request for the totp endpoint
type TotpRequest struct {
Code string `json:"code"`
}
// Server configuration
type HandlersConfig struct {
AppURL string
Domain string
CookieSecure bool
DisableContinue bool
GenericName string
Title string
}