Compare commits

...

9 Commits

Author SHA1 Message Date
Stavros
ada3531565 chore: use correct timezone in discohook 2025-03-10 21:25:49 +02:00
Stavros
939ed26fd0 chore: update discohook date 2025-03-10 21:22:01 +02:00
Stavros
da0641c115 chore: migrate to new domain 2025-03-10 21:21:31 +02:00
Stavros
753b95baff docs: change warning to note in contributing 2025-03-10 18:50:43 +02:00
Stavros
9dd9829058 docs: update contributing 2025-03-10 18:47:54 +02:00
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
Stavros
ad718d3ef8 refactor: migrate release workflow to native runners 2025-03-09 19:24:52 +02:00
13 changed files with 187 additions and 339 deletions

View File

@@ -1,58 +0,0 @@
name: Alpha Release
on:
workflow_dispatch:
inputs:
alpha:
description: "Alpha version (e.g. 1, 2, 3)"
required: true
jobs:
get-tag:
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.tag.outputs.name }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Get tag
id: tag
run: echo "name=$(cat internal/assets/version)-alpha.${{ github.event.inputs.alpha }}" >> $GITHUB_OUTPUT
build-docker:
needs: get-tag
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
push: true
platforms: linux/arm64, linux/amd64
tags: ghcr.io/${{ github.repository_owner }}/tinyauth:${{ needs.get-tag.outputs.tag }}
alpha-release:
needs: [get-tag, build-docker]
runs-on: ubuntu-latest
steps:
- name: Create alpha release
uses: softprops/action-gh-release@v2
with:
prerelease: true
tag_name: ${{ needs.get-tag.outputs.tag }}

View File

@@ -1,58 +0,0 @@
name: Beta Release
on:
workflow_dispatch:
inputs:
alpha:
description: "Beta version (e.g. 1, 2, 3)"
required: true
jobs:
get-tag:
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.tag.outputs.name }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Get tag
id: tag
run: echo "name=$(cat internal/assets/version)-beta.${{ github.event.inputs.alpha }}" >> $GITHUB_OUTPUT
build-docker:
needs: get-tag
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
push: true
platforms: linux/arm64, linux/amd64
tags: ghcr.io/${{ github.repository_owner }}/tinyauth:${{ needs.get-tag.outputs.tag }}
beta-release:
needs: [get-tag, build-docker]
runs-on: ubuntu-latest
steps:
- name: Create beta release
uses: softprops/action-gh-release@v2
with:
prerelease: true
tag_name: ${{ needs.get-tag.outputs.tag }}

View File

