mirror of
				https://github.com/steveiliop56/tinyauth.git
				synced 2025-10-30 21:55:43 +00:00 
			
		
		
		
	Compare commits
	
		
			17 Commits
		
	
	
		
			feat/totp
			...
			v3.1.0-bet
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | ec67ea3807 | ||
|   | 3649d0d84e | ||
|   | c0ffe3faf4 | ||
|   | ad718d3ef8 | ||
|   | 38105d0b4e | ||
|   | e13bd14eb6 | ||
|   | 43dc3f9aa6 | ||
|   | 00bfaa1cbe | ||
|   | 8cc0f8b31b | ||
|   | 631059be69 | ||
|   | 5188089673 | ||
|   | 47fff12bac | ||
|   | a8c51b649f | ||
|   | c2e8f1b473 | ||
|   | bdf327cc9a | ||
|   | 46ec623d74 | ||
|   | f97c4d7e78 | 
							
								
								
									
										58
									
								
								.github/workflows/alpha-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										58
									
								
								.github/workflows/alpha-release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -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 }} | ||||
							
								
								
									
										58
									
								
								.github/workflows/beta-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										58
									
								
								.github/workflows/beta-release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -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 }} | ||||
							
								
								
									
										145
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										145
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,32 +1,22 @@ | ||||
| name: Release | ||||
| on: | ||||
|   workflow_dispatch: | ||||
|   push: | ||||
|     tags: | ||||
|       - "v*" | ||||
|  | ||||
| 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)" >> $GITHUB_OUTPUT | ||||
|  | ||||
|   build-docker: | ||||
|     needs: get-tag | ||||
|   build: | ||||
|     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: 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 | ||||
| @@ -35,21 +25,112 @@ jobs: | ||||
|           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: | ||||
|           context: . | ||||
|           push: true | ||||
|           platforms: linux/arm64, linux/amd64 | ||||
|           tags: ghcr.io/${{ github.repository_owner }}/tinyauth:${{ needs.get-tag.outputs.tag }}, ghcr.io/${{ github.repository_owner }}/tinyauth:latest | ||||
|           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 | ||||
|  | ||||
|   release: | ||||
|     needs: [get-tag, build-docker] | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Create release | ||||
|         uses: softprops/action-gh-release@v2 | ||||
|       - 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: | ||||
|           prerelease: false | ||||
|           make_latest: false | ||||
|           tag_name: ${{ needs.get-tag.outputs.tag }} | ||||
|           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=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 ' *) | ||||
|   | ||||
							
								
								
									
										2
									
								
								FUNDING.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								FUNDING.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| github: steveiliop56 | ||||
