Compare commits

...

3 Commits

Author SHA1 Message Date
Stavros
ec67ea3807 refactor: detect if using browser or headless client for better responses 2025-03-10 17:02:23 +02:00
Stavros
3649d0d84e fix: allow oauth resource when oauth whitelist is empty 2025-03-10 16:22:32 +02:00
Stavros
c0ffe3faf4 refactor: release multiple semver tags 2025-03-10 16:02:48 +02:00
4 changed files with 32 additions and 20 deletions

View File

@@ -125,9 +125,8 @@ jobs:
with: with:
images: ghcr.io/${{ github.repository_owner }}/tinyauth images: ghcr.io/${{ github.repository_owner }}/tinyauth
tags: | tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}} type=semver,pattern={{version}}
type=semver,pattern={{major}}
type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}}.{{minor}}
- name: Create manifest list and push - name: Create manifest list and push

View File

@@ -8,12 +8,12 @@ services:
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
nginx: whoami:
container_name: nginx container_name: whoami
image: nginx:latest image: traefik/whoami:latest
labels: labels:
traefik.enable: true traefik.enable: true
traefik.http.routers.nginx.rule: Host(`nginx.dev.local`) traefik.http.routers.nginx.rule: Host(`whoami.dev.local`)
traefik.http.services.nginx.loadbalancer.server.port: 80 traefik.http.services.nginx.loadbalancer.server.port: 80
traefik.http.routers.nginx.middlewares: tinyauth traefik.http.routers.nginx.middlewares: tinyauth

View File

@@ -131,18 +131,24 @@ func (api *API) SetupRoutes() {
return return
} }
log.Debug().Interface("proxy", proxy.Proxy).Msg("Got proxy") // Check if the request is coming from a browser (tools like curl/bruno use */* and they don't include the text/html)
isBrowser := strings.Contains(c.Request.Header.Get("Accept"), "text/html")
// Check if using basic auth if isBrowser {
_, _, basicAuth := c.Request.BasicAuth() log.Debug().Msg("Request is most likely coming from a browser")
} else {
log.Debug().Msg("Request is most likely not coming from a browser")
}
log.Debug().Interface("proxy", proxy.Proxy).Msg("Got proxy")
// Check if auth is enabled // Check if auth is enabled
authEnabled, authEnabledErr := api.Auth.AuthEnabled(c) authEnabled, authEnabledErr := api.Auth.AuthEnabled(c)
// Handle error // Handle error
if authEnabledErr != nil { if authEnabledErr != nil {
// Return 500 if nginx is the proxy or if the request is using basic auth // Return 500 if nginx is the proxy or if the request is not coming from a browser
if proxy.Proxy == "nginx" || basicAuth { if proxy.Proxy == "nginx" || !isBrowser {
log.Error().Err(authEnabledErr).Msg("Failed to check if auth is enabled") log.Error().Err(authEnabledErr).Msg("Failed to check if auth is enabled")
c.JSON(500, gin.H{ c.JSON(500, gin.H{
"status": 500, "status": 500,
@@ -186,8 +192,8 @@ func (api *API) SetupRoutes() {
// Check if there was an error // Check if there was an error
if appAllowedErr != nil { if appAllowedErr != nil {
// Return 500 if nginx is the proxy or if the request is using basic auth // Return 500 if nginx is the proxy or if the request is not coming from a browser
if proxy.Proxy == "nginx" || basicAuth { if proxy.Proxy == "nginx" || !isBrowser {
log.Error().Err(appAllowedErr).Msg("Failed to check if app is allowed") log.Error().Err(appAllowedErr).Msg("Failed to check if app is allowed")
c.JSON(500, gin.H{ c.JSON(500, gin.H{
"status": 500, "status": 500,
@@ -208,9 +214,11 @@ func (api *API) SetupRoutes() {
if !appAllowed { if !appAllowed {
log.Warn().Str("username", userContext.Username).Str("host", host).Msg("User not allowed") log.Warn().Str("username", userContext.Username).Str("host", host).Msg("User not allowed")
// Return 401 if nginx is the proxy or if the request is using an Authorization header // Set WWW-Authenticate header
if proxy.Proxy == "nginx" || basicAuth {
c.Header("WWW-Authenticate", "Basic realm=\"tinyauth\"") c.Header("WWW-Authenticate", "Basic realm=\"tinyauth\"")
// Return 401 if nginx is the proxy or if the request is not coming from a browser
if proxy.Proxy == "nginx" || !isBrowser {
c.JSON(401, gin.H{ c.JSON(401, gin.H{
"status": 401, "status": 401,
"message": "Unauthorized", "message": "Unauthorized",
@@ -252,9 +260,11 @@ func (api *API) SetupRoutes() {
// The user is not logged in // The user is not logged in
log.Debug().Msg("Unauthorized") log.Debug().Msg("Unauthorized")
// Return 401 if nginx is the proxy or if the request is using an Authorization header // Set www-authenticate header
if proxy.Proxy == "nginx" || basicAuth {
c.Header("WWW-Authenticate", "Basic realm=\"tinyauth\"") c.Header("WWW-Authenticate", "Basic realm=\"tinyauth\"")
// Return 401 if nginx is the proxy or if the request is not coming from a browser
if proxy.Proxy == "nginx" || !isBrowser {
c.JSON(401, gin.H{ c.JSON(401, gin.H{
"status": 401, "status": 401,
"message": "Unauthorized", "message": "Unauthorized",

View File

@@ -162,7 +162,10 @@ func (auth *Auth) ResourceAllowed(c *gin.Context, context types.UserContext) (bo
// Check if resource is allowed // Check if resource is allowed
allowed, allowedErr := auth.Docker.ContainerAction(appId, func(labels types.TinyauthLabels) (bool, error) { allowed, allowedErr := auth.Docker.ContainerAction(appId, func(labels types.TinyauthLabels) (bool, error) {
// If the container has an oauth whitelist, check if the user is in it // If the container has an oauth whitelist, check if the user is in it
if context.OAuth && len(labels.OAuthWhitelist) != 0 { if context.OAuth {
if len(labels.OAuthWhitelist) == 0 {
return true, nil
}
log.Debug().Msg("Checking OAuth whitelist") log.Debug().Msg("Checking OAuth whitelist")
if slices.Contains(labels.OAuthWhitelist, context.Username) { if slices.Contains(labels.OAuthWhitelist, context.Username) {
return true, nil return true, nil