mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2025-10-29 13:15:46 +00:00
Compare commits
9 Commits
v3.0.0-alp
...
v3.0.1-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ee0b645e6 | ||
|
|
5c34ab96a9 | ||
|
|
cb6f93d879 | ||
|
|
df0c356511 | ||
|
|
d1c6ae1ba1 | ||
|
|
0f8d2e7fde | ||
|
|
0da82ae3fe | ||
|
|
f9ab9a6406 | ||
|
|
6f35923735 |
@@ -24,7 +24,7 @@ Tinyauth is a simple authentication middleware that adds simple username/passwor
|
|||||||
|
|
||||||
## Discord
|
## Discord
|
||||||
|
|
||||||
I just made a Discord server for Tinyauth! It is not only for Tinyauth but general self-hosting because I just like chatting with people! The link is [here](https://discord.gg/gWpzrksk), see you there!
|
I just made a Discord server for Tinyauth! It is not only for Tinyauth but general self-hosting because I just like chatting with people! The link is [here](https://discord.gg/eHzVaCzRRd), see you there!
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
@@ -46,5 +46,5 @@ Tinyauth is licensed under the GNU General Public License v3.0. TL;DR — You ma
|
|||||||
|
|
||||||
Credits for the logo of this app go to:
|
Credits for the logo of this app go to:
|
||||||
|
|
||||||
- **Freepik** for providing the police hat and logo.
|
- **Freepik** for providing the police hat and badge.
|
||||||
- **Renee French** for the original gopher logo.
|
- **Renee French** for the original gopher logo.
|
||||||
|
|||||||
@@ -62,7 +62,9 @@ var rootCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create oauth whitelist
|
// Create oauth whitelist
|
||||||
oauthWhitelist := strings.Split(config.OAuthWhitelist, ",")
|
oauthWhitelist := utils.Filter(strings.Split(config.OAuthWhitelist, ","), func(val string) bool {
|
||||||
|
return val != ""
|
||||||
|
})
|
||||||
log.Debug().Msg("Parsed OAuth whitelist")
|
log.Debug().Msg("Parsed OAuth whitelist")
|
||||||
|
|
||||||
// Create OAuth config
|
// Create OAuth config
|
||||||
|
|||||||
@@ -30,4 +30,4 @@ services:
|
|||||||
traefik.enable: true
|
traefik.enable: true
|
||||||
traefik.http.routers.tinyauth.rule: Host(`tinyauth.dev.local`)
|
traefik.http.routers.tinyauth.rule: Host(`tinyauth.dev.local`)
|
||||||
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.http.middlewares.tinyauth.forwardauth.address: http://tinyauth:3000/api/auth/traefik
|
||||||
|
|||||||
@@ -28,4 +28,4 @@ services:
|
|||||||
traefik.enable: true
|
traefik.enable: true
|
||||||
traefik.http.routers.tinyauth.rule: Host(`tinyauth.example.com`)
|
traefik.http.routers.tinyauth.rule: Host(`tinyauth.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.http.middlewares.tinyauth.forwardauth.address: http://tinyauth:3000/api/auth/traefik
|
||||||
|
|||||||
@@ -533,10 +533,7 @@ func (api *API) SetupRoutes() {
|
|||||||
|
|
||||||
// If it is empty it means that no redirect_uri was provided to the login screen so we just log in
|
// If it is empty it means that no redirect_uri was provided to the login screen so we just log in
|
||||||
if redirectURIErr != nil {
|
if redirectURIErr != nil {
|
||||||
c.JSON(200, gin.H{
|
c.Redirect(http.StatusPermanentRedirect, api.Config.AppURL)
|
||||||
"status": 200,
|
|
||||||
"message": "Logged in",
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug().Str("redirectURI", redirectURI).Msg("Got redirect URI")
|
log.Debug().Str("redirectURI", redirectURI).Msg("Got redirect URI")
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
v3.0.0
|
v3.0.1
|
||||||
@@ -207,3 +207,13 @@ func GetTinyauthLabels(labels map[string]string) types.TinyauthLabels {
|
|||||||
func OAuthConfigured(config types.Config) bool {
|
func OAuthConfigured(config types.Config) bool {
|
||||||
return (config.GithubClientId != "" && config.GithubClientSecret != "") || (config.GoogleClientId != "" && config.GoogleClientSecret != "") || (config.GenericClientId != "" && config.GenericClientSecret != "") || (config.TailscaleClientId != "" && config.TailscaleClientSecret != "")
|
return (config.GithubClientId != "" && config.GithubClientSecret != "") || (config.GoogleClientId != "" && config.GoogleClientSecret != "") || (config.GenericClientId != "" && config.GenericClientSecret != "") || (config.TailscaleClientId != "" && config.TailscaleClientSecret != "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter helper function
|
||||||
|
func Filter[T any](slice []T, test func(T) bool) (res []T) {
|
||||||
|
for _, value := range slice {
|
||||||
|
if test(value) {
|
||||||
|
res = append(res, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|||||||
@@ -313,3 +313,22 @@ func TestGetTinyauthLabels(t *testing.T) {
|
|||||||
t.Fatalf("Expected %v, got %v", expected, result)
|
t.Fatalf("Expected %v, got %v", expected, result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test the filter function
|
||||||
|
func TestFilter(t *testing.T) {
|
||||||
|
t.Log("Testing filter helper")
|
||||||
|
|
||||||
|
// Create variables
|
||||||
|
data := []string{"", "val1", "", "val2", "", "val3", ""}
|
||||||
|
expected := []string{"val1", "val2", "val3"}
|
||||||
|
|
||||||
|
// Test the filter function
|
||||||
|
result := utils.Filter(data, func(val string) bool {
|
||||||
|
return val != ""
|
||||||
|
})
|
||||||
|
|
||||||
|
// Check if the result is equal to the expected
|
||||||
|
if !reflect.DeepEqual(expected, result) {
|
||||||
|
t.Fatalf("Expected %v, got %v", expected, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Navigate } from "react-router";
|
|||||||
import { useUserContext } from "../context/user-context";
|
import { useUserContext } from "../context/user-context";
|
||||||
import { Layout } from "../components/layouts/layout";
|
import { Layout } from "../components/layouts/layout";
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
import { isQueryValid } from "../utils/utils";
|
||||||
|
|
||||||
export const ContinuePage = () => {
|
export const ContinuePage = () => {
|
||||||
const queryString = window.location.search;
|
const queryString = window.location.search;
|
||||||
@@ -16,7 +17,7 @@ export const ContinuePage = () => {
|
|||||||
return <Navigate to={`/login?redirect_uri=${redirectUri}`} />;
|
return <Navigate to={`/login?redirect_uri=${redirectUri}`} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (redirectUri === "null" || redirectUri === "") {
|
if (!isQueryValid(redirectUri)) {
|
||||||
return <Navigate to="/" />;
|
return <Navigate to="/" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +32,11 @@ export const ContinuePage = () => {
|
|||||||
}, 500);
|
}, 500);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!URL.canParse(redirectUri)) {
|
let uri;
|
||||||
|
|
||||||
|
try {
|
||||||
|
uri = new URL(redirectUri);
|
||||||
|
} catch {
|
||||||
return (
|
return (
|
||||||
<ContinuePageLayout>
|
<ContinuePageLayout>
|
||||||
<Text size="xl" fw={700}>
|
<Text size="xl" fw={700}>
|
||||||
@@ -45,8 +50,6 @@ export const ContinuePage = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uri = new URL(redirectUri);
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
window.location.protocol === "https:" &&
|
window.location.protocol === "https:" &&
|
||||||
uri.protocol === "http:"
|
uri.protocol === "http:"
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { GoogleIcon } from "../icons/google";
|
|||||||
import { GithubIcon } from "../icons/github";
|
import { GithubIcon } from "../icons/github";
|
||||||
import { OAuthIcon } from "../icons/oauth";
|
import { OAuthIcon } from "../icons/oauth";
|
||||||
import { TailscaleIcon } from "../icons/tailscale";
|
import { TailscaleIcon } from "../icons/tailscale";
|
||||||
|
import { isQueryValid } from "../utils/utils";
|
||||||
|
|
||||||
export const LoginPage = () => {
|
export const LoginPage = () => {
|
||||||
const queryString = window.location.search;
|
const queryString = window.location.search;
|
||||||
@@ -70,7 +71,7 @@ export const LoginPage = () => {
|
|||||||
color: "green",
|
color: "green",
|
||||||
});
|
});
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (redirectUri === "null" || redirectUri === "") {
|
if (!isQueryValid(redirectUri)) {
|
||||||
window.location.replace("/");
|
window.location.replace("/");
|
||||||
} else {
|
} else {
|
||||||
window.location.replace(`/continue?redirect_uri=${redirectUri}`);
|
window.location.replace(`/continue?redirect_uri=${redirectUri}`);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Button, Code, Paper, Text } from "@mantine/core";
|
import { Button, Code, Paper, Text } from "@mantine/core";
|
||||||
import { Layout } from "../components/layouts/layout";
|
import { Layout } from "../components/layouts/layout";
|
||||||
import { Navigate } from "react-router";
|
import { Navigate } from "react-router";
|
||||||
|
import { isQueryValid } from "../utils/utils";
|
||||||
|
|
||||||
export const UnauthorizedPage = () => {
|
export const UnauthorizedPage = () => {
|
||||||
const queryString = window.location.search;
|
const queryString = window.location.search;
|
||||||
@@ -8,7 +9,7 @@ export const UnauthorizedPage = () => {
|
|||||||
const username = params.get("username") ?? "";
|
const username = params.get("username") ?? "";
|
||||||
const resource = params.get("resource") ?? "";
|
const resource = params.get("resource") ?? "";
|
||||||
|
|
||||||
if (username === "null" || username === "") {
|
if (!isQueryValid(username)) {
|
||||||
return <Navigate to="/" />;
|
return <Navigate to="/" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ export const UnauthorizedPage = () => {
|
|||||||
</Text>
|
</Text>
|
||||||
<Text>
|
<Text>
|
||||||
The user with username <Code>{username}</Code> is not authorized to{" "}
|
The user with username <Code>{username}</Code> is not authorized to{" "}
|
||||||
{resource !== "null" && resource !== "" ? (
|
{isQueryValid(resource) ? (
|
||||||
<span>
|
<span>
|
||||||
access the <Code>{resource}</Code> resource.
|
access the <Code>{resource}</Code> resource.
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
export const capitalize = (s: string) => s.charAt(0).toUpperCase() + s.slice(1);
|
export const capitalize = (s: string) => s.charAt(0).toUpperCase() + s.slice(1);
|
||||||
|
export const isQueryValid = (value: string) => value.trim() !== "" && value !== "null";
|
||||||
|
|||||||
Reference in New Issue
Block a user