| buy_me_a_coffee: steveiliop56 | ||||
| @@ -42,6 +42,14 @@ All contributions to the codebase are welcome! If you have any recommendations o | ||||
|  | ||||
| Tinyauth is licensed under the GNU General Public License v3.0. TL;DR — You may copy, distribute and modify the software as long as you track changes/dates in source files. Any modifications to or software including (via compiler) GPL-licensed code must also be made available under the GPL along with build & install instructions. For more information about the license check the [license](./LICENSE) file. | ||||
|  | ||||
| ## Sponsors | ||||
|  | ||||
| Thanks a lot to the following people for providing me with more coffee: | ||||
|  | ||||
| | <img height="64" src="https://avatars.githubusercontent.com/u/47644445?v=4" alt="Nicolas"> | <img height="64" src="https://avatars.githubusercontent.com/u/4255748?v=4" alt="Erwin"> | | ||||
| | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | | ||||
| | <div align="center"><a href="https://github.com/nicotsx">Nicolas</a></div>                 | <div align="center"><a href="https://github.com/erwinkramer">Erwin</a></div>            | | ||||
|  | ||||
| ## Acknowledgements | ||||
|  | ||||
| Credits for the logo of this app go to: | ||||
|   | ||||
| @@ -8,12 +8,12 @@ services: | ||||
|     volumes: | ||||
|       - /var/run/docker.sock:/var/run/docker.sock | ||||
|  | ||||
|   nginx: | ||||
|     container_name: nginx | ||||
|     image: nginx:latest | ||||
|   whoami: | ||||
|     container_name: whoami | ||||
|     image: traefik/whoami:latest | ||||
|     labels: | ||||
|       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.routers.nginx.middlewares: tinyauth | ||||
|  | ||||
| @@ -31,4 +31,4 @@ services: | ||||
|       traefik.http.routers.tinyauth.rule: Host(`tinyauth.dev.local`) | ||||
|       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.authResponseHeaders: X-Tinyauth-User | ||||
|       traefik.http.middlewares.tinyauth.forwardauth.authResponseHeaders: Remote-User | ||||
|   | ||||
| @@ -29,4 +29,4 @@ services: | ||||
|       traefik.http.routers.tinyauth.rule: Host(`tinyauth.example.com`) | ||||
|       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.authResponseHeaders: X-Tinyauth-User | ||||
|       traefik.http.middlewares.tinyauth.forwardauth.authResponseHeaders: Remote-User | ||||
|   | ||||
| @@ -131,18 +131,24 @@ func (api *API) SetupRoutes() { | ||||
| 			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 | ||||
| 		_, _, basicAuth := c.Request.BasicAuth() | ||||
| 		if isBrowser { | ||||
| 			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 | ||||
| 		authEnabled, authEnabledErr := api.Auth.AuthEnabled(c) | ||||
|  | ||||
| 		// Handle error | ||||
| 		if authEnabledErr != nil { | ||||
| 			// Return 500 if nginx is the proxy or if the request is using basic auth | ||||
| 			if proxy.Proxy == "nginx" || basicAuth { | ||||
| 			// Return 500 if nginx is the proxy or if the request is not coming from a browser | ||||
| 			if proxy.Proxy == "nginx" || !isBrowser { | ||||
| 				log.Error().Err(authEnabledErr).Msg("Failed to check if auth is enabled") | ||||
| 				c.JSON(500, gin.H{ | ||||
| 					"status":  500, | ||||
| @@ -186,8 +192,8 @@ func (api *API) SetupRoutes() { | ||||
|  | ||||
| 			// Check if there was an error | ||||
| 			if appAllowedErr != nil { | ||||
| 				// Return 500 if nginx is the proxy or if the request is using basic auth | ||||
| 				if proxy.Proxy == "nginx" || basicAuth { | ||||
| 				// Return 500 if nginx is the proxy or if the request is not coming from a browser | ||||
| 				if proxy.Proxy == "nginx" || !isBrowser { | ||||
| 					log.Error().Err(appAllowedErr).Msg("Failed to check if app is allowed") | ||||
| 					c.JSON(500, gin.H{ | ||||
| 						"status":  500, | ||||
| @@ -208,9 +214,11 @@ func (api *API) SetupRoutes() { | ||||
| 			if !appAllowed { | ||||
| 				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 | ||||
| 				if proxy.Proxy == "nginx" || basicAuth { | ||||
| 				// Set WWW-Authenticate header | ||||
| 				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{ | ||||
| 						"status":  401, | ||||
| 						"message": "Unauthorized", | ||||
| @@ -237,7 +245,7 @@ func (api *API) SetupRoutes() { | ||||
| 			} | ||||
|  | ||||
| 			// Set the user header | ||||
| 			c.Header("X-Tinyauth-User", userContext.Username) | ||||
| 			c.Header("Remote-User", userContext.Username) | ||||
|  | ||||
| 			// The user is allowed to access the app | ||||
| 			c.JSON(200, gin.H{ | ||||
| @@ -252,9 +260,11 @@ func (api *API) SetupRoutes() { | ||||
| 		// The user is not logged in | ||||
| 		log.Debug().Msg("Unauthorized") | ||||
|  | ||||
| 		// Return 401 if nginx is the proxy or if the request is using an Authorization header | ||||
| 		if proxy.Proxy == "nginx" || basicAuth { | ||||
| 		// Set www-authenticate header | ||||
| 		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{ | ||||
| 				"status":  401, | ||||
| 				"message": "Unauthorized", | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| v3.0.1 | ||||
| v3.1.0 | ||||
| @@ -162,7 +162,10 @@ func (auth *Auth) ResourceAllowed(c *gin.Context, context types.UserContext) (bo | ||||
| 	// Check if resource is allowed | ||||
| 	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 context.OAuth && len(labels.OAuthWhitelist) != 0 { | ||||
| 		if context.OAuth { | ||||
| 			if len(labels.OAuthWhitelist) == 0 { | ||||
| 				return true, nil | ||||
| 			} | ||||
| 			log.Debug().Msg("Checking OAuth whitelist") | ||||
| 			if slices.Contains(labels.OAuthWhitelist, context.Username) { | ||||
| 				return true, nil | ||||
|   | ||||
		Reference in New Issue
	
	Block a user