mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2026-05-08 05:18:11 +00:00
* feat: add support for oauth whitelist file (#817) * Merge branch 'main' into feat/oauth-whitelist-file * fix: fix conflicts * tests: use testify for testing --------- Co-authored-by: Stavros <steveiliop56@gmail.com>
This commit is contained in:
@@ -91,6 +91,8 @@ TINYAUTH_APPS_name_LDAP_GROUPS=
|
||||
|
||||
# Comma-separated list of allowed OAuth domains.
|
||||
TINYAUTH_OAUTH_WHITELIST=
|
||||
# Path to the OAuth whitelist file.
|
||||
TINYAUTH_OAUTH_WHITELISTFILE=
|
||||
# The OAuth provider to use for automatic redirection.
|
||||
TINYAUTH_OAUTH_AUTOREDIRECT=
|
||||
# OAuth client ID.
|
||||
|
||||
@@ -31,6 +31,7 @@ type BootstrapApp struct {
|
||||
oauthSessionCookieName string
|
||||
localUsers *[]model.LocalUser
|
||||
oauthProviders map[string]model.OAuthServiceConfig
|
||||
oauthWhitelist []string
|
||||
configuredProviders []controller.Provider
|
||||
oidcClients []model.OIDCClientConfig
|
||||
}
|
||||
@@ -71,6 +72,13 @@ func (app *BootstrapApp) Setup() error {
|
||||
|
||||
app.context.localUsers = users
|
||||
|
||||
oauthWhitelist, err := utils.GetStringList(app.config.OAuth.Whitelist, app.config.OAuth.WhitelistFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
app.context.oauthWhitelist = oauthWhitelist
|
||||
|
||||
// Setup OAuth providers
|
||||
app.context.oauthProviders = app.config.OAuth.Providers
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ func (app *BootstrapApp) initServices(queries *repository.Queries) (Services, er
|
||||
|
||||
authService := service.NewAuthService(service.AuthServiceConfig{
|
||||
LocalUsers: app.context.localUsers,
|
||||
OauthWhitelist: app.config.OAuth.Whitelist,
|
||||
OauthWhitelist: app.context.oauthWhitelist,
|
||||
SessionExpiry: app.config.Auth.SessionExpiry,
|
||||
SessionMaxLifetime: app.config.Auth.SessionMaxLifetime,
|
||||
SecureCookie: app.config.Auth.SecureCookie,
|
||||
|
||||
@@ -148,6 +148,7 @@ type IPConfig struct {
|
||||
|
||||
type OAuthConfig struct {
|
||||
Whitelist []string `description:"Comma-separated list of allowed OAuth domains." yaml:"whitelist"`
|
||||
WhitelistFile string `description:"Path to the OAuth whitelist file." yaml:"whitelistFile"`
|
||||
AutoRedirect string `description:"The OAuth provider to use for automatic redirection." yaml:"autoRedirect"`
|
||||
Providers map[string]OAuthServiceConfig `description:"OAuth providers configuration." yaml:"providers"`
|
||||
}
|
||||
|
||||
@@ -28,3 +28,41 @@ func CoalesceToString(value any) string {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func ParseNonEmptyLines(contents string) []string {
|
||||
lines := make([]string, 0)
|
||||
|
||||
for line := range strings.SplitSeq(contents, "\n") {
|
||||
lineTrimmed := strings.TrimSpace(line)
|
||||
if lineTrimmed == "" {
|
||||
continue
|
||||
}
|
||||
lines = append(lines, lineTrimmed)
|
||||
}
|
||||
|
||||
return lines
|
||||
}
|
||||
|
||||
func GetStringList(valuesCfg []string, valuesPath string) ([]string, error) {
|
||||
values := make([]string, 0, len(valuesCfg))
|
||||
|
||||
for _, value := range valuesCfg {
|
||||
valueTrimmed := strings.TrimSpace(value)
|
||||
if valueTrimmed == "" {
|
||||
continue
|
||||
}
|
||||
values = append(values, valueTrimmed)
|
||||
}
|
||||
|
||||
if valuesPath == "" {
|
||||
return values, nil
|
||||
}
|
||||
|
||||
contents, err := ReadFile(valuesPath)
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
|
||||
values = append(values, ParseNonEmptyLines(contents)...)
|
||||
return values, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package utils_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -56,3 +57,33 @@ func TestCompileUserEmail(t *testing.T) {
|
||||
// Test with invalid email
|
||||
assert.Equal(t, "user@example.com", utils.CompileUserEmail("user", "example.com"))
|
||||
}
|
||||
|
||||
func TestParseNonEmptyLines(t *testing.T) {
|
||||
lines := utils.ParseNonEmptyLines(" first@example.com \n\n second@example.com \n \n")
|
||||
|
||||
assert.Equal(t, []string{"first@example.com", "second@example.com"}, lines)
|
||||
}
|
||||
|
||||
func TestGetStringList(t *testing.T) {
|
||||
file, err := os.Create("/tmp/tinyauth_list_test_file")
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = file.WriteString(" third@example.com \n\n fourth@example.com \n")
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = file.Close()
|
||||
assert.NoError(t, err)
|
||||
defer os.Remove("/tmp/tinyauth_list_test_file")
|
||||
|
||||
values, err := utils.GetStringList([]string{" first@example.com ", "", "second@example.com"}, "/tmp/tinyauth_list_test_file")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{"first@example.com", "second@example.com", "third@example.com", "fourth@example.com"}, values)
|
||||
|
||||
values, err = utils.GetStringList(nil, "")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{}, values)
|
||||
|
||||
values, err = utils.GetStringList(nil, "/tmp/non_existing_list_file")
|
||||
assert.ErrorContains(t, err, "no such file or directory")
|
||||
assert.Equal(t, []string{}, values)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ func ParseUsers(usersStr []string, userAttributes map[string]model.UserAttribute
|
||||
var users []model.LocalUser
|
||||
|
||||
if len(usersStr) == 0 {
|
||||
return &users, nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
for _, user := range usersStr {
|
||||
@@ -34,32 +34,9 @@ func ParseUsers(usersStr []string, userAttributes map[string]model.UserAttribute
|
||||
}
|
||||
|
||||
func GetUsers(usersCfg []string, usersPath string, userAttributes map[string]model.UserAttributes) (*[]model.LocalUser, error) {
|
||||
var usersStr []string
|
||||
|
||||
if len(usersCfg) == 0 && usersPath == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if len(usersCfg) > 0 {
|
||||
usersStr = append(usersStr, usersCfg...)
|
||||
}
|
||||
|
||||
if usersPath != "" {
|
||||
contents, err := ReadFile(usersPath)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lines := strings.SplitSeq(contents, "\n")
|
||||
|
||||
for line := range lines {
|
||||
lineTrimmed := strings.TrimSpace(line)
|
||||
if lineTrimmed == "" {
|
||||
continue
|
||||
}
|
||||
usersStr = append(usersStr, lineTrimmed)
|
||||
}
|
||||
usersStr, err := GetStringList(usersCfg, usersPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ParseUsers(usersStr, userAttributes)
|
||||
|
||||
Reference in New Issue
Block a user