fix: only use groups in OAuth

This commit is contained in:
Stavros
2025-05-01 22:00:37 +03:00
parent 5278fbea68
commit a98a91a394
3 changed files with 68 additions and 46 deletions

View File

@@ -70,7 +70,7 @@ export const ContinuePage = () => {
</Button> </Button>
<Button <Button
fullWidth fullWidth
mt="sm" mt="xs"
color="gray" color="gray"
onClick={() => (window.location.href = "/")} onClick={() => (window.location.href = "/")}
> >
@@ -110,7 +110,7 @@ export const ContinuePage = () => {
</Button> </Button>
<Button <Button
fullWidth fullWidth
mt="sm" mt="xs"
color="gray" color="gray"
onClick={() => (window.location.href = "/")} onClick={() => (window.location.href = "/")}
> >

View File

@@ -2,8 +2,9 @@ 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 { Trans, useTranslation } from "react-i18next"; import { Trans, useTranslation } from "react-i18next";
import React from "react"; import React, { useEffect } from "react";
import { isValidQuery } from "../utils/utils"; import { isValidQuery } from "../utils/utils";
import { useIsMounted } from "../lib/hooks/use-is-mounted";
export const UnauthorizedPage = () => { export const UnauthorizedPage = () => {
const queryString = window.location.search; const queryString = window.location.search;
@@ -12,13 +13,31 @@ export const UnauthorizedPage = () => {
const groupErr = params.get("groupErr") ?? ""; const groupErr = params.get("groupErr") ?? "";
const resource = params.get("resource") ?? ""; const resource = params.get("resource") ?? "";
const [isGroupErr, setIsGroupErr] = React.useState(false);
const useMounted = useIsMounted();
useEffect(() => {
if (useMounted()) {
if (isValidQuery(groupErr)) {
if (groupErr === "true") {
setIsGroupErr(true);
return;
}
setIsGroupErr(false);
return;
}
setIsGroupErr(false);
}
}, []);
const { t } = useTranslation(); const { t } = useTranslation();
if (!isValidQuery(username)) { if (!isValidQuery(username)) {
return <Navigate to="/" />; return <Navigate to="/" />;
} }
if (isValidQuery(resource) && !isValidQuery(groupErr)) { if (isValidQuery(resource) && !isGroupErr) {
return ( return (
<UnauthorizedLayout> <UnauthorizedLayout>
<Trans <Trans
@@ -31,7 +50,7 @@ export const UnauthorizedPage = () => {
); );
} }
if (isValidQuery(groupErr) && isValidQuery(resource)) { if (isGroupErr && isValidQuery(resource)) {
return ( return (
<UnauthorizedLayout> <UnauthorizedLayout>
<Trans <Trans

View File

@@ -75,6 +75,8 @@ func (h *Handlers) AuthHandler(c *gin.Context) {
// Get the container labels // Get the container labels
labels, err := h.Docker.GetLabels(appId) labels, err := h.Docker.GetLabels(appId)
log.Debug().Interface("labels", labels).Msg("Got labels")
// Check if there was an error // Check if there was an error
if err != nil { if err != nil {
log.Error().Err(err).Msg("Failed to get container labels") log.Error().Err(err).Msg("Failed to get container labels")
@@ -183,54 +185,55 @@ func (h *Handlers) AuthHandler(c *gin.Context) {
return return
} }
log.Debug().Interface("labels", labels).Msg("Got labels") // Check groups if using OAuth
if userContext.OAuth {
// Check if user is in required groups
groupOk := h.Auth.OAuthGroup(c, userContext, labels)
// Check if user is in required groups log.Debug().Bool("groupOk", groupOk).Msg("Checking if user is in required groups")
groupOk := h.Auth.OAuthGroup(c, userContext, labels)
log.Debug().Bool("groupOk", groupOk).Msg("Checking if user is in required groups") // The user is not allowed to access the app
if !groupOk {
log.Warn().Str("username", userContext.Username).Str("host", host).Msg("User is not in required groups")
// The user is not allowed to access the app // Set WWW-Authenticate header
if !groupOk { c.Header("WWW-Authenticate", "Basic realm=\"tinyauth\"")
log.Warn().Str("username", userContext.Username).Str("host", host).Msg("User is not in required groups")
// Set WWW-Authenticate header if proxy.Proxy == "nginx" || !isBrowser {
c.Header("WWW-Authenticate", "Basic realm=\"tinyauth\"") c.JSON(401, gin.H{
"status": 401,
"message": "Unauthorized",
})
return
}
if proxy.Proxy == "nginx" || !isBrowser { // Values
c.JSON(401, gin.H{ values := types.UnauthorizedQuery{
"status": 401, Resource: strings.Split(host, ".")[0],
"message": "Unauthorized", GroupErr: true,
}) }
// Use either username or email
if userContext.OAuth {
values.Username = userContext.Email
} else {
values.Username = userContext.Username
}
// Build query
queries, err := query.Values(values)
// Handle error (no need to check for nginx/headers since we are sure we are using caddy/traefik)
if err != nil {
log.Error().Err(err).Msg("Failed to build queries")
c.Redirect(http.StatusPermanentRedirect, fmt.Sprintf("%s/error", h.Config.AppURL))
return
}
// We are using caddy/traefik so redirect
c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%s/unauthorized?%s", h.Config.AppURL, queries.Encode()))
return return
} }
// Values
values := types.UnauthorizedQuery{
Resource: strings.Split(host, ".")[0],
GroupErr: true,
}
// Use either username or email
if userContext.OAuth {
values.Username = userContext.Email
} else {
values.Username = userContext.Username
}
// Build query
queries, err := query.Values(values)
// Handle error (no need to check for nginx/headers since we are sure we are using caddy/traefik)
if err != nil {
log.Error().Err(err).Msg("Failed to build queries")
c.Redirect(http.StatusPermanentRedirect, fmt.Sprintf("%s/error", h.Config.AppURL))
return
}
// We are using caddy/traefik so redirect
c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%s/unauthorized?%s", h.Config.AppURL, queries.Encode()))
return
} }
c.Header("Remote-User", utils.SanitizeHeader(userContext.Username)) c.Header("Remote-User", utils.SanitizeHeader(userContext.Username))