@@ -1,137 +0,0 @@
name: Experimental Build
on:
workflow_dispatch:
push:
tags:
- "v*"
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/tinyauth
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6
id: build
with:
platforms: linux/amd64
labels: ${{ steps.meta.outputs.labels }}
tags: ghcr.io/${{ github.repository_owner }}/tinyauth
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
- name: Export digest
run: |
mkdir -p ${{ runner.temp }}/digests
digest="${{ steps.build.outputs.digest }}"
touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-linux-amd64
path: ${{ runner.temp }}/digests/*
if-no-files-found: error
retention-days: 1
build-arm:
runs-on: ubuntu-24.04-arm
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/tinyauth
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6
id: build
with:
platforms: linux/arm64
labels: ${{ steps.meta.outputs.labels }}
tags: ghcr.io/${{ github.repository_owner }}/tinyauth
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
- name: Export digest
run: |
mkdir -p ${{ runner.temp }}/digests
digest="${{ steps.build.outputs.digest }}"
touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-linux-arm64
path: ${{ runner.temp }}/digests/*
if-no-files-found: error
retention-days: 1
merge:
runs-on: ubuntu-latest
needs:
- build
- build-arm
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: ${{ runner.temp }}/digests
pattern: digests-*
merge-multiple: true
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/tinyauth
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
- name: Create manifest list and push
working-directory: ${{ runner.temp }}/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf 'ghcr.io/${{ github.repository_owner }}/tinyauth@sha256:%s ' *)

View File

@@ -1,32 +1,22 @@
name: Release name: Release
on: on:
workflow_dispatch: workflow_dispatch:
push:
tags:
- "v*"
jobs: jobs:
get-tag: build:
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.tag.outputs.name }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Get tag
id: tag
run: echo "name=$(cat internal/assets/version)" >> $GITHUB_OUTPUT
build-docker:
needs: get-tag
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Set up QEMU - name: Docker meta
uses: docker/setup-qemu-action@v3 id: meta
uses: docker/metadata-action@v5
- name: Set up Docker Buildx with:
uses: docker/setup-buildx-action@v3 images: ghcr.io/${{ github.repository_owner }}/tinyauth
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
uses: docker/login-action@v3 uses: docker/login-action@v3
@@ -35,21 +25,112 @@ jobs:
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push - name: Build and push
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
id: build
with: with:
context: . platforms: linux/amd64
push: true labels: ${{ steps.meta.outputs.labels }}
platforms: linux/arm64, linux/amd64 tags: ghcr.io/${{ github.repository_owner }}/tinyauth
tags: ghcr.io/${{ github.repository_owner }}/tinyauth:${{ needs.get-tag.outputs.tag }}, ghcr.io/${{ github.repository_owner }}/tinyauth:latest outputs: type=image,push-by-digest=true,name-canonical=true,push=true
release: - name: Export digest
needs: [get-tag, build-docker] run: |
runs-on: ubuntu-latest mkdir -p ${{ runner.temp }}/digests
steps: digest="${{ steps.build.outputs.digest }}"
- name: Create release touch "${{ runner.temp }}/digests/${digest#sha256:}"
uses: softprops/action-gh-release@v2
- name: Upload digest
uses: actions/upload-artifact@v4
with: with:
prerelease: false name: digests-linux-amd64
make_latest: false path: ${{ runner.temp }}/digests/*
tag_name: ${{ needs.get-tag.outputs.tag }} if-no-files-found: error
retention-days: 1
build-arm:
runs-on: ubuntu-24.04-arm
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/tinyauth
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6
id: build
with:
platforms: linux/arm64
labels: ${{ steps.meta.outputs.labels }}
tags: ghcr.io/${{ github.repository_owner }}/tinyauth
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
- name: Export digest
run: |
mkdir -p ${{ runner.temp }}/digests
digest="${{ steps.build.outputs.digest }}"
touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-linux-arm64
path: ${{ runner.temp }}/digests/*
if-no-files-found: error
retention-days: 1
merge:
runs-on: ubuntu-latest
needs:
- build
- build-arm
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: ${{ runner.temp }}/digests
pattern: digests-*
merge-multiple: true
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/tinyauth
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}
type=semver,pattern={{major}}.{{minor}}
- name: Create manifest list and push
working-directory: ${{ runner.temp }}/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf 'ghcr.io/${{ github.repository_owner }}/tinyauth@sha256:%s ' *)

View File

@@ -1,6 +1,6 @@
# Contributing # Contributing
Contributing is relatively easy. Contributing is relatively easy, you just need to follow the steps carefully and you will be up and running with a development server in less than 5 minutes.
## Requirements ## Requirements
@@ -8,6 +8,7 @@ Contributing is relatively easy.
- Golang v1.23.2 and above - Golang v1.23.2 and above
- Git - Git
- Docker - Docker
- Make (not required but it will make your life easier)
## Cloning the repository ## Cloning the repository
@@ -20,48 +21,42 @@ cd tinyauth
## Install requirements ## Install requirements
Now it's time to install the requirements, firstly the Go ones: To install the requirements simply run:
```sh ```sh
go mod download make requirements
``` ```
And now the site ones: It will download all the node packages required by the frontend as well as all the go requirements.
```sh
cd site
bun i
```
## Developing locally ## Developing locally
In order to develop the app locally you need to build the frontend and copy it to the assets folder in order for Go to embed it and host it. In order to build the frontend run: In order to develop the app you need to firstly compile the frontend and then the go app. To avoid running the same commands over and over again you can just run:
```sh ```sh
cd site make run
bun run build
cd ..
``` ```
Copy it to the assets folder: This is the equivalent of `go run main.go`, if you would like to build a binary run:
```sh ```sh
rm -rf internal/assets/dist make build
cp -r site/dist internal/assets/dist
``` ```
Finally either run the app with: To avoid rebuilding the frontend every time you can run:
```sh ```sh
go run main.go make run-no-web
``` ```
Or build it with: And:
```sh ```sh
go build make build-no-web
``` ```
For these commands to succeed you must have built the frontend at least once.
> [!WARNING] > [!WARNING]
> Make sure you have set the environment variables when running outside of docker else the app will fail. > Make sure you have set the environment variables when running outside of docker else the app will fail.
@@ -70,8 +65,8 @@ go build
My recommended development method is docker so I can test that both my image works and that the app responds correctly to traefik. In my setup I have set these two DNS records in my DNS server: My recommended development method is docker so I can test that both my image works and that the app responds correctly to traefik. In my setup I have set these two DNS records in my DNS server:
``` ```
*.dev.local -> 127.0.0.1 *.dev.example.com -> 127.0.0.1
dev.local -> 127.0.0.1 dev.example.com -> 127.0.0.1
``` ```
Then I can just make sure the domains are correct in the example docker compose file and do: Then I can just make sure the domains are correct in the example docker compose file and do:
@@ -79,3 +74,6 @@ Then I can just make sure the domains are correct in the example docker compose
```sh ```sh
docker compose -f docker-compose.dev.yml up --build docker compose -f docker-compose.dev.yml up --build
``` ```
> [!NOTE]
> I would recommend copying the example `docker-compose.dev.yml` into a `docker-compose.test.yml` file, so as you don't accidentally commit any sensitive information.

View File

@@ -2,6 +2,11 @@
web: web:
cd site; bun run build cd site; bun run build
# Requirements
requirements:
cd site; bun install
go mod tidy
# Copy site assets # Copy site assets
assets: web assets: web
rm -rf internal/assets/dist rm -rf internal/assets/dist
@@ -12,6 +17,10 @@ assets: web
run: assets run: assets
go run main.go go run main.go
# Run development binary without compiling the frontend
run-skip-web:
go run main.go
# Test # Test
test: test:
go test ./... go test ./...
@@ -20,6 +29,6 @@ test:
build: assets build: assets
go build -o tinyauth go build -o tinyauth
# Build no site # Build the binary without compiling the frontend
build-skip-web: build-skip-web:
go build -o tinyauth go build -o tinyauth

View File

@@ -28,11 +28,11 @@ I just made a Discord server for Tinyauth! It is not only for Tinyauth but gener
## Getting Started ## Getting Started
You can easily get started with tinyauth by following the guide on the [documentation](https://tinyauth.doesmycode.work/docs/getting-started.html). There is also an available [docker compose file](./docker-compose.example.yml) that has traefik, nginx and tinyauth to demonstrate its capabilities. You can easily get started with tinyauth by following the guide on the [documentation](https://tinyauth.app/docs/getting-started.html). There is also an available [docker compose file](./docker-compose.example.yml) that has traefik, nginx and tinyauth to demonstrate its capabilities.
## Documentation ## Documentation
You can find documentation and guides on all available configuration of tinyauth [here](https://tinyauth.doesmycode.work). You can find documentation and guides on all available configuration of tinyauth [here](https://tinyauth.app).
## Contributing ## Contributing

View File

@@ -3,8 +3,8 @@
"embeds": [ "embeds": [
{ {
"title": "Welcome to Tinyauth Discord!", "title": "Welcome to Tinyauth Discord!",
"description": "Tinyauth is a simple authentication middleware that adds simple username/password login or OAuth with Google, Github and any generic OAuth provider to all of your docker apps.\n\n**Information**\n\n• Github: <https://github.com/steveiliop56/tinyauth>\n• Website: <https://tinyauth.doesmycode.work>", "description": "Tinyauth is a simple authentication middleware that adds simple username/password login or OAuth with Google, Github and any generic OAuth provider to all of your docker apps.\n\n**Information**\n\n• Github: <https://github.com/steveiliop56/tinyauth>\n• Website: <https://tinyauth.app>",
"url": "https://tinyauth.doesmycode.work", "url": "https://tinyauth.app",
"color": 7002085, "color": 7002085,
"author": { "author": {
"name": "Tinyauth" "name": "Tinyauth"
@@ -12,7 +12,7 @@
"footer": { "footer": {
"text": "Updated at" "text": "Updated at"
}, },
"timestamp": "2025-02-06T22:00:00.000Z", "timestamp": "2025-03-10T19:00:00.000Z",
"thumbnail": { "thumbnail": {
"url": "https://github.com/steveiliop56/tinyauth/blob/main/site/public/logo.png?raw=true" "url": "https://github.com/steveiliop56/tinyauth/blob/main/site/public/logo.png?raw=true"
} }

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.example.com`)
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
@@ -24,11 +24,11 @@ services:
dockerfile: Dockerfile dockerfile: Dockerfile
environment: environment:
- SECRET=some-random-32-chars-string - SECRET=some-random-32-chars-string
- APP_URL=http://tinyauth.dev.local - APP_URL=http://tinyauth.dev.example.com
- USERS=user:$$2a$$10$$UdLYoJ5lgPsC0RKqYH/jMua7zIn0g9kPqWmhYayJYLaZQ/FTmH2/u # user:password - USERS=user:$$2a$$10$$UdLYoJ5lgPsC0RKqYH/jMua7zIn0g9kPqWmhYayJYLaZQ/FTmH2/u # user:password
labels: labels:
traefik.enable: true traefik.enable: true
traefik.http.routers.tinyauth.rule: Host(`tinyauth.dev.local`) traefik.http.routers.tinyauth.rule: Host(`tinyauth.dev.example.com`)
traefik.http.services.tinyauth.loadbalancer.server.port: 3000 traefik.http.services.tinyauth.loadbalancer.server.port: 3000
traefik.http.middlewares.tinyauth.forwardauth.address: http://tinyauth:3000/api/auth/traefik traefik.http.middlewares.tinyauth.forwardauth.address: http://tinyauth:3000/api/auth/traefik
traefik.http.middlewares.tinyauth.forwardauth.authResponseHeaders: Remote-User traefik.http.middlewares.tinyauth.forwardauth.authResponseHeaders: Remote-User

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.example.com`) traefik.http.routers.nginx.rule: Host(`whoami.example.com`)
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

2
go.mod
View File

@@ -7,6 +7,7 @@ require (
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
github.com/mdp/qrterminal/v3 v3.2.0
github.com/rs/zerolog v1.33.0 github.com/rs/zerolog v1.33.0
github.com/spf13/cobra v1.8.1 github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.19.0 github.com/spf13/viper v1.19.0
@@ -15,7 +16,6 @@ require (
require ( require (
github.com/containerd/log v0.1.0 // indirect github.com/containerd/log v0.1.0 // indirect
github.com/mdp/qrterminal/v3 v3.2.0 // indirect
github.com/moby/term v0.5.2 // indirect github.com/moby/term v0.5.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect github.com/morikuni/aec v1.0.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect

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