Merge branch 'main' into refactor/sqlc

This commit is contained in:
Stavros
2025-12-30 18:34:42 +02:00
53 changed files with 654 additions and 279 deletions

View File

@@ -0,0 +1 @@
ALTER TABLE "sessions" DROP COLUMN "oauth_sub";

View File

@@ -0,0 +1 @@
ALTER TABLE "sessions" ADD COLUMN "oauth_sub" TEXT;

View File

@@ -11,10 +11,11 @@ import (
"sort"
"strings"
"time"
"tinyauth/internal/config"
"tinyauth/internal/controller"
"tinyauth/internal/repository"
"tinyauth/internal/utils"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/controller"
"github.com/steveiliop56/tinyauth/internal/repository"
"github.com/steveiliop56/tinyauth/internal/utils"
"github.com/rs/zerolog/log"
)

View File

@@ -3,8 +3,9 @@ package bootstrap
import (
"fmt"
"strings"
"tinyauth/internal/controller"
"tinyauth/internal/middleware"
"github.com/steveiliop56/tinyauth/internal/controller"
"github.com/steveiliop56/tinyauth/internal/middleware"
"github.com/gin-gonic/gin"
)

View File

@@ -1,8 +1,8 @@
package bootstrap
import (
"tinyauth/internal/repository"
"tinyauth/internal/service"
"github.com/steveiliop56/tinyauth/internal/repository"
"github.com/steveiliop56/tinyauth/internal/service"
"github.com/rs/zerolog/log"
)
@@ -45,7 +45,7 @@ func (app *BootstrapApp) initServices(queries *repository.Queries) (Services, er
services.dockerService = dockerService
accessControlsService := service.NewAccessControlsService(dockerService)
accessControlsService := service.NewAccessControlsService(dockerService, app.config.Apps)
err = accessControlsService.Init()

View File

@@ -25,6 +25,7 @@ type Config struct {
LogJSON bool `description:"Enable JSON formatted logs." yaml:"logJSON"`
Server ServerConfig `description:"Server configuration." yaml:"server"`
Auth AuthConfig `description:"Authentication configuration." yaml:"auth"`
Apps map[string]App `description:"Application ACLs configuration." yaml:"apps"`
OAuth OAuthConfig `description:"OAuth configuration." yaml:"oauth"`
UI UIConfig `description:"UI customization." yaml:"ui"`
Ldap LdapConfig `description:"LDAP configuration." yaml:"ldap"`
@@ -79,6 +80,7 @@ const DefaultNamePrefix = "TINYAUTH_"
// OAuth/OIDC config
type Claims struct {
Sub string `json:"sub"`
Name string `json:"name"`
Email string `json:"email"`
PreferredUsername string `json:"preferred_username"`
@@ -125,6 +127,7 @@ type SessionCookie struct {
TotpPending bool
OAuthGroups string
OAuthName string
OAuthSub string
}
type UserContext struct {
@@ -138,6 +141,7 @@ type UserContext struct {
OAuthGroups string
TotpEnabled bool
OAuthName string
OAuthSub string
}
// API responses and queries
@@ -153,61 +157,55 @@ type RedirectQuery struct {
RedirectURI string `url:"redirect_uri"`
}
// Labels
// ACLs
type Apps struct {
Apps map[string]App
Apps map[string]App `description:"App ACLs configuration." yaml:"apps"`
}
type App struct {
Config AppConfig
Users AppUsers
OAuth AppOAuth
IP AppIP
Response AppResponse
Path AppPath
Config AppConfig `description:"App configuration." yaml:"config"`
Users AppUsers `description:"User access configuration." yaml:"users"`
OAuth AppOAuth `description:"OAuth access configuration." yaml:"oauth"`
IP AppIP `description:"IP access configuration." yaml:"ip"`
Response AppResponse `description:"Response customization." yaml:"response"`
Path AppPath `description:"Path access configuration." yaml:"path"`
}
type AppConfig struct {
Domain string
Domain string `description:"The domain of the app." yaml:"domain"`
}
type AppUsers struct {
Allow string
Block string
Allow string `description:"Comma-separated list of allowed users." yaml:"allow"`
Block string `description:"Comma-separated list of blocked users." yaml:"block"`
}
type AppOAuth struct {
Whitelist string
Groups string
Whitelist string `description:"Comma-separated list of allowed OAuth groups." yaml:"whitelist"`
Groups string `description:"Comma-separated list of required OAuth groups." yaml:"groups"`
}
type AppIP struct {
Allow []string
Block []string
Bypass []string
Allow []string `description:"List of allowed IPs or CIDR ranges." yaml:"allow"`
Block []string `description:"List of blocked IPs or CIDR ranges." yaml:"block"`
Bypass []string `description:"List of IPs or CIDR ranges that bypass authentication." yaml:"bypass"`
}
type AppResponse struct {
Headers []string
BasicAuth AppBasicAuth
Headers []string `description:"Custom headers to add to the response." yaml:"headers"`
BasicAuth AppBasicAuth `description:"Basic authentication for the app." yaml:"basicAuth"`
}
type AppBasicAuth struct {
Username string
Password string
PasswordFile string
Username string `description:"Basic auth username." yaml:"username"`
Password string `description:"Basic auth password." yaml:"password"`
PasswordFile string `description:"Path to the file containing the basic auth password." yaml:"passwordFile"`
}
type AppPath struct {
Allow string
Block string
}
// Flags
type Providers struct {
Providers map[string]OAuthServiceConfig
Allow string `description:"Comma-separated list of allowed paths." yaml:"allow"`
Block string `description:"Comma-separated list of blocked paths." yaml:"block"`
}
// API server

View File

@@ -3,7 +3,8 @@ package controller
import (
"fmt"
"net/url"
"tinyauth/internal/utils"
"github.com/steveiliop56/tinyauth/internal/utils"
"github.com/gin-gonic/gin"
"github.com/rs/zerolog/log"
@@ -20,6 +21,7 @@ type UserContextResponse struct {
OAuth bool `json:"oauth"`
TotpPending bool `json:"totpPending"`
OAuthName string `json:"oauthName"`
OAuthSub string `json:"oauthSub"`
}
type AppContextResponse struct {
@@ -88,6 +90,7 @@ func (controller *ContextController) userContextHandler(c *gin.Context) {
OAuth: context.OAuth,
TotpPending: context.TotpPending,
OAuthName: context.OAuthName,
OAuthSub: context.OAuthSub,
}
if err != nil {

View File

@@ -4,8 +4,9 @@ import (
"encoding/json"
"net/http/httptest"
"testing"
"tinyauth/internal/config"
"tinyauth/internal/controller"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/controller"
"github.com/gin-gonic/gin"
"gotest.tools/v3/assert"
@@ -43,6 +44,7 @@ var userContext = config.UserContext{
TotpPending: false,
OAuthGroups: "",
TotpEnabled: false,
OAuthSub: "",
}
func setupContextController(middlewares *[]gin.HandlerFunc) (*gin.Engine, *httptest.ResponseRecorder) {

View File

@@ -5,9 +5,10 @@ import (
"net/http"
"strings"
"time"
"tinyauth/internal/config"
"tinyauth/internal/service"
"tinyauth/internal/utils"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/service"
"github.com/steveiliop56/tinyauth/internal/utils"
"github.com/gin-gonic/gin"
"github.com/google/go-querystring/query"
@@ -196,6 +197,7 @@ func (controller *OAuthController) oauthCallbackHandler(c *gin.Context) {
Provider: req.Provider,
OAuthGroups: utils.CoalesceToString(user.Groups),
OAuthName: service.GetName(),
OAuthSub: user.Sub,
}
log.Trace().Interface("session_cookie", sessionCookie).Msg("Creating session cookie")

View File

@@ -5,9 +5,10 @@ import (
"net/http"
"slices"
"strings"
"tinyauth/internal/config"
"tinyauth/internal/service"
"tinyauth/internal/utils"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/service"
"github.com/steveiliop56/tinyauth/internal/utils"
"github.com/gin-gonic/gin"
"github.com/google/go-querystring/query"
@@ -42,7 +43,8 @@ func NewProxyController(config ProxyControllerConfig, router *gin.RouterGroup, a
func (controller *ProxyController) SetupRoutes() {
proxyGroup := controller.router.Group("/auth")
proxyGroup.Any("/:proxy", controller.proxyHandler)
proxyGroup.GET("/:proxy", controller.proxyHandler)
proxyGroup.POST("/:proxy", controller.proxyHandler)
}
func (controller *ProxyController) proxyHandler(c *gin.Context) {
@@ -67,15 +69,6 @@ func (controller *ProxyController) proxyHandler(c *gin.Context) {
return
}
if req.Proxy != "envoy" && c.Request.Method != http.MethodGet {
log.Warn().Str("method", c.Request.Method).Msg("Invalid method for proxy")
c.JSON(405, gin.H{
"status": 405,
"message": "Method Not Allowed",
})
return
}
isBrowser := strings.Contains(c.Request.Header.Get("Accept"), "text/html")
if isBrowser {
@@ -246,6 +239,7 @@ func (controller *ProxyController) proxyHandler(c *gin.Context) {
c.Header("Remote-Name", utils.SanitizeHeader(userContext.Name))
c.Header("Remote-Email", utils.SanitizeHeader(userContext.Email))
c.Header("Remote-Groups", utils.SanitizeHeader(userContext.OAuthGroups))
c.Header("Remote-Sub", utils.SanitizeHeader(userContext.OAuthSub))
controller.setHeaders(c, acls)

View File

@@ -3,9 +3,10 @@ package controller_test
import (
"net/http/httptest"
"testing"
"tinyauth/internal/config"
"tinyauth/internal/controller"
"tinyauth/internal/service"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/controller"
"github.com/steveiliop56/tinyauth/internal/service"
"github.com/gin-gonic/gin"
"gotest.tools/v3/assert"
@@ -40,7 +41,7 @@ func setupProxyController(t *testing.T, middlewares *[]gin.HandlerFunc) (*gin.En
assert.NilError(t, dockerService.Init())
// Access controls
accessControlsService := service.NewAccessControlsService(dockerService)
accessControlsService := service.NewAccessControlsService(dockerService, map[string]config.App{})
assert.NilError(t, accessControlsService.Init())
@@ -80,13 +81,6 @@ func TestProxyHandler(t *testing.T) {
assert.Equal(t, 400, recorder.Code)
// Test invalid method
recorder = httptest.NewRecorder()
req = httptest.NewRequest("POST", "/api/auth/traefik", nil)
router.ServeHTTP(recorder, req)
assert.Equal(t, 405, recorder.Code)
// Test logged out user (traefik/caddy)
recorder = httptest.NewRecorder()
req = httptest.NewRequest("GET", "/api/auth/traefik", nil)

View File

@@ -4,7 +4,8 @@ import (
"net/http/httptest"
"os"
"testing"
"tinyauth/internal/controller"
"github.com/steveiliop56/tinyauth/internal/controller"
"github.com/gin-gonic/gin"
"gotest.tools/v3/assert"

View File

@@ -3,9 +3,10 @@ package controller
import (
"fmt"
"strings"
"tinyauth/internal/config"
"tinyauth/internal/service"
"tinyauth/internal/utils"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/service"
"github.com/steveiliop56/tinyauth/internal/utils"
"github.com/gin-gonic/gin"
"github.com/pquerna/otp/totp"

View File

@@ -7,9 +7,10 @@ import (
"strings"
"testing"
"time"
"tinyauth/internal/config"
"tinyauth/internal/controller"
"tinyauth/internal/service"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/controller"
"github.com/steveiliop56/tinyauth/internal/service"
"github.com/gin-gonic/gin"
"github.com/pquerna/otp/totp"

View File

@@ -3,9 +3,10 @@ package middleware
import (
"fmt"
"strings"
"tinyauth/internal/config"
"tinyauth/internal/service"
"tinyauth/internal/utils"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/service"
"github.com/steveiliop56/tinyauth/internal/utils"
"github.com/gin-gonic/gin"
"github.com/rs/zerolog/log"
@@ -65,6 +66,7 @@ func (m *ContextMiddleware) Middleware() gin.HandlerFunc {
goto basic
}
m.auth.RefreshSessionCookie(c)
c.Set("context", &config.UserContext{
Username: cookie.Username,
Name: cookie.Name,
@@ -89,6 +91,7 @@ func (m *ContextMiddleware) Middleware() gin.HandlerFunc {
goto basic
}
m.auth.RefreshSessionCookie(c)
c.Set("context", &config.UserContext{
Username: cookie.Username,
Name: cookie.Name,
@@ -96,6 +99,7 @@ func (m *ContextMiddleware) Middleware() gin.HandlerFunc {
Provider: cookie.Provider,
OAuthGroups: cookie.OAuthGroups,
OAuthName: cookie.OAuthName,
OAuthSub: cookie.OAuthSub,
IsLoggedIn: true,
OAuth: true,
})

View File

@@ -7,7 +7,8 @@ import (
"os"
"strings"
"time"
"tinyauth/internal/assets"
"github.com/steveiliop56/tinyauth/internal/assets"
"github.com/gin-gonic/gin"
)

View File

@@ -0,0 +1,14 @@
package model
type Session struct {
UUID string `gorm:"column:uuid;primaryKey"`
Username string `gorm:"column:username"`
Email string `gorm:"column:email"`
Name string `gorm:"column:name"`
Provider string `gorm:"column:provider"`
TOTPPending bool `gorm:"column:totp_pending"`
OAuthGroups string `gorm:"column:oauth_groups"`
Expiry int64 `gorm:"column:expiry"`
OAuthName string `gorm:"column:oauth_name"`
OAuthSub string `gorm:"column:oauth_sub"`
}

View File

@@ -1,122 +1,54 @@
package service
import (
"tinyauth/internal/config"
"errors"
"strings"
"github.com/rs/zerolog/log"
"github.com/steveiliop56/tinyauth/internal/config"
)
/*
Environment variable/flag based ACLs are disabled until v5 due to a technical challenge
with the current parsing logic.
The current parser works for simple OAuth provider configs like:
- PROVIDERS_MY_AMAZING_PROVIDER_CLIENT_ID
However, it breaks down when handling nested structs required for ACLs. The custom parsing
solution that worked for v4 OAuth providers is incompatible with the ACL parsing logic,
making the codebase unmaintainable and fragile.
A solution is being considered for v5 that would standardize the format to something like:
- TINYAUTH_PROVIDERS_GOOGLE_CLIENTSECRET
- TINYAUTH_APPS_MYAPP_CONFIG_DOMAIN
This would allow the Traefik parser to handle everything consistently, but requires a
config migration. Until this is resolved, environment-based ACLs are disabled and only
Docker label-based ACLs are supported.
See: https://discord.com/channels/1337450123600465984/1337459086270271538/1434986689935179838 for more information
*/
type AccessControlsService struct {
docker *DockerService
// envACLs config.Apps
static map[string]config.App
}
func NewAccessControlsService(docker *DockerService) *AccessControlsService {
func NewAccessControlsService(docker *DockerService, static map[string]config.App) *AccessControlsService {
return &AccessControlsService{
docker: docker,
static: static,
}
}
func (acls *AccessControlsService) Init() error {
// acls.envACLs = config.Apps{}
// env := os.Environ()
// appEnvVars := []string{}
// for _, e := range env {
// if strings.HasPrefix(e, "TINYAUTH_APPS_") {
// appEnvVars = append(appEnvVars, e)
// }
// }
// err := acls.loadEnvACLs(appEnvVars)
// if err != nil {
// return err
// }
// return nil
return nil
return nil // No initialization needed
}
// func (acls *AccessControlsService) loadEnvACLs(appEnvVars []string) error {
// if len(appEnvVars) == 0 {
// return nil
// }
func (acls *AccessControlsService) lookupStaticACLs(domain string) (config.App, error) {
for app, config := range acls.static {
if config.Config.Domain == domain {
log.Debug().Str("name", app).Msg("Found matching container by domain")
return config, nil
}
// envAcls := map[string]string{}
if strings.SplitN(domain, ".", 2)[0] == app {
log.Debug().Str("name", app).Msg("Found matching container by app name")
return config, nil
}
}
return config.App{}, errors.New("no results")
}
// for _, e := range appEnvVars {
// parts := strings.SplitN(e, "=", 2)
// if len(parts) != 2 {
// continue
// }
func (acls *AccessControlsService) GetAccessControls(domain string) (config.App, error) {
// First check in the static config
app, err := acls.lookupStaticACLs(domain)
// key := parts[0]
// key = strings.ToLower(key)
// key = strings.ReplaceAll(key, "_", ".")
// value := parts[1]
// envAcls[key] = value
// }
// apps, err := decoders.DecodeLabels(envAcls)
// if err != nil {
// return err
// }
// acls.envACLs = apps
// return nil
// }
// func (acls *AccessControlsService) lookupEnvACLs(appDomain string) *config.App {
// if len(acls.envACLs.Apps) == 0 {
// return nil
// }
// for appName, appACLs := range acls.envACLs.Apps {
// if appACLs.Config.Domain == appDomain {
// return &appACLs
// }
// if strings.SplitN(appDomain, ".", 2)[0] == appName {
// return &appACLs
// }
// }
// return nil
// }
func (acls *AccessControlsService) GetAccessControls(appDomain string) (config.App, error) {
// First check environment variables
// envACLs := acls.lookupEnvACLs(appDomain)
// if envACLs != nil {
// log.Debug().Str("domain", appDomain).Msg("Found matching access controls in environment variables")
// return *envACLs, nil
// }
if err == nil {
log.Debug().Msg("Using ACls from static configuration")
return app, nil
}
// Fallback to Docker labels
return acls.docker.GetLabels(appDomain)
log.Debug().Msg("Falling back to Docker labels for ACLs")
return acls.docker.GetLabels(domain)
}

View File

@@ -9,9 +9,10 @@ import (
"strings"
"sync"
"time"
"tinyauth/internal/config"
"tinyauth/internal/repository"
"tinyauth/internal/utils"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/model"
"github.com/steveiliop56/tinyauth/internal/utils"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
@@ -57,7 +58,6 @@ func NewAuthService(config AuthServiceConfig, docker *DockerService, ldap *LdapS
}
func (auth *AuthService) Init() error {
auth.ctx = context.Background()
return nil
}
@@ -215,6 +215,7 @@ func (auth *AuthService) CreateSessionCookie(c *gin.Context, data *config.Sessio
OAuthGroups: data.OAuthGroups,
Expiry: time.Now().Add(time.Duration(expiry) * time.Second).Unix(),
OAuthName: data.OAuthName,
OAuthSub: data.OAuthSub,
}
_, err = auth.queries.CreateSession(c, session)
@@ -228,6 +229,40 @@ func (auth *AuthService) CreateSessionCookie(c *gin.Context, data *config.Sessio
return nil
}
func (auth *AuthService) RefreshSessionCookie(c *gin.Context) error {
cookie, err := c.Cookie(auth.config.SessionCookieName)
if err != nil {
return err
}
session, err := gorm.G[model.Session](auth.database).Where("uuid = ?", cookie).First(c)
if err != nil {
return err
}
currentTime := time.Now().Unix()
if session.Expiry-currentTime > int64(time.Hour.Seconds()) {
return nil
}
newExpiry := currentTime + int64(time.Hour.Seconds())
_, err = gorm.G[model.Session](auth.database).Where("uuid = ?", cookie).Updates(c, model.Session{
Expiry: newExpiry,
})
if err != nil {
return err
}
c.SetCookie(auth.config.SessionCookieName, cookie, int(time.Hour.Seconds()), "/", fmt.Sprintf(".%s", auth.config.CookieDomain), auth.config.SecureCookie, true)
return nil
}
func (auth *AuthService) DeleteSessionCookie(c *gin.Context) error {
cookie, err := c.Cookie(auth.config.SessionCookieName)
@@ -282,6 +317,7 @@ func (auth *AuthService) GetSessionCookie(c *gin.Context) (config.SessionCookie,
TotpPending: session.TotpPending,
OAuthGroups: session.OAuthGroups,
OAuthName: session.OAuthName,
OAuthSub: session.OAuthSub,
}, nil
}

View File

@@ -0,0 +1,92 @@
package service
import (
"database/sql"
"fmt"
"os"
"path/filepath"
"github.com/steveiliop56/tinyauth/internal/assets"
"github.com/glebarez/sqlite"
"github.com/golang-migrate/migrate/v4"
sqliteMigrate "github.com/golang-migrate/migrate/v4/database/sqlite3"
"github.com/golang-migrate/migrate/v4/source/iofs"
"gorm.io/gorm"
)
type DatabaseServiceConfig struct {
DatabasePath string
}
type DatabaseService struct {
config DatabaseServiceConfig
database *gorm.DB
}
func NewDatabaseService(config DatabaseServiceConfig) *DatabaseService {
return &DatabaseService{
config: config,
}
}
func (ds *DatabaseService) Init() error {
dbPath := ds.config.DatabasePath
if dbPath == "" {
dbPath = "/data/tinyauth.db"
}
dir := filepath.Dir(dbPath)
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("failed to create database directory %s: %w", dir, err)
}
gormDB, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{})
if err != nil {
return err
}
sqlDB, err := gormDB.DB()
if err != nil {
return err
}
sqlDB.SetMaxOpenConns(1)
err = ds.migrateDatabase(sqlDB)
if err != nil && err != migrate.ErrNoChange {
return err
}
ds.database = gormDB
return nil
}
func (ds *DatabaseService) migrateDatabase(sqlDB *sql.DB) error {
data, err := iofs.New(assets.Migrations, "migrations")
if err != nil {
return err
}
target, err := sqliteMigrate.WithInstance(sqlDB, &sqliteMigrate.Config{})
if err != nil {
return err
}
migrator, err := migrate.NewWithInstance("iofs", data, "tinyauth", target)
if err != nil {
return err
}
return migrator.Up()
}
func (ds *DatabaseService) GetDatabase() *gorm.DB {
return ds.database
}

View File

@@ -3,8 +3,9 @@ package service
import (
"context"
"strings"
"tinyauth/internal/config"
"tinyauth/internal/utils/decoders"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/utils/decoders"
container "github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"

View File

@@ -10,7 +10,8 @@ import (
"io"
"net/http"
"time"
"tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/rs/zerolog/log"
"golang.org/x/oauth2"

View File

@@ -9,8 +9,10 @@ import (
"fmt"
"io"
"net/http"
"strconv"
"time"
"tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/config"
"golang.org/x/oauth2"
"golang.org/x/oauth2/endpoints"
@@ -26,6 +28,7 @@ type GithubEmailResponse []struct {
type GithubUserInfoResponse struct {
Login string `json:"login"`
Name string `json:"name"`
ID int `json:"id"`
}
type GithubOAuthService struct {
@@ -171,6 +174,7 @@ func (github *GithubOAuthService) Userinfo() (config.Claims, error) {
user.PreferredUsername = userInfo.Login
user.Name = userInfo.Name
user.Sub = strconv.Itoa(userInfo.ID)
return user, nil
}

View File

@@ -10,18 +10,14 @@ import (
"net/http"
"strings"
"time"
"tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/config"
"golang.org/x/oauth2"
"golang.org/x/oauth2/endpoints"
)
var GoogleOAuthScopes = []string{"https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile"}
type GoogleUserInfoResponse struct {
Email string `json:"email"`
Name string `json:"name"`
}
var GoogleOAuthScopes = []string{"openid", "email", "profile"}
type GoogleOAuthService struct {
config oauth2.Config
@@ -90,7 +86,7 @@ func (google *GoogleOAuthService) Userinfo() (config.Claims, error) {
client := google.config.Client(google.context, google.token)
res, err := client.Get("https://www.googleapis.com/userinfo/v2/me")
res, err := client.Get("https://openidconnect.googleapis.com/v1/userinfo")
if err != nil {
return config.Claims{}, err
}
@@ -105,16 +101,12 @@ func (google *GoogleOAuthService) Userinfo() (config.Claims, error) {
return config.Claims{}, err
}
var userInfo GoogleUserInfoResponse
err = json.Unmarshal(body, &userInfo)
err = json.Unmarshal(body, &user)
if err != nil {
return config.Claims{}, err
}
user.PreferredUsername = strings.Split(userInfo.Email, "@")[0]
user.Name = userInfo.Name
user.Email = userInfo.Email
user.PreferredUsername = strings.SplitN(user.Email, "@", 2)[0]
return user, nil
}

View File

@@ -2,7 +2,8 @@ package service
import (
"errors"
"tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/rs/zerolog/log"
"golang.org/x/exp/slices"

View File

@@ -5,7 +5,8 @@ import (
"net"
"net/url"
"strings"
"tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/gin-gonic/gin"
"github.com/weppos/publicsuffix-go/publicsuffix"

View File

@@ -2,8 +2,9 @@ package utils_test
import (
"testing"
"tinyauth/internal/config"
"tinyauth/internal/utils"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/utils"
"github.com/gin-gonic/gin"
"gotest.tools/v3/assert"

View File

@@ -2,8 +2,9 @@ package decoders_test
import (
"testing"
"tinyauth/internal/config"
"tinyauth/internal/utils/decoders"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/utils/decoders"
"gotest.tools/v3/assert"
)

View File

@@ -2,7 +2,8 @@ package utils_test
import (
"testing"
"tinyauth/internal/utils"
"github.com/steveiliop56/tinyauth/internal/utils"
"gotest.tools/v3/assert"
)

View File

@@ -3,7 +3,8 @@ package loaders
import (
"fmt"
"os"
"tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/config"
"github.com/traefik/paerser/cli"
"github.com/traefik/paerser/env"

View File

@@ -3,7 +3,8 @@ package utils_test
import (
"os"
"testing"
"tinyauth/internal/utils"
"github.com/steveiliop56/tinyauth/internal/utils"
"gotest.tools/v3/assert"
)

View File

@@ -2,7 +2,8 @@ package utils_test
import (
"testing"
"tinyauth/internal/utils"
"github.com/steveiliop56/tinyauth/internal/utils"
"gotest.tools/v3/assert"
)

View File

@@ -3,7 +3,8 @@ package utils
import (
"errors"
"strings"
"tinyauth/internal/config"
"github.com/steveiliop56/tinyauth/internal/config"
)
func ParseUsers(users string) ([]config.User, error) {

View File

@@ -3,7 +3,8 @@ package utils_test
import (
"os"
"testing"
"tinyauth/internal/utils"
"github.com/steveiliop56/tinyauth/internal/utils"
"gotest.tools/v3/assert"
)