Compare commits

..

3 Commits

Author SHA1 Message Date
Stavros
01581fc359 refactor: update domain warning screen 2026-03-01 13:29:07 +02:00
Stavros
914e46f565 chore: review comments 2026-03-01 12:50:46 +02:00
Stavros
570da3590d refactor: card title and layout tweaks 2026-02-28 21:14:12 +02:00
65 changed files with 207 additions and 389 deletions

View File

@@ -4,23 +4,14 @@
# The base URL where the app is hosted. # The base URL where the app is hosted.
TINYAUTH_APPURL= TINYAUTH_APPURL=
# database config
# The path to the database, including file name.
TINYAUTH_DATABASE_PATH="./tinyauth.db"
# analytics config
# Enable periodic version information collection.
TINYAUTH_ANALYTICS_ENABLED=true
# resources config
# Enable the resources server.
TINYAUTH_RESOURCES_ENABLED=true
# The directory where resources are stored. # The directory where resources are stored.
TINYAUTH_RESOURCES_PATH="./resources" TINYAUTH_RESOURCESDIR="./resources"
# The path to the database file.
TINYAUTH_DATABASEPATH="./tinyauth.db"
# Disable analytics.
TINYAUTH_DISABLEANALYTICS=false
# Disable resources server.
TINYAUTH_DISABLERESOURCES=false
# server config # server config
@@ -116,9 +107,9 @@ TINYAUTH_OAUTH_PROVIDERS_name_NAME=
# oidc config # oidc config
# Path to the private key file, including file name. # Path to the private key file.
TINYAUTH_OIDC_PRIVATEKEYPATH="./tinyauth_oidc_key" TINYAUTH_OIDC_PRIVATEKEYPATH="./tinyauth_oidc_key"
# Path to the public key file, including file name. # Path to the public key file.
TINYAUTH_OIDC_PUBLICKEYPATH="./tinyauth_oidc_key.pub" TINYAUTH_OIDC_PUBLICKEYPATH="./tinyauth_oidc_key.pub"
# OIDC client ID. # OIDC client ID.
TINYAUTH_OIDC_CLIENTS_name_CLIENTID= TINYAUTH_OIDC_CLIENTS_name_CLIENTID=
@@ -139,8 +130,8 @@ TINYAUTH_UI_TITLE="Tinyauth"
TINYAUTH_UI_FORGOTPASSWORDMESSAGE="You can change your password by changing the configuration." TINYAUTH_UI_FORGOTPASSWORDMESSAGE="You can change your password by changing the configuration."
# Path to the background image. # Path to the background image.
TINYAUTH_UI_BACKGROUNDIMAGE="/background.jpg" TINYAUTH_UI_BACKGROUNDIMAGE="/background.jpg"
# Enable UI warnings. # Disable UI warnings.
TINYAUTH_UI_WARNINGSENABLED=true TINYAUTH_UI_DISABLEWARNINGS=false
# ldap config # ldap config

3
.gitignore vendored
View File

@@ -45,6 +45,3 @@ __debug_*
# generated markdown (for docs) # generated markdown (for docs)
/config.gen.md /config.gen.md
# testing config
config.certify.yml

View File

@@ -57,9 +57,9 @@ EXPOSE 3000
VOLUME ["/data"] VOLUME ["/data"]
ENV TINYAUTH_DATABASE_PATH=/data/tinyauth.db ENV TINYAUTH_DATABASEPATH=/data/tinyauth.db
ENV TINYAUTH_RESOURCES_PATH=/data/resources ENV TINYAUTH_RESOURCESDIR=/data/resources
ENV PATH=$PATH:/tinyauth ENV PATH=$PATH:/tinyauth

View File

@@ -18,8 +18,8 @@ COPY ./air.toml ./
EXPOSE 3000 EXPOSE 3000
ENV TINYAUTH_DATABASE_PATH=/data/tinyauth.db ENV TINYAUTH_DATABASEPATH=/data/tinyauth.db
ENV TINYAUTH_RESOURCES_PATH=/data/resources ENV TINYAUTH_RESOURCESDIR=/data/resources
ENTRYPOINT ["air", "-c", "air.toml"] ENTRYPOINT ["air", "-c", "air.toml"]

View File

@@ -60,9 +60,9 @@ EXPOSE 3000
VOLUME ["/data"] VOLUME ["/data"]
ENV TINYAUTH_DATABASE_PATH=/data/tinyauth.db ENV TINYAUTH_DATABASEPATH=/data/tinyauth.db
ENV TINYAUTH_RESOURCES_PATH=/data/resources ENV TINYAUTH_RESOURCESDIR=/data/resources
ENV PATH=$PATH:/tinyauth ENV PATH=$PATH:/tinyauth

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 MiB

After

Width:  |  Height:  |  Size: 4.5 MiB

View File

@@ -13,14 +13,14 @@
"@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-slot": "^1.2.4",
"@tailwindcss/vite": "^4.2.1", "@tailwindcss/vite": "^4.2.1",
"@tanstack/react-query": "^5.90.21", "@tanstack/react-query": "^5.90.21",
"axios": "^1.13.6", "axios": "^1.13.5",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"i18next": "^25.8.13", "i18next": "^25.8.13",
"i18next-browser-languagedetector": "^8.2.1", "i18next-browser-languagedetector": "^8.2.1",
"i18next-resources-to-backend": "^1.2.1", "i18next-resources-to-backend": "^1.2.1",
"input-otp": "^1.4.2", "input-otp": "^1.4.2",
"lucide-react": "^0.576.0", "lucide-react": "^0.575.0",
"next-themes": "^0.4.6", "next-themes": "^0.4.6",
"radix-ui": "^1.4.3", "radix-ui": "^1.4.3",
"react": "^19.2.4", "react": "^19.2.4",
@@ -37,14 +37,14 @@
"devDependencies": { "devDependencies": {
"@eslint/js": "^10.0.1", "@eslint/js": "^10.0.1",
"@tanstack/eslint-plugin-query": "^5.91.4", "@tanstack/eslint-plugin-query": "^5.91.4",
"@types/node": "^25.3.3", "@types/node": "^25.3.1",
"@types/react": "^19.2.14", "@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.1.4", "@vitejs/plugin-react": "^5.1.4",
"eslint": "^10.0.2", "eslint": "^10.0.2",
"eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.5.2", "eslint-plugin-react-refresh": "^0.5.2",
"globals": "^17.4.0", "globals": "^17.3.0",
"prettier": "3.8.1", "prettier": "3.8.1",
"rollup-plugin-visualizer": "^7.0.0", "rollup-plugin-visualizer": "^7.0.0",
"tw-animate-css": "^1.4.0", "tw-animate-css": "^1.4.0",
@@ -417,7 +417,7 @@
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
"@types/node": ["@types/node@25.3.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ=="], "@types/node": ["@types/node@25.3.1", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-hj9YIJimBCipHVfHKRMnvmHg+wfhKc0o4mTtXh9pKBjC8TLJzz0nzGmLi5UJsYAUgSvXFHgb0V2oY10DUFtImw=="],
"@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="], "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
@@ -463,7 +463,7 @@
"asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
"axios": ["axios@1.13.6", "", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ=="], "axios": ["axios@1.13.5", "", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q=="],
"bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="], "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],
@@ -613,7 +613,7 @@
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
"globals": ["globals@17.4.0", "", {}, "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw=="], "globals": ["globals@17.3.0", "", {}, "sha512-yMqGUQVVCkD4tqjOJf3TnrvaaHDMYp4VlUSObbkIiuCPe/ofdMBFIAcBbCSRFWOnos6qRiTVStDwqPLUclaxIw=="],
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
@@ -723,7 +723,7 @@
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
"lucide-react": ["lucide-react@0.576.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-koNxU14BXrxUfZQ9cUaP0ES1uyPZKYDjk31FQZB6dQ/x+tXk979sVAn9ppZ/pVeJJyOxVM8j1E+8QEuSc02Vug=="], "lucide-react": ["lucide-react@0.575.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-VuXgKZrk0uiDlWjGGXmKV6MSk9Yy4l10qgVvzGn2AWBx1Ylt0iBexKOAoA6I7JO3m+M9oeovJd3yYENfkUbOeg=="],
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],

View File

@@ -19,14 +19,14 @@
"@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-slot": "^1.2.4",
"@tailwindcss/vite": "^4.2.1", "@tailwindcss/vite": "^4.2.1",
"@tanstack/react-query": "^5.90.21", "@tanstack/react-query": "^5.90.21",
"axios": "^1.13.6", "axios": "^1.13.5",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"i18next": "^25.8.13", "i18next": "^25.8.13",
"i18next-browser-languagedetector": "^8.2.1", "i18next-browser-languagedetector": "^8.2.1",
"i18next-resources-to-backend": "^1.2.1", "i18next-resources-to-backend": "^1.2.1",
"input-otp": "^1.4.2", "input-otp": "^1.4.2",
"lucide-react": "^0.576.0", "lucide-react": "^0.575.0",
"next-themes": "^0.4.6", "next-themes": "^0.4.6",
"radix-ui": "^1.4.3", "radix-ui": "^1.4.3",
"react": "^19.2.4", "react": "^19.2.4",
@@ -43,14 +43,14 @@
"devDependencies": { "devDependencies": {
"@eslint/js": "^10.0.1", "@eslint/js": "^10.0.1",
"@tanstack/eslint-plugin-query": "^5.91.4", "@tanstack/eslint-plugin-query": "^5.91.4",
"@types/node": "^25.3.3", "@types/node": "^25.3.1",
"@types/react": "^19.2.14", "@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.1.4", "@vitejs/plugin-react": "^5.1.4",
"eslint": "^10.0.2", "eslint": "^10.0.2",
"eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.5.2", "eslint-plugin-react-refresh": "^0.5.2",
"globals": "^17.4.0", "globals": "^17.3.0",
"prettier": "3.8.1", "prettier": "3.8.1",
"rollup-plugin-visualizer": "^7.0.0", "rollup-plugin-visualizer": "^7.0.0",
"tw-animate-css": "^1.4.0", "tw-animate-css": "^1.4.0",

View File

@@ -43,7 +43,7 @@ export const LoginForm = (props: Props) => {
<FormLabel className="mb-2">{t("loginUsername")}</FormLabel> <FormLabel className="mb-2">{t("loginUsername")}</FormLabel>
<FormControl className="mb-1"> <FormControl className="mb-1">
<Input <Input
placeholder={t("loginUsername").toLocaleLowerCase()} placeholder={t("loginUsername")}
disabled={loading} disabled={loading}
autoComplete="username" autoComplete="username"
{...field} {...field}
@@ -62,7 +62,7 @@ export const LoginForm = (props: Props) => {
<FormLabel className="mb-2">{t("loginPassword")}</FormLabel> <FormLabel className="mb-2">{t("loginPassword")}</FormLabel>
<FormControl> <FormControl>
<Input <Input
placeholder={t("loginPassword").toLowerCase()} placeholder={t("loginPassword")}
type="password" type="password"
disabled={loading} disabled={loading}
autoComplete="current-password" autoComplete="current-password"

View File

@@ -21,6 +21,7 @@ export const DomainWarning = (props: Props) => {
const { search } = useLocation(); const { search } = useLocation();
const searchParams = new URLSearchParams(search); const searchParams = new URLSearchParams(search);
const redirectUri = searchParams.get("redirect_uri");
return ( return (
<Card role="alert" aria-live="assertive"> <Card role="alert" aria-live="assertive">
@@ -45,7 +46,9 @@ export const DomainWarning = (props: Props) => {
<CardFooter className="flex flex-col items-stretch gap-3"> <CardFooter className="flex flex-col items-stretch gap-3">
<Button <Button
onClick={() => onClick={() =>
window.location.assign(`${appUrl}/login?${searchParams.toString()}`) window.location.assign(
`${appUrl}/login?redirect_uri=${encodeURIComponent(redirectUri || "")}`,
)
} }
variant="outline" variant="outline"
> >

View File

@@ -31,7 +31,7 @@ const BaseLayout = ({ children }: { children: React.ReactNode }) => {
}; };
export const Layout = () => { export const Layout = () => {
const { appUrl, warningsEnabled } = useAppContext(); const { appUrl, disableUiWarnings } = useAppContext();
const [ignoreDomainWarning, setIgnoreDomainWarning] = useState(() => { const [ignoreDomainWarning, setIgnoreDomainWarning] = useState(() => {
return window.sessionStorage.getItem("ignoreDomainWarning") === "true"; return window.sessionStorage.getItem("ignoreDomainWarning") === "true";
}); });
@@ -42,7 +42,7 @@ export const Layout = () => {
setIgnoreDomainWarning(true); setIgnoreDomainWarning(true);
}, [setIgnoreDomainWarning]); }, [setIgnoreDomainWarning]);
if (!ignoreDomainWarning && warningsEnabled && appUrl !== currentUrl) { if (!ignoreDomainWarning && !disableUiWarnings && appUrl !== currentUrl) {
return ( return (
<BaseLayout> <BaseLayout>
<DomainWarning <DomainWarning

View File

@@ -4,7 +4,6 @@ export type OIDCValues = {
client_id: string; client_id: string;
redirect_uri: string; redirect_uri: string;
state: string; state: string;
nonce: string;
}; };
interface IuseOIDCParams { interface IuseOIDCParams {
@@ -14,7 +13,7 @@ interface IuseOIDCParams {
missingParams: string[]; missingParams: string[];
} }
const optionalParams: string[] = ["state", "nonce"]; const optionalParams: string[] = ["state"];
export function useOIDCParams(params: URLSearchParams): IuseOIDCParams { export function useOIDCParams(params: URLSearchParams): IuseOIDCParams {
let compiled: string = ""; let compiled: string = "";
@@ -27,7 +26,6 @@ export function useOIDCParams(params: URLSearchParams): IuseOIDCParams {
client_id: params.get("client_id") ?? "", client_id: params.get("client_id") ?? "",
redirect_uri: params.get("redirect_uri") ?? "", redirect_uri: params.get("redirect_uri") ?? "",
state: params.get("state") ?? "", state: params.get("state") ?? "",
nonce: params.get("nonce") ?? "",
}; };
for (const key of Object.keys(values)) { for (const key of Object.keys(values)) {

View File

@@ -58,8 +58,6 @@
"invalidInput": "Invalid input", "invalidInput": "Invalid input",
"domainWarningTitle": "Invalid Domain", "domainWarningTitle": "Invalid Domain",
"domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.", "domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignore", "ignoreTitle": "Ignore",
"goToCorrectDomainTitle": "Go to correct domain", "goToCorrectDomainTitle": "Go to correct domain",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Invalid input", "invalidInput": "Invalid input",
"domainWarningTitle": "Invalid Domain", "domainWarningTitle": "Invalid Domain",
"domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.", "domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "تجاهل", "ignoreTitle": "تجاهل",
"goToCorrectDomainTitle": "Go to correct domain", "goToCorrectDomainTitle": "Go to correct domain",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Invalid input", "invalidInput": "Invalid input",
"domainWarningTitle": "Invalid Domain", "domainWarningTitle": "Invalid Domain",
"domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.", "domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignore", "ignoreTitle": "Ignore",
"goToCorrectDomainTitle": "Go to correct domain", "goToCorrectDomainTitle": "Go to correct domain",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Neplatný údaj", "invalidInput": "Neplatný údaj",
"domainWarningTitle": "Invalid Domain", "domainWarningTitle": "Invalid Domain",
"domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.", "domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignore", "ignoreTitle": "Ignore",
"goToCorrectDomainTitle": "Go to correct domain", "goToCorrectDomainTitle": "Go to correct domain",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Invalid input", "invalidInput": "Invalid input",
"domainWarningTitle": "Invalid Domain", "domainWarningTitle": "Invalid Domain",
"domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.", "domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignore", "ignoreTitle": "Ignore",
"goToCorrectDomainTitle": "Go to correct domain", "goToCorrectDomainTitle": "Go to correct domain",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Ungültige Eingabe", "invalidInput": "Ungültige Eingabe",
"domainWarningTitle": "Ungültige Domain", "domainWarningTitle": "Ungültige Domain",
"domainWarningSubtitle": "Diese Instanz ist so konfiguriert, dass sie von <code>{{appUrl}}</code> aufgerufen werden kann, aber <code>{{currentUrl}}</code> wird verwendet. Wenn Sie fortfahren, können Probleme bei der Authentifizierung auftreten.", "domainWarningSubtitle": "Diese Instanz ist so konfiguriert, dass sie von <code>{{appUrl}}</code> aufgerufen werden kann, aber <code>{{currentUrl}}</code> wird verwendet. Wenn Sie fortfahren, können Probleme bei der Authentifizierung auftreten.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignorieren", "ignoreTitle": "Ignorieren",
"goToCorrectDomainTitle": "Zur korrekten Domain gehen", "goToCorrectDomainTitle": "Zur korrekten Domain gehen",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -1,9 +1,9 @@
{ {
"loginTitle": "Καλώς ήρθατε, συνδεθείτε με", "loginTitle": "Καλώς ήρθατε, συνδεθείτε με",
"loginTitleSimple": "Καλώς ήρθατε, παρακαλώ συνδεθείτε", "loginTitleSimple": "Καλώς ορίσατε, παρακαλώ συνδεθείτε",
"loginDivider": "Ή", "loginDivider": "Ή",
"loginUsername": "Όνομα Χρήστη", "loginUsername": "Όνομα Χρήστη",
"loginPassword": "Κωδικόs πρόσβασης", "loginPassword": "Κωδικός",
"loginSubmit": "Είσοδος", "loginSubmit": "Είσοδος",
"loginFailTitle": "Αποτυχία σύνδεσης", "loginFailTitle": "Αποτυχία σύνδεσης",
"loginFailSubtitle": "Παρακαλώ ελέγξτε το όνομα χρήστη και τον κωδικό πρόσβασης", "loginFailSubtitle": "Παρακαλώ ελέγξτε το όνομα χρήστη και τον κωδικό πρόσβασης",
@@ -19,7 +19,7 @@
"loginOauthAutoRedirectButton": "Ανακατεύθυνση τώρα", "loginOauthAutoRedirectButton": "Ανακατεύθυνση τώρα",
"continueTitle": "Συνέχεια", "continueTitle": "Συνέχεια",
"continueRedirectingTitle": "Ανακατεύθυνση...", "continueRedirectingTitle": "Ανακατεύθυνση...",
"continueRedirectingSubtitle": "Θα μεταφερθείτε σύντομα στην εφαρμογή σας", "continueRedirectingSubtitle": "Θα πρέπει να μεταφερθείτε σύντομα στην εφαρμογή σας",
"continueRedirectManually": "Χειροκίνητη ανακατεύθυνση", "continueRedirectManually": "Χειροκίνητη ανακατεύθυνση",
"continueInsecureRedirectTitle": "Μη ασφαλής ανακατεύθυνση", "continueInsecureRedirectTitle": "Μη ασφαλής ανακατεύθυνση",
"continueInsecureRedirectSubtitle": "Προσπαθείτε να ανακατευθύνετε από <code>https</code> σε <code>http</code> το οποίο δεν είναι ασφαλές. Είστε σίγουροι ότι θέλετε να συνεχίσετε;", "continueInsecureRedirectSubtitle": "Προσπαθείτε να ανακατευθύνετε από <code>https</code> σε <code>http</code> το οποίο δεν είναι ασφαλές. Είστε σίγουροι ότι θέλετε να συνεχίσετε;",
@@ -41,7 +41,7 @@
"totpSuccessSubtitle": "Ανακατεύθυνση στην εφαρμογή σας", "totpSuccessSubtitle": "Ανακατεύθυνση στην εφαρμογή σας",
"totpTitle": "Εισάγετε τον κωδικό TOTP", "totpTitle": "Εισάγετε τον κωδικό TOTP",
"totpSubtitle": "Παρακαλώ εισάγετε τον κωδικό από την εφαρμογή ελέγχου ταυτότητας.", "totpSubtitle": "Παρακαλώ εισάγετε τον κωδικό από την εφαρμογή ελέγχου ταυτότητας.",
"unauthorizedTitle": "Σφάλμα μη εξουσιοδότησης", "unauthorizedTitle": "Μη εξουσιοδοτημένο",
"unauthorizedResourceSubtitle": "Ο χρήστης με όνομα χρήστη <code>{{username}}</code> δεν έχει άδεια πρόσβασης στον πόρο <code>{{resource}}</code>.", "unauthorizedResourceSubtitle": "Ο χρήστης με όνομα χρήστη <code>{{username}}</code> δεν έχει άδεια πρόσβασης στον πόρο <code>{{resource}}</code>.",
"unauthorizedLoginSubtitle": "Ο χρήστης με όνομα χρήστη <code>{{username}}</code> δεν είναι εξουσιοδοτημένος να συνδεθεί.", "unauthorizedLoginSubtitle": "Ο χρήστης με όνομα χρήστη <code>{{username}}</code> δεν είναι εξουσιοδοτημένος να συνδεθεί.",
"unauthorizedGroupsSubtitle": "Ο χρήστης με όνομα χρήστη <code>{{username}}</code> δεν είναι στις ομάδες που απαιτούνται από τον πόρο <code>{{resource}}</code>.", "unauthorizedGroupsSubtitle": "Ο χρήστης με όνομα χρήστη <code>{{username}}</code> δεν είναι στις ομάδες που απαιτούνται από τον πόρο <code>{{resource}}</code>.",
@@ -57,9 +57,7 @@
"fieldRequired": "Αυτό το πεδίο είναι υποχρεωτικό", "fieldRequired": "Αυτό το πεδίο είναι υποχρεωτικό",
"invalidInput": "Μη έγκυρη καταχώρηση", "invalidInput": "Μη έγκυρη καταχώρηση",
"domainWarningTitle": "Μη έγκυρο domain", "domainWarningTitle": "Μη έγκυρο domain",
"domainWarningSubtitle": "Έχετε επισκεφθεί αυτή την εφαρμογή από λανθασμένο domain. Αν προχωρήσετε, ενδέχεται να αντιμετωπίσετε προβλήματα με τον έλεγχο ταυτότητας.", "domainWarningSubtitle": "Αυτή η εφαρμογή έχει ρυθμιστεί για πρόσβαση από <code>{{appUrl}}</code>, αλλά <code>{{currentUrl}}</code> χρησιμοποιείται. Αν συνεχίσετε, μπορεί να αντιμετωπίσετε προβλήματα με την ταυτοποίηση.",
"domainWarningCurrent": "Τρέχον:",
"domainWarningExpected": "Αναμένεται:",
"ignoreTitle": "Παράβλεψη", "ignoreTitle": "Παράβλεψη",
"goToCorrectDomainTitle": "Μεταβείτε στο σωστό domain", "goToCorrectDomainTitle": "Μεταβείτε στο σωστό domain",
"authorizeTitle": "Εξουσιοδότηση", "authorizeTitle": "Εξουσιοδότηση",
@@ -74,7 +72,7 @@
"authorizeErrorMissingParams": "Οι παρακάτω απαραίτητες πληροφορίες λείπουν από το αίτημά σας: {{missingParams}}", "authorizeErrorMissingParams": "Οι παρακάτω απαραίτητες πληροφορίες λείπουν από το αίτημά σας: {{missingParams}}",
"openidScopeName": "Σύνδεση OpenID", "openidScopeName": "Σύνδεση OpenID",
"openidScopeDescription": "Επιτρέπει στην εφαρμογή την πρόσβαση στις πληροφορίες σύνδεσης OpenID.", "openidScopeDescription": "Επιτρέπει στην εφαρμογή την πρόσβαση στις πληροφορίες σύνδεσης OpenID.",
"emailScopeName": "Ηλεκτρονικό ταχυδρομείο", "emailScopeName": "Διεύθυνση ηλεκτρονικού ταχυδρομείου",
"emailScopeDescription": "Επιτρέπει στην εφαρμογή να έχει πρόσβαση στη διεύθυνση ηλεκτρονικού ταχυδρομείου σας.", "emailScopeDescription": "Επιτρέπει στην εφαρμογή να έχει πρόσβαση στη διεύθυνση ηλεκτρονικού ταχυδρομείου σας.",
"profileScopeName": "Προφίλ", "profileScopeName": "Προφίλ",
"profileScopeDescription": "Επιτρέπει στην εφαρμογή να έχει πρόσβαση στις πληροφορίες του προφίλ σας.", "profileScopeDescription": "Επιτρέπει στην εφαρμογή να έχει πρόσβαση στις πληροφορίες του προφίλ σας.",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Invalid input", "invalidInput": "Invalid input",
"domainWarningTitle": "Invalid Domain", "domainWarningTitle": "Invalid Domain",
"domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.", "domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignore", "ignoreTitle": "Ignore",
"goToCorrectDomainTitle": "Go to correct domain", "goToCorrectDomainTitle": "Go to correct domain",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Virheellinen syöte", "invalidInput": "Virheellinen syöte",
"domainWarningTitle": "Virheellinen verkkotunnus", "domainWarningTitle": "Virheellinen verkkotunnus",
"domainWarningSubtitle": "Tämä instanssi on määritelty käyttämään osoitetta <code>{{appUrl}}</code>, mutta nykyinen osoite on <code>{{currentUrl}}</code>. Jos jatkat, saatat törmätä ongelmiin autentikoinnissa.", "domainWarningSubtitle": "Tämä instanssi on määritelty käyttämään osoitetta <code>{{appUrl}}</code>, mutta nykyinen osoite on <code>{{currentUrl}}</code>. Jos jatkat, saatat törmätä ongelmiin autentikoinnissa.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Jätä huomiotta", "ignoreTitle": "Jätä huomiotta",
"goToCorrectDomainTitle": "Siirry oikeaan verkkotunnukseen", "goToCorrectDomainTitle": "Siirry oikeaan verkkotunnukseen",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Saisie non valide", "invalidInput": "Saisie non valide",
"domainWarningTitle": "Domaine invalide", "domainWarningTitle": "Domaine invalide",
"domainWarningSubtitle": "Cette instance est configurée pour être accédée depuis <code>{{appUrl}}</code>, mais <code>{{currentUrl}}</code> est utilisé. Si vous continuez, vous pourriez rencontrer des problèmes d'authentification.", "domainWarningSubtitle": "Cette instance est configurée pour être accédée depuis <code>{{appUrl}}</code>, mais <code>{{currentUrl}}</code> est utilisé. Si vous continuez, vous pourriez rencontrer des problèmes d'authentification.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignorer", "ignoreTitle": "Ignorer",
"goToCorrectDomainTitle": "Aller au bon domaine", "goToCorrectDomainTitle": "Aller au bon domaine",
"authorizeTitle": "Autoriser", "authorizeTitle": "Autoriser",
@@ -73,7 +71,7 @@
"authorizeErrorClientInfo": "Une erreur est survenue lors du chargement des informations du client. Veuillez réessayer plus tard.", "authorizeErrorClientInfo": "Une erreur est survenue lors du chargement des informations du client. Veuillez réessayer plus tard.",
"authorizeErrorMissingParams": "Les paramètres suivants sont manquants : {{missingParams}}", "authorizeErrorMissingParams": "Les paramètres suivants sont manquants : {{missingParams}}",
"openidScopeName": "Connexion OpenID", "openidScopeName": "Connexion OpenID",
"openidScopeDescription": "Autorise l'application à accéder à vos informations \"OpenID Connect\".", "openidScopeDescription": "Allows the app to access your OpenID Connect information.",
"emailScopeName": "Email", "emailScopeName": "Email",
"emailScopeDescription": "Autorise l'application à accéder à votre adresse e-mail.", "emailScopeDescription": "Autorise l'application à accéder à votre adresse e-mail.",
"profileScopeName": "Profil", "profileScopeName": "Profil",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Invalid input", "invalidInput": "Invalid input",
"domainWarningTitle": "Invalid Domain", "domainWarningTitle": "Invalid Domain",
"domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.", "domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignore", "ignoreTitle": "Ignore",
"goToCorrectDomainTitle": "Go to correct domain", "goToCorrectDomainTitle": "Go to correct domain",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Invalid input", "invalidInput": "Invalid input",
"domainWarningTitle": "Invalid Domain", "domainWarningTitle": "Invalid Domain",
"domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.", "domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignore", "ignoreTitle": "Ignore",
"goToCorrectDomainTitle": "Go to correct domain", "goToCorrectDomainTitle": "Go to correct domain",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Input non valido", "invalidInput": "Input non valido",
"domainWarningTitle": "Dominio non valido", "domainWarningTitle": "Dominio non valido",
"domainWarningSubtitle": "Questa istanza è configurata per essere accessibile da <code>{{appUrl}}</code>, ma la stai visitando da <code>{{currentUrl}}</code>. Se procedi, potresti incorrere in problemi di autenticazione.", "domainWarningSubtitle": "Questa istanza è configurata per essere accessibile da <code>{{appUrl}}</code>, ma la stai visitando da <code>{{currentUrl}}</code>. Se procedi, potresti incorrere in problemi di autenticazione.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignora", "ignoreTitle": "Ignora",
"goToCorrectDomainTitle": "Vai al dominio corretto", "goToCorrectDomainTitle": "Vai al dominio corretto",
"authorizeTitle": "Autorizza", "authorizeTitle": "Autorizza",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Invalid input", "invalidInput": "Invalid input",
"domainWarningTitle": "Invalid Domain", "domainWarningTitle": "Invalid Domain",
"domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.", "domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignore", "ignoreTitle": "Ignore",
"goToCorrectDomainTitle": "Go to correct domain", "goToCorrectDomainTitle": "Go to correct domain",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Invalid input", "invalidInput": "Invalid input",
"domainWarningTitle": "Invalid Domain", "domainWarningTitle": "Invalid Domain",
"domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.", "domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignore", "ignoreTitle": "Ignore",
"goToCorrectDomainTitle": "Go to correct domain", "goToCorrectDomainTitle": "Go to correct domain",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Ongeldige invoer", "invalidInput": "Ongeldige invoer",
"domainWarningTitle": "Ongeldig domein", "domainWarningTitle": "Ongeldig domein",
"domainWarningSubtitle": "Deze instantie is geconfigureerd voor toegang tot <code>{{appUrl}}</code>, maar <code>{{currentUrl}}</code> wordt gebruikt. Als je doorgaat, kun je problemen ondervinden met authenticatie.", "domainWarningSubtitle": "Deze instantie is geconfigureerd voor toegang tot <code>{{appUrl}}</code>, maar <code>{{currentUrl}}</code> wordt gebruikt. Als je doorgaat, kun je problemen ondervinden met authenticatie.",
"domainWarningCurrent": "Huidige:",
"domainWarningExpected": "Verwachte:",
"ignoreTitle": "Negeren", "ignoreTitle": "Negeren",
"goToCorrectDomainTitle": "Ga naar het juiste domein", "goToCorrectDomainTitle": "Ga naar het juiste domein",
"authorizeTitle": "Autoriseren", "authorizeTitle": "Autoriseren",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Invalid input", "invalidInput": "Invalid input",
"domainWarningTitle": "Invalid Domain", "domainWarningTitle": "Invalid Domain",
"domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.", "domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignore", "ignoreTitle": "Ignore",
"goToCorrectDomainTitle": "Go to correct domain", "goToCorrectDomainTitle": "Go to correct domain",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Nieprawidłowe dane wejściowe", "invalidInput": "Nieprawidłowe dane wejściowe",
"domainWarningTitle": "Nieprawidłowa domena", "domainWarningTitle": "Nieprawidłowa domena",
"domainWarningSubtitle": "Ta instancja jest skonfigurowana do uzyskania dostępu z <code>{{appUrl}}</code>, ale <code>{{currentUrl}}</code> jest w użyciu. Jeśli będziesz kontynuować, mogą wystąpić problemy z uwierzytelnianiem.", "domainWarningSubtitle": "Ta instancja jest skonfigurowana do uzyskania dostępu z <code>{{appUrl}}</code>, ale <code>{{currentUrl}}</code> jest w użyciu. Jeśli będziesz kontynuować, mogą wystąpić problemy z uwierzytelnianiem.",
"domainWarningCurrent": "Bieżąca:",
"domainWarningExpected": "Oczekiwana:",
"ignoreTitle": "Zignoruj", "ignoreTitle": "Zignoruj",
"goToCorrectDomainTitle": "Przejdź do prawidłowej domeny", "goToCorrectDomainTitle": "Przejdź do prawidłowej domeny",
"authorizeTitle": "Autoryzuj", "authorizeTitle": "Autoryzuj",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Entrada Inválida", "invalidInput": "Entrada Inválida",
"domainWarningTitle": "Domínio inválido", "domainWarningTitle": "Domínio inválido",
"domainWarningSubtitle": "Esta instância está configurada para ser acessada de <code>{{appUrl}}</code>, mas <code>{{currentUrl}}</code> está sendo usado. Se você continuar, você pode encontrar problemas com a autenticação.", "domainWarningSubtitle": "Esta instância está configurada para ser acessada de <code>{{appUrl}}</code>, mas <code>{{currentUrl}}</code> está sendo usado. Se você continuar, você pode encontrar problemas com a autenticação.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignorar", "ignoreTitle": "Ignorar",
"goToCorrectDomainTitle": "Ir para o domínio correto", "goToCorrectDomainTitle": "Ir para o domínio correto",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Entrada inválida", "invalidInput": "Entrada inválida",
"domainWarningTitle": "Domínio inválido", "domainWarningTitle": "Domínio inválido",
"domainWarningSubtitle": "Esta instância está configurada para ser acedida a partir de <code>{{appUrl}}</code>, mas está a ser usado <code>{{currentUrl}}</code>. Se continuares, poderás ter problemas de autenticação.", "domainWarningSubtitle": "Esta instância está configurada para ser acedida a partir de <code>{{appUrl}}</code>, mas está a ser usado <code>{{currentUrl}}</code>. Se continuares, poderás ter problemas de autenticação.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignorar", "ignoreTitle": "Ignorar",
"goToCorrectDomainTitle": "Ir para o domínio correto", "goToCorrectDomainTitle": "Ir para o domínio correto",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Invalid input", "invalidInput": "Invalid input",
"domainWarningTitle": "Invalid Domain", "domainWarningTitle": "Invalid Domain",
"domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.", "domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignore", "ignoreTitle": "Ignore",
"goToCorrectDomainTitle": "Go to correct domain", "goToCorrectDomainTitle": "Go to correct domain",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Недопустимый ввод", "invalidInput": "Недопустимый ввод",
"domainWarningTitle": "Неверный домен", "domainWarningTitle": "Неверный домен",
"domainWarningSubtitle": "Этот экземпляр настроен на доступ к нему из <code>{{appUrl}}</code>, но <code>{{currentUrl}}</code> в настоящее время используется. Если вы продолжите, то могут возникнуть проблемы с авторизацией.", "domainWarningSubtitle": "Этот экземпляр настроен на доступ к нему из <code>{{appUrl}}</code>, но <code>{{currentUrl}}</code> в настоящее время используется. Если вы продолжите, то могут возникнуть проблемы с авторизацией.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Игнорировать", "ignoreTitle": "Игнорировать",
"goToCorrectDomainTitle": "Перейти к правильному домену", "goToCorrectDomainTitle": "Перейти к правильному домену",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Неисправан унос", "invalidInput": "Неисправан унос",
"domainWarningTitle": "Неисправан домен", "domainWarningTitle": "Неисправан домен",
"domainWarningSubtitle": "Ова инстанца је подешена да јој се приступа са <code>{{appUrl}}</code>, али се користи <code>{{currentUrl}}</code>. Ако наставите, можете искусити проблеме са аутентификацијом.", "domainWarningSubtitle": "Ова инстанца је подешена да јој се приступа са <code>{{appUrl}}</code>, али се користи <code>{{currentUrl}}</code>. Ако наставите, можете искусити проблеме са аутентификацијом.",
"domainWarningCurrent": "Тренутни:",
"domainWarningExpected": "Очекивани:",
"ignoreTitle": "Игнориши", "ignoreTitle": "Игнориши",
"goToCorrectDomainTitle": "Иди на исправан домен", "goToCorrectDomainTitle": "Иди на исправан домен",
"authorizeTitle": "Ауторизуј", "authorizeTitle": "Ауторизуј",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Invalid input", "invalidInput": "Invalid input",
"domainWarningTitle": "Invalid Domain", "domainWarningTitle": "Invalid Domain",
"domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.", "domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignore", "ignoreTitle": "Ignore",
"goToCorrectDomainTitle": "Go to correct domain", "goToCorrectDomainTitle": "Go to correct domain",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "Geçersiz girdi", "invalidInput": "Geçersiz girdi",
"domainWarningTitle": "Geçersiz alan adı", "domainWarningTitle": "Geçersiz alan adı",
"domainWarningSubtitle": "Bu örnek, <code>{{appUrl}}</code> adresinden erişilecek şekilde yapılandırılmıştır, ancak <code>{{currentUrl}}</code> kullanılmaktadır. Devam ederseniz, kimlik doğrulama ile ilgili sorunlarla karşılaşabilirsiniz.", "domainWarningSubtitle": "Bu örnek, <code>{{appUrl}}</code> adresinden erişilecek şekilde yapılandırılmıştır, ancak <code>{{currentUrl}}</code> kullanılmaktadır. Devam ederseniz, kimlik doğrulama ile ilgili sorunlarla karşılaşabilirsiniz.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Yoksay", "ignoreTitle": "Yoksay",
"goToCorrectDomainTitle": "Doğru alana gidin", "goToCorrectDomainTitle": "Doğru alana gidin",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -51,33 +51,31 @@
"forgotPasswordTitle": "Забули пароль?", "forgotPasswordTitle": "Забули пароль?",
"failedToFetchProvidersTitle": "Не вдалося завантажити провайдерів автентифікації. Будь ласка, перевірте вашу конфігурацію.", "failedToFetchProvidersTitle": "Не вдалося завантажити провайдерів автентифікації. Будь ласка, перевірте вашу конфігурацію.",
"errorTitle": "Виникла помилка", "errorTitle": "Виникла помилка",
"errorSubtitleInfo": "Під час обробки запиту сталась помилка:", "errorSubtitleInfo": "The following error occurred while processing your request:",
"errorSubtitle": "An error occurred while trying to perform this action. Please check the console for more information.", "errorSubtitle": "An error occurred while trying to perform this action. Please check the console for more information.",
"forgotPasswordMessage": "Ви можете скинути пароль, змінивши змінну середовища \"USERS\".", "forgotPasswordMessage": "Ви можете скинути пароль, змінивши змінну середовища \"USERS\".",
"fieldRequired": "Це поле обов'язкове для заповнення", "fieldRequired": "Це поле обов'язкове для заповнення",
"invalidInput": "Невірне введення", "invalidInput": "Невірне введення",
"domainWarningTitle": "Невірний домен", "domainWarningTitle": "Невірний домен",
"domainWarningSubtitle": "Даний ресурс налаштований для доступу з <code>{{appUrl}}</code>, але використовується <code>{{currentUrl}}</code>. Якщо ви продовжите, можуть виникнути проблеми з автентифікацією.", "domainWarningSubtitle": "Даний ресурс налаштований для доступу з <code>{{appUrl}}</code>, але використовується <code>{{currentUrl}}</code>. Якщо ви продовжите, можуть виникнути проблеми з автентифікацією.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ігнорувати", "ignoreTitle": "Ігнорувати",
"goToCorrectDomainTitle": "Перейти за коректним доменом", "goToCorrectDomainTitle": "Перейти за коректним доменом",
"authorizeTitle": "Авторизуватись", "authorizeTitle": "Authorize",
"authorizeCardTitle": "Перейти до {{app}}?", "authorizeCardTitle": "Continue to {{app}}?",
"authorizeSubtitle": "Чи хочете ви продовжити роботу з цим додатком? Будь ласка, уважно перегляньте дозволи, які вимагає додаток.", "authorizeSubtitle": "Would you like to continue to this app? Please carefully review the permissions requested by the app.",
"authorizeSubtitleOAuth": "Бажаєте продовжити роботу з цим додатком?", "authorizeSubtitleOAuth": "Would you like to continue to this app?",
"authorizeLoadingTitle": "Завантаження...", "authorizeLoadingTitle": "Loading...",
"authorizeLoadingSubtitle": "Будь ласка, зачекайте, поки ми завантажуємо клієнтську інформацію.", "authorizeLoadingSubtitle": "Please wait while we load the client information.",
"authorizeSuccessTitle": "Авторизовано", "authorizeSuccessTitle": "Authorized",
"authorizeSuccessSubtitle": "Вас буде перенаправлено до програми за декілька секунд.", "authorizeSuccessSubtitle": "You will be redirected to the app in a few seconds.",
"authorizeErrorClientInfo": "Під час завантаження даних клієнта сталася помилка. Будь ласка, спробуйте ще раз пізніше.", "authorizeErrorClientInfo": "An error occurred while loading the client information. Please try again later.",
"authorizeErrorMissingParams": "Відсутні наступні параметри: {{missingParams}}", "authorizeErrorMissingParams": "The following parameters are missing: {{missingParams}}",
"openidScopeName": "OpenID Connect", "openidScopeName": "OpenID Connect",
"openidScopeDescription": "Дозволяє програмі отримувати доступ до вашої інформації OpenID Connect.", "openidScopeDescription": "Allows the app to access your OpenID Connect information.",
"emailScopeName": "Електронна пошта", "emailScopeName": "Email",
"emailScopeDescription": "Дозволяє програмі отримувати доступ до вашої адреси електронної пошти.", "emailScopeDescription": "Allows the app to access your email address.",
"profileScopeName": "Профіль", "profileScopeName": "Profile",
"profileScopeDescription": "Дозволяє програмі отримувати доступ до інформації вашого профілю.", "profileScopeDescription": "Allows the app to access your profile information.",
"groupsScopeName": "Групи", "groupsScopeName": "Groups",
"groupsScopeDescription": "Дозволяє програмі отримувати доступ до інформації про групу." "groupsScopeDescription": "Allows the app to access your group information."
} }

View File

@@ -58,8 +58,6 @@
"invalidInput": "Invalid input", "invalidInput": "Invalid input",
"domainWarningTitle": "Invalid Domain", "domainWarningTitle": "Invalid Domain",
"domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.", "domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "Ignore", "ignoreTitle": "Ignore",
"goToCorrectDomainTitle": "Go to correct domain", "goToCorrectDomainTitle": "Go to correct domain",
"authorizeTitle": "Authorize", "authorizeTitle": "Authorize",

View File

@@ -58,8 +58,6 @@
"invalidInput": "无效的输入", "invalidInput": "无效的输入",
"domainWarningTitle": "无效域名", "domainWarningTitle": "无效域名",
"domainWarningSubtitle": "当前实例配置的访问地址为 <code>{{appUrl}}</code>,但您正在使用 <code>{{currentUrl}}</code>。若继续操作,可能会遇到身份验证问题。", "domainWarningSubtitle": "当前实例配置的访问地址为 <code>{{appUrl}}</code>,但您正在使用 <code>{{currentUrl}}</code>。若继续操作,可能会遇到身份验证问题。",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "忽略", "ignoreTitle": "忽略",
"goToCorrectDomainTitle": "转到正确的域名", "goToCorrectDomainTitle": "转到正确的域名",
"authorizeTitle": "授权", "authorizeTitle": "授权",

View File

@@ -58,8 +58,6 @@
"invalidInput": "無效的輸入", "invalidInput": "無效的輸入",
"domainWarningTitle": "無效的網域", "domainWarningTitle": "無效的網域",
"domainWarningSubtitle": "此服務設定為透過 <code>{{appUrl}}</code> 存取,但目前使用的是 <code>{{currentUrl}}</code>。若繼續操作,可能會遇到驗證問題。", "domainWarningSubtitle": "此服務設定為透過 <code>{{appUrl}}</code> 存取,但目前使用的是 <code>{{currentUrl}}</code>。若繼續操作,可能會遇到驗證問題。",
"domainWarningCurrent": "Current:",
"domainWarningExpected": "Expected:",
"ignoreTitle": "忽略", "ignoreTitle": "忽略",
"goToCorrectDomainTitle": "前往正確域名", "goToCorrectDomainTitle": "前往正確域名",
"authorizeTitle": "授權", "authorizeTitle": "授權",

View File

@@ -98,7 +98,6 @@ export const AuthorizePage = () => {
client_id: props.client_id, client_id: props.client_id,
redirect_uri: props.redirect_uri, redirect_uri: props.redirect_uri,
state: props.state, state: props.state,
nonce: props.nonce,
}); });
}, },
mutationKey: ["authorize", props.client_id], mutationKey: ["authorize", props.client_id],
@@ -156,8 +155,8 @@ export const AuthorizePage = () => {
<Card> <Card>
<CardHeader className="mb-2"> <CardHeader className="mb-2">
<div className="flex flex-col gap-3 items-center justify-center text-center"> <div className="flex flex-col gap-3 items-center justify-center text-center">
<div className="bg-accent-foreground box-content text-muted text-xl font-bold font-sans rounded-lg size-8 p-2 flex items-center justify-center"> <div className="bg-accent-foreground text-muted text-xl font-bold font-sans rounded-lg px-4 py-3">
{getClientInfo.data?.name.slice(0, 1) || "U"} {getClientInfo.data?.name.slice(0, 1)}
</div> </div>
<CardTitle className="text-xl"> <CardTitle className="text-xl">
{t("authorizeCardTitle", { {t("authorizeCardTitle", {
@@ -171,8 +170,8 @@ export const AuthorizePage = () => {
</CardDescription> </CardDescription>
</div> </div>
</CardHeader> </CardHeader>
{scopes.includes("openid") && ( <CardContent className="mb-2">
<CardContent className="mb-2"> {scopes.includes("openid") && (
<div className="flex flex-wrap gap-2 items-center justify-center"> <div className="flex flex-wrap gap-2 items-center justify-center">
{scopes.map((id) => { {scopes.map((id) => {
const scope = scopeMap.find((s) => s.id === id); const scope = scopeMap.find((s) => s.id === id);
@@ -190,8 +189,8 @@ export const AuthorizePage = () => {
); );
})} })}
</div> </div>
</CardContent> )}
)} </CardContent>
<CardFooter className="flex flex-col items-stretch gap-3"> <CardFooter className="flex flex-col items-stretch gap-3">
<Button <Button
onClick={() => authorizeMutation.mutate()} onClick={() => authorizeMutation.mutate()}

View File

@@ -14,7 +14,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
import { useRedirectUri } from "@/lib/hooks/redirect-uri"; import { useRedirectUri } from "@/lib/hooks/redirect-uri";
export const ContinuePage = () => { export const ContinuePage = () => {
const { cookieDomain, warningsEnabled } = useAppContext(); const { cookieDomain, disableUiWarnings } = useAppContext();
const { isLoggedIn } = useUserContext(); const { isLoggedIn } = useUserContext();
const { search } = useLocation(); const { search } = useLocation();
const { t } = useTranslation(); const { t } = useTranslation();
@@ -35,9 +35,10 @@ export const ContinuePage = () => {
const urlHref = url?.href; const urlHref = url?.href;
const hasValidRedirect = valid && allowedProto; const hasValidRedirect = valid && allowedProto;
const showUntrustedWarning = hasValidRedirect && !trusted && warningsEnabled; const showUntrustedWarning =
hasValidRedirect && !trusted && !disableUiWarnings;
const showInsecureWarning = const showInsecureWarning =
hasValidRedirect && httpsDowngrade && warningsEnabled; hasValidRedirect && httpsDowngrade && !disableUiWarnings;
const shouldAutoRedirect = const shouldAutoRedirect =
isLoggedIn && isLoggedIn &&
hasValidRedirect && hasValidRedirect &&

View File

@@ -258,13 +258,13 @@ export const LoginPage = () => {
/> />
)} )}
{providers.length == 0 && ( {providers.length == 0 && (
<pre className="break-normal! text-sm text-red-600"> <p className="text-center text-red-600 max-w-sm">
{t("failedToFetchProvidersTitle")} {t("failedToFetchProvidersTitle")}
</pre> </p>
)} )}
</CardContent> </CardContent>
{userAuthConfigured && ( <CardFooter>
<CardFooter> {userAuthConfigured && (
<Button <Button
className="w-full" className="w-full"
type="submit" type="submit"
@@ -273,8 +273,8 @@ export const LoginPage = () => {
> >
{t("loginSubmit")} {t("loginSubmit")}
</Button> </Button>
</CardFooter> )}
)} </CardFooter>
</Card> </Card>
); );
}; };

View File

@@ -14,7 +14,7 @@ export const appContextSchema = z.object({
forgotPasswordMessage: z.string(), forgotPasswordMessage: z.string(),
backgroundImage: z.string(), backgroundImage: z.string(),
oauthAutoRedirect: z.string(), oauthAutoRedirect: z.string(),
warningsEnabled: z.boolean(), disableUiWarnings: z.boolean(),
}); });
export type AppContextSchema = z.infer<typeof appContextSchema>; export type AppContextSchema = z.infer<typeof appContextSchema>;

30
go.mod
View File

@@ -1,6 +1,8 @@
module github.com/steveiliop56/tinyauth module github.com/steveiliop56/tinyauth
go 1.25.0 go 1.24.0
toolchain go1.24.3
replace github.com/traefik/paerser v0.2.2 => ./paerser replace github.com/traefik/paerser v0.2.2 => ./paerser
@@ -8,7 +10,7 @@ require (
github.com/cenkalti/backoff/v5 v5.0.3 github.com/cenkalti/backoff/v5 v5.0.3
github.com/charmbracelet/huh v0.8.0 github.com/charmbracelet/huh v0.8.0
github.com/docker/docker v28.5.2+incompatible github.com/docker/docker v28.5.2+incompatible
github.com/gin-gonic/gin v1.12.0 github.com/gin-gonic/gin v1.11.0
github.com/go-jose/go-jose/v4 v4.1.3 github.com/go-jose/go-jose/v4 v4.1.3
github.com/go-ldap/ldap/v3 v3.4.12 github.com/go-ldap/ldap/v3 v3.4.12
github.com/golang-migrate/migrate/v4 v4.19.1 github.com/golang-migrate/migrate/v4 v4.19.1
@@ -36,9 +38,8 @@ require (
github.com/atotto/clipboard v0.1.4 // indirect github.com/atotto/clipboard v0.1.4 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/boombuler/barcode v1.0.2 // indirect github.com/boombuler/barcode v1.0.2 // indirect
github.com/bytedance/gopkg v0.1.3 // indirect github.com/bytedance/sonic v1.14.0 // indirect
github.com/bytedance/sonic v1.15.0 // indirect github.com/bytedance/sonic/loader v0.3.0 // indirect
github.com/bytedance/sonic/loader v0.5.0 // indirect
github.com/catppuccin/go v0.3.0 // indirect github.com/catppuccin/go v0.3.0 // indirect
github.com/charmbracelet/bubbles v0.21.1-0.20250623103423-23b8fd6302d7 // indirect github.com/charmbracelet/bubbles v0.21.1-0.20250623103423-23b8fd6302d7 // indirect
github.com/charmbracelet/bubbletea v1.3.6 // indirect github.com/charmbracelet/bubbletea v1.3.6 // indirect
@@ -58,16 +59,16 @@ require (
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/gabriel-vasile/mimetype v1.4.12 // indirect github.com/gabriel-vasile/mimetype v1.4.10 // indirect
github.com/gin-contrib/sse v1.1.0 // indirect github.com/gin-contrib/sse v1.1.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.30.1 // indirect github.com/go-playground/validator/v10 v10.28.0 // indirect
github.com/goccy/go-json v0.10.5 // indirect github.com/goccy/go-json v0.10.4 // indirect
github.com/goccy/go-yaml v1.19.2 // indirect github.com/goccy/go-yaml v1.18.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/huandu/xstrings v1.5.0 // indirect github.com/huandu/xstrings v1.5.0 // indirect
github.com/imdario/mergo v0.3.11 // indirect github.com/imdario/mergo v0.3.11 // indirect
@@ -97,28 +98,27 @@ require (
github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/quic-go/qpack v0.6.0 // indirect github.com/quic-go/qpack v0.6.0 // indirect
github.com/quic-go/quic-go v0.59.0 // indirect github.com/quic-go/quic-go v0.57.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect
github.com/shopspring/decimal v1.4.0 // indirect github.com/shopspring/decimal v1.4.0 // indirect
github.com/spf13/cast v1.10.0 // indirect github.com/spf13/cast v1.10.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.3.1 // indirect github.com/ugorji/go/codec v1.3.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
go.opentelemetry.io/otel v1.37.0 // indirect go.opentelemetry.io/otel v1.37.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect
go.opentelemetry.io/otel/metric v1.37.0 // indirect go.opentelemetry.io/otel/metric v1.37.0 // indirect
go.opentelemetry.io/otel/trace v1.37.0 // indirect go.opentelemetry.io/otel/trace v1.37.0 // indirect
golang.org/x/arch v0.22.0 // indirect golang.org/x/arch v0.20.0 // indirect
golang.org/x/net v0.51.0 // indirect golang.org/x/net v0.49.0 // indirect
golang.org/x/sync v0.19.0 // indirect golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.41.0 // indirect golang.org/x/sys v0.41.0 // indirect
golang.org/x/term v0.40.0 // indirect golang.org/x/term v0.40.0 // indirect
golang.org/x/text v0.34.0 // indirect golang.org/x/text v0.34.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect google.golang.org/protobuf v1.36.9 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/libc v1.67.6 // indirect modernc.org/libc v1.67.6 // indirect
modernc.org/mathutil v1.7.1 // indirect modernc.org/mathutil v1.7.1 // indirect

60
go.sum
View File

@@ -26,12 +26,10 @@ github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.2 h1:79yrbttoZrLGkL/oOI8hBrUKucwOL0oOjUgEguGMcJ4= github.com/boombuler/barcode v1.0.2 h1:79yrbttoZrLGkL/oOI8hBrUKucwOL0oOjUgEguGMcJ4=
github.com/boombuler/barcode v1.0.2/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.2/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE=
github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
github.com/catppuccin/go v0.3.0 h1:d+0/YicIq+hSTo5oPuRi5kOpqkVA5tAsU6dNhvRu+aY= github.com/catppuccin/go v0.3.0 h1:d+0/YicIq+hSTo5oPuRi5kOpqkVA5tAsU6dNhvRu+aY=
github.com/catppuccin/go v0.3.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc= github.com/catppuccin/go v0.3.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
@@ -97,12 +95,12 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw= github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8= github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk=
github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc= github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls=
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo= github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
@@ -120,12 +118,12 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w= github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688=
github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM= github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/golang-migrate/migrate/v4 v4.19.1 h1:OCyb44lFuQfYXYLx1SCxPZQGU7mcaZ7gH9yH4jSFbBA= github.com/golang-migrate/migrate/v4 v4.19.1 h1:OCyb44lFuQfYXYLx1SCxPZQGU7mcaZ7gH9yH4jSFbBA=
github.com/golang-migrate/migrate/v4 v4.19.1/go.mod h1:CTcgfjxhaUtsLipnLoQRWCrjYXycRz/g5+RWDuYgPrE= github.com/golang-migrate/migrate/v4 v4.19.1/go.mod h1:CTcgfjxhaUtsLipnLoQRWCrjYXycRz/g5+RWDuYgPrE=
@@ -238,8 +236,8 @@ github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= github.com/quic-go/quic-go v0.57.0 h1:AsSSrrMs4qI/hLrKlTH/TGQeTMY0ib1pAOX7vA3AdqE=
github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= github.com/quic-go/quic-go v0.57.0/go.mod h1:ly4QBAjHA2VhdnxhojRsCUOeJwKYg+taDlos92xb1+s=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
@@ -261,27 +259,23 @@ github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qq
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY= github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
github.com/weppos/publicsuffix-go v0.50.2 h1:KsJFc8IEKTJovM46SRCnGNsM+rFShxcs6VEHjOJcXzE= github.com/weppos/publicsuffix-go v0.50.2 h1:KsJFc8IEKTJovM46SRCnGNsM+rFShxcs6VEHjOJcXzE=
github.com/weppos/publicsuffix-go v0.50.2/go.mod h1:CbQCKDtXF8UcT7hrxeMa0MDjwhpOI9iYOU7cfq+yo8k= github.com/weppos/publicsuffix-go v0.50.2/go.mod h1:CbQCKDtXF8UcT7hrxeMa0MDjwhpOI9iYOU7cfq+yo8k=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE=
go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
@@ -302,10 +296,10 @@ go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mx
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI= golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c=
golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A= golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
@@ -320,8 +314,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ=
golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -366,8 +360,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c h1:
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo= google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo=
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

View File

@@ -1,2 +0,0 @@
ALTER TABLE "oidc_codes" DROP COLUMN "nonce";
ALTER TABLE "oidc_tokens" DROP COLUMN "nonce";

View File

@@ -1,2 +0,0 @@
ALTER TABLE "oidc_codes" ADD COLUMN "nonce" TEXT DEFAULT "";
ALTER TABLE "oidc_tokens" ADD COLUMN "nonce" TEXT DEFAULT "";

View File

@@ -124,7 +124,7 @@ func (app *BootstrapApp) Setup() error {
tlog.App.Trace().Str("redirectCookieName", app.context.redirectCookieName).Msg("Redirect cookie name") tlog.App.Trace().Str("redirectCookieName", app.context.redirectCookieName).Msg("Redirect cookie name")
// Database // Database
db, err := app.SetupDatabase(app.config.Database.Path) db, err := app.SetupDatabase(app.config.DatabasePath)
if err != nil { if err != nil {
return fmt.Errorf("failed to setup database: %w", err) return fmt.Errorf("failed to setup database: %w", err)
@@ -193,7 +193,7 @@ func (app *BootstrapApp) Setup() error {
go app.dbCleanup(queries) go app.dbCleanup(queries)
// If analytics are not disabled, start heartbeat // If analytics are not disabled, start heartbeat
if app.config.Analytics.Enabled { if !app.config.DisableAnalytics {
tlog.App.Debug().Msg("Starting heartbeat routine") tlog.App.Debug().Msg("Starting heartbeat routine")
go app.heartbeat() go app.heartbeat()
} }

View File

@@ -71,7 +71,7 @@ func (app *BootstrapApp) setupRouter() (*gin.Engine, error) {
ForgotPasswordMessage: app.config.UI.ForgotPasswordMessage, ForgotPasswordMessage: app.config.UI.ForgotPasswordMessage,
BackgroundImage: app.config.UI.BackgroundImage, BackgroundImage: app.config.UI.BackgroundImage,
OAuthAutoRedirect: app.config.OAuth.AutoRedirect, OAuthAutoRedirect: app.config.OAuth.AutoRedirect,
WarningsEnabled: app.config.UI.WarningsEnabled, DisableUIWarnings: app.config.UI.DisableWarnings,
}, apiRouter) }, apiRouter)
contextController.SetupRoutes() contextController.SetupRoutes()
@@ -103,8 +103,8 @@ func (app *BootstrapApp) setupRouter() (*gin.Engine, error) {
userController.SetupRoutes() userController.SetupRoutes()
resourcesController := controller.NewResourcesController(controller.ResourcesControllerConfig{ resourcesController := controller.NewResourcesController(controller.ResourcesControllerConfig{
Path: app.config.Resources.Path, ResourcesDir: app.config.ResourcesDir,
Enabled: app.config.Resources.Enabled, ResourcesDisabled: app.config.DisableResources,
}, &engine.RouterGroup) }, &engine.RouterGroup)
resourcesController.SetupRoutes() resourcesController.SetupRoutes()

View File

@@ -3,16 +3,8 @@ package config
// Default configuration // Default configuration
func NewDefaultConfiguration() *Config { func NewDefaultConfiguration() *Config {
return &Config{ return &Config{
Database: DatabaseConfig{ ResourcesDir: "./resources",
Path: "./tinyauth.db", DatabasePath: "./tinyauth.db",
},
Analytics: AnalyticsConfig{
Enabled: true,
},
Resources: ResourcesConfig{
Enabled: true,
Path: "./resources",
},
Server: ServerConfig{ Server: ServerConfig{
Port: 3000, Port: 3000,
Address: "0.0.0.0", Address: "0.0.0.0",
@@ -27,7 +19,6 @@ func NewDefaultConfiguration() *Config {
Title: "Tinyauth", Title: "Tinyauth",
ForgotPasswordMessage: "You can change your password by changing the configuration.", ForgotPasswordMessage: "You can change your password by changing the configuration.",
BackgroundImage: "/background.jpg", BackgroundImage: "/background.jpg",
WarningsEnabled: true,
}, },
Ldap: LdapConfig{ Ldap: LdapConfig{
Insecure: false, Insecure: false,
@@ -77,32 +68,20 @@ var RedirectCookieName = "tinyauth-redirect"
// Main app config // Main app config
type Config struct { type Config struct {
AppURL string `description:"The base URL where the app is hosted." yaml:"appUrl"` AppURL string `description:"The base URL where the app is hosted." yaml:"appUrl"`
Database DatabaseConfig `description:"Database configuration." yaml:"database"` ResourcesDir string `description:"The directory where resources are stored." yaml:"resourcesDir"`
Analytics AnalyticsConfig `description:"Analytics configuration." yaml:"analytics"` DatabasePath string `description:"The path to the database file." yaml:"databasePath"`
Resources ResourcesConfig `description:"Resources configuration." yaml:"resources"` DisableAnalytics bool `description:"Disable analytics." yaml:"disableAnalytics"`
Server ServerConfig `description:"Server configuration." yaml:"server"` DisableResources bool `description:"Disable resources server." yaml:"disableResources"`
Auth AuthConfig `description:"Authentication configuration." yaml:"auth"` Server ServerConfig `description:"Server configuration." yaml:"server"`
Apps map[string]App `description:"Application ACLs configuration." yaml:"apps"` Auth AuthConfig `description:"Authentication configuration." yaml:"auth"`
OAuth OAuthConfig `description:"OAuth configuration." yaml:"oauth"` Apps map[string]App `description:"Application ACLs configuration." yaml:"apps"`
OIDC OIDCConfig `description:"OIDC configuration." yaml:"oidc"` OAuth OAuthConfig `description:"OAuth configuration." yaml:"oauth"`
UI UIConfig `description:"UI customization." yaml:"ui"` OIDC OIDCConfig `description:"OIDC configuration." yaml:"oidc"`
Ldap LdapConfig `description:"LDAP configuration." yaml:"ldap"` UI UIConfig `description:"UI customization." yaml:"ui"`
Experimental ExperimentalConfig `description:"Experimental features, use with caution." yaml:"experimental"` Ldap LdapConfig `description:"LDAP configuration." yaml:"ldap"`
Log LogConfig `description:"Logging configuration." yaml:"log"` Experimental ExperimentalConfig `description:"Experimental features, use with caution." yaml:"experimental"`
} Log LogConfig `description:"Logging configuration." yaml:"log"`
type DatabaseConfig struct {
Path string `description:"The path to the database, including file name." yaml:"path"`
}
type AnalyticsConfig struct {
Enabled bool `description:"Enable periodic version information collection." yaml:"enabled"`
}
type ResourcesConfig struct {
Enabled bool `description:"Enable the resources server." yaml:"enabled"`
Path string `description:"The directory where resources are stored." yaml:"path"`
} }
type ServerConfig struct { type ServerConfig struct {
@@ -135,8 +114,8 @@ type OAuthConfig struct {
} }
type OIDCConfig struct { type OIDCConfig struct {
PrivateKeyPath string `description:"Path to the private key file, including file name." yaml:"privateKeyPath"` PrivateKeyPath string `description:"Path to the private key file." yaml:"privateKeyPath"`
PublicKeyPath string `description:"Path to the public key file, including file name." yaml:"publicKeyPath"` PublicKeyPath string `description:"Path to the public key file." yaml:"publicKeyPath"`
Clients map[string]OIDCClientConfig `description:"OIDC clients configuration." yaml:"clients"` Clients map[string]OIDCClientConfig `description:"OIDC clients configuration." yaml:"clients"`
} }
@@ -144,7 +123,7 @@ type UIConfig struct {
Title string `description:"The title of the UI." yaml:"title"` Title string `description:"The title of the UI." yaml:"title"`
ForgotPasswordMessage string `description:"Message displayed on the forgot password page." yaml:"forgotPasswordMessage"` ForgotPasswordMessage string `description:"Message displayed on the forgot password page." yaml:"forgotPasswordMessage"`
BackgroundImage string `description:"Path to the background image." yaml:"backgroundImage"` BackgroundImage string `description:"Path to the background image." yaml:"backgroundImage"`
WarningsEnabled bool `description:"Enable UI warnings." yaml:"warningsEnabled"` DisableWarnings bool `description:"Disable UI warnings." yaml:"disableWarnings"`
} }
type LdapConfig struct { type LdapConfig struct {

View File

@@ -33,7 +33,7 @@ type AppContextResponse struct {
ForgotPasswordMessage string `json:"forgotPasswordMessage"` ForgotPasswordMessage string `json:"forgotPasswordMessage"`
BackgroundImage string `json:"backgroundImage"` BackgroundImage string `json:"backgroundImage"`
OAuthAutoRedirect string `json:"oauthAutoRedirect"` OAuthAutoRedirect string `json:"oauthAutoRedirect"`
WarningsEnabled bool `json:"warningsEnabled"` DisableUIWarnings bool `json:"disableUiWarnings"`
} }
type Provider struct { type Provider struct {
@@ -50,7 +50,7 @@ type ContextControllerConfig struct {
ForgotPasswordMessage string ForgotPasswordMessage string
BackgroundImage string BackgroundImage string
OAuthAutoRedirect string OAuthAutoRedirect string
WarningsEnabled bool DisableUIWarnings bool
} }
type ContextController struct { type ContextController struct {
@@ -59,7 +59,7 @@ type ContextController struct {
} }
func NewContextController(config ContextControllerConfig, router *gin.RouterGroup) *ContextController { func NewContextController(config ContextControllerConfig, router *gin.RouterGroup) *ContextController {
if !config.WarningsEnabled { if config.DisableUIWarnings {
tlog.App.Warn().Msg("UI warnings are disabled. This may expose users to security risks. Proceed with caution.") tlog.App.Warn().Msg("UI warnings are disabled. This may expose users to security risks. Proceed with caution.")
} }
@@ -124,6 +124,6 @@ func (controller *ContextController) appContextHandler(c *gin.Context) {
ForgotPasswordMessage: controller.config.ForgotPasswordMessage, ForgotPasswordMessage: controller.config.ForgotPasswordMessage,
BackgroundImage: controller.config.BackgroundImage, BackgroundImage: controller.config.BackgroundImage,
OAuthAutoRedirect: controller.config.OAuthAutoRedirect, OAuthAutoRedirect: controller.config.OAuthAutoRedirect,
WarningsEnabled: controller.config.WarningsEnabled, DisableUIWarnings: controller.config.DisableUIWarnings,
}) })
} }

View File

@@ -32,7 +32,7 @@ var contextControllerCfg = controller.ContextControllerConfig{
ForgotPasswordMessage: "Contact admin to reset your password.", ForgotPasswordMessage: "Contact admin to reset your password.",
BackgroundImage: "/assets/bg.jpg", BackgroundImage: "/assets/bg.jpg",
OAuthAutoRedirect: "google", OAuthAutoRedirect: "google",
WarningsEnabled: true, DisableUIWarnings: false,
} }
var contextCtrlTestContext = config.UserContext{ var contextCtrlTestContext = config.UserContext{
@@ -82,7 +82,7 @@ func TestAppContextHandler(t *testing.T) {
ForgotPasswordMessage: contextControllerCfg.ForgotPasswordMessage, ForgotPasswordMessage: contextControllerCfg.ForgotPasswordMessage,
BackgroundImage: contextControllerCfg.BackgroundImage, BackgroundImage: contextControllerCfg.BackgroundImage,
OAuthAutoRedirect: contextControllerCfg.OAuthAutoRedirect, OAuthAutoRedirect: contextControllerCfg.OAuthAutoRedirect,
WarningsEnabled: contextControllerCfg.WarningsEnabled, DisableUIWarnings: contextControllerCfg.DisableUIWarnings,
} }
router, recorder := setupContextController(nil) router, recorder := setupContextController(nil)

View File

@@ -296,7 +296,7 @@ func (controller *OIDCController) Token(c *gin.Context) {
return return
} }
tokenRes, err := controller.oidc.GenerateAccessToken(c, client, entry) tokenRes, err := controller.oidc.GenerateAccessToken(c, client, entry.Sub, entry.Scope)
if err != nil { if err != nil {
tlog.App.Error().Err(err).Msg("Failed to generate access token") tlog.App.Error().Err(err).Msg("Failed to generate access token")

View File

@@ -7,8 +7,8 @@ import (
) )
type ResourcesControllerConfig struct { type ResourcesControllerConfig struct {
Path string ResourcesDir string
Enabled bool ResourcesDisabled bool
} }
type ResourcesController struct { type ResourcesController struct {
@@ -18,7 +18,7 @@ type ResourcesController struct {
} }
func NewResourcesController(config ResourcesControllerConfig, router *gin.RouterGroup) *ResourcesController { func NewResourcesController(config ResourcesControllerConfig, router *gin.RouterGroup) *ResourcesController {
fileServer := http.StripPrefix("/resources", http.FileServer(http.Dir(config.Path))) fileServer := http.StripPrefix("/resources", http.FileServer(http.Dir(config.ResourcesDir)))
return &ResourcesController{ return &ResourcesController{
config: config, config: config,
@@ -32,14 +32,14 @@ func (controller *ResourcesController) SetupRoutes() {
} }
func (controller *ResourcesController) resourcesHandler(c *gin.Context) { func (controller *ResourcesController) resourcesHandler(c *gin.Context) {
if controller.config.Path == "" { if controller.config.ResourcesDir == "" {
c.JSON(404, gin.H{ c.JSON(404, gin.H{
"status": 404, "status": 404,
"message": "Resources not found", "message": "Resources not found",
}) })
return return
} }
if !controller.config.Enabled { if controller.config.ResourcesDisabled {
c.JSON(403, gin.H{ c.JSON(403, gin.H{
"status": 403, "status": 403,
"message": "Resources are disabled", "message": "Resources are disabled",

View File

@@ -18,8 +18,7 @@ func TestResourcesHandler(t *testing.T) {
group := router.Group("/") group := router.Group("/")
ctrl := controller.NewResourcesController(controller.ResourcesControllerConfig{ ctrl := controller.NewResourcesController(controller.ResourcesControllerConfig{
Path: "/tmp/tinyauth", ResourcesDir: "/tmp/tinyauth",
Enabled: true,
}, group) }, group)
ctrl.SetupRoutes() ctrl.SetupRoutes()

View File

@@ -59,7 +59,7 @@ func (controller *WellKnownController) OpenIDConnectConfiguration(c *gin.Context
SubjectTypesSupported: []string{"pairwise"}, SubjectTypesSupported: []string{"pairwise"},
IDTokenSigningAlgValuesSupported: []string{"RS256"}, IDTokenSigningAlgValuesSupported: []string{"RS256"},
TokenEndpointAuthMethodsSupported: []string{"client_secret_basic", "client_secret_post"}, TokenEndpointAuthMethodsSupported: []string{"client_secret_basic", "client_secret_post"},
ClaimsSupported: []string{"sub", "updated_at", "name", "preferred_username", "email", "email_verified", "groups"}, ClaimsSupported: []string{"sub", "updated_at", "name", "preferred_username", "email", "groups"},
ServiceDocumentation: "https://tinyauth.app/docs/guides/oidc", ServiceDocumentation: "https://tinyauth.app/docs/guides/oidc",
}) })
} }

View File

@@ -11,7 +11,6 @@ type OidcCode struct {
RedirectURI string RedirectURI string
ClientID string ClientID string
ExpiresAt int64 ExpiresAt int64
Nonce string
} }
type OidcToken struct { type OidcToken struct {
@@ -22,7 +21,6 @@ type OidcToken struct {
ClientID string ClientID string
TokenExpiresAt int64 TokenExpiresAt int64
RefreshTokenExpiresAt int64 RefreshTokenExpiresAt int64
Nonce string
} }
type OidcUserinfo struct { type OidcUserinfo struct {

View File

@@ -16,12 +16,11 @@ INSERT INTO "oidc_codes" (
"scope", "scope",
"redirect_uri", "redirect_uri",
"client_id", "client_id",
"expires_at", "expires_at"
"nonce"
) VALUES ( ) VALUES (
?, ?, ?, ?, ?, ?, ? ?, ?, ?, ?, ?, ?
) )
RETURNING sub, code_hash, scope, redirect_uri, client_id, expires_at, nonce RETURNING sub, code_hash, scope, redirect_uri, client_id, expires_at
` `
type CreateOidcCodeParams struct { type CreateOidcCodeParams struct {
@@ -31,7 +30,6 @@ type CreateOidcCodeParams struct {
RedirectURI string RedirectURI string
ClientID string ClientID string
ExpiresAt int64 ExpiresAt int64
Nonce string
} }
func (q *Queries) CreateOidcCode(ctx context.Context, arg CreateOidcCodeParams) (OidcCode, error) { func (q *Queries) CreateOidcCode(ctx context.Context, arg CreateOidcCodeParams) (OidcCode, error) {
@@ -42,7 +40,6 @@ func (q *Queries) CreateOidcCode(ctx context.Context, arg CreateOidcCodeParams)
arg.RedirectURI, arg.RedirectURI,
arg.ClientID, arg.ClientID,
arg.ExpiresAt, arg.ExpiresAt,
arg.Nonce,
) )
var i OidcCode var i OidcCode
err := row.Scan( err := row.Scan(
@@ -52,7 +49,6 @@ func (q *Queries) CreateOidcCode(ctx context.Context, arg CreateOidcCodeParams)
&i.RedirectURI, &i.RedirectURI,
&i.ClientID, &i.ClientID,
&i.ExpiresAt, &i.ExpiresAt,
&i.Nonce,
) )
return i, err return i, err
} }
@@ -65,12 +61,11 @@ INSERT INTO "oidc_tokens" (
"scope", "scope",
"client_id", "client_id",
"token_expires_at", "token_expires_at",
"refresh_token_expires_at", "refresh_token_expires_at"
"nonce"
) VALUES ( ) VALUES (
?, ?, ?, ?, ?, ?, ?, ? ?, ?, ?, ?, ?, ?, ?
) )
RETURNING sub, access_token_hash, refresh_token_hash, scope, client_id, token_expires_at, refresh_token_expires_at, nonce RETURNING sub, access_token_hash, refresh_token_hash, scope, client_id, token_expires_at, refresh_token_expires_at
` `
type CreateOidcTokenParams struct { type CreateOidcTokenParams struct {
@@ -81,7 +76,6 @@ type CreateOidcTokenParams struct {
ClientID string ClientID string
TokenExpiresAt int64 TokenExpiresAt int64
RefreshTokenExpiresAt int64 RefreshTokenExpiresAt int64
Nonce string
} }
func (q *Queries) CreateOidcToken(ctx context.Context, arg CreateOidcTokenParams) (OidcToken, error) { func (q *Queries) CreateOidcToken(ctx context.Context, arg CreateOidcTokenParams) (OidcToken, error) {
@@ -93,7 +87,6 @@ func (q *Queries) CreateOidcToken(ctx context.Context, arg CreateOidcTokenParams
arg.ClientID, arg.ClientID,
arg.TokenExpiresAt, arg.TokenExpiresAt,
arg.RefreshTokenExpiresAt, arg.RefreshTokenExpiresAt,
arg.Nonce,
) )
var i OidcToken var i OidcToken
err := row.Scan( err := row.Scan(
@@ -104,7 +97,6 @@ func (q *Queries) CreateOidcToken(ctx context.Context, arg CreateOidcTokenParams
&i.ClientID, &i.ClientID,
&i.TokenExpiresAt, &i.TokenExpiresAt,
&i.RefreshTokenExpiresAt, &i.RefreshTokenExpiresAt,
&i.Nonce,
) )
return i, err return i, err
} }
@@ -156,7 +148,7 @@ func (q *Queries) CreateOidcUserInfo(ctx context.Context, arg CreateOidcUserInfo
const deleteExpiredOidcCodes = `-- name: DeleteExpiredOidcCodes :many const deleteExpiredOidcCodes = `-- name: DeleteExpiredOidcCodes :many
DELETE FROM "oidc_codes" DELETE FROM "oidc_codes"
WHERE "expires_at" < ? WHERE "expires_at" < ?
RETURNING sub, code_hash, scope, redirect_uri, client_id, expires_at, nonce RETURNING sub, code_hash, scope, redirect_uri, client_id, expires_at
` `
func (q *Queries) DeleteExpiredOidcCodes(ctx context.Context, expiresAt int64) ([]OidcCode, error) { func (q *Queries) DeleteExpiredOidcCodes(ctx context.Context, expiresAt int64) ([]OidcCode, error) {
@@ -175,7 +167,6 @@ func (q *Queries) DeleteExpiredOidcCodes(ctx context.Context, expiresAt int64) (
&i.RedirectURI, &i.RedirectURI,
&i.ClientID, &i.ClientID,
&i.ExpiresAt, &i.ExpiresAt,
&i.Nonce,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@@ -193,7 +184,7 @@ func (q *Queries) DeleteExpiredOidcCodes(ctx context.Context, expiresAt int64) (
const deleteExpiredOidcTokens = `-- name: DeleteExpiredOidcTokens :many const deleteExpiredOidcTokens = `-- name: DeleteExpiredOidcTokens :many
DELETE FROM "oidc_tokens" DELETE FROM "oidc_tokens"
WHERE "token_expires_at" < ? AND "refresh_token_expires_at" < ? WHERE "token_expires_at" < ? AND "refresh_token_expires_at" < ?
RETURNING sub, access_token_hash, refresh_token_hash, scope, client_id, token_expires_at, refresh_token_expires_at, nonce RETURNING sub, access_token_hash, refresh_token_hash, scope, client_id, token_expires_at, refresh_token_expires_at
` `
type DeleteExpiredOidcTokensParams struct { type DeleteExpiredOidcTokensParams struct {
@@ -218,7 +209,6 @@ func (q *Queries) DeleteExpiredOidcTokens(ctx context.Context, arg DeleteExpired
&i.ClientID, &i.ClientID,
&i.TokenExpiresAt, &i.TokenExpiresAt,
&i.RefreshTokenExpiresAt, &i.RefreshTokenExpiresAt,
&i.Nonce,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@@ -286,7 +276,7 @@ func (q *Queries) DeleteOidcUserInfo(ctx context.Context, sub string) error {
const getOidcCode = `-- name: GetOidcCode :one const getOidcCode = `-- name: GetOidcCode :one
DELETE FROM "oidc_codes" DELETE FROM "oidc_codes"
WHERE "code_hash" = ? WHERE "code_hash" = ?
RETURNING sub, code_hash, scope, redirect_uri, client_id, expires_at, nonce RETURNING sub, code_hash, scope, redirect_uri, client_id, expires_at
` `
func (q *Queries) GetOidcCode(ctx context.Context, codeHash string) (OidcCode, error) { func (q *Queries) GetOidcCode(ctx context.Context, codeHash string) (OidcCode, error) {
@@ -299,7 +289,6 @@ func (q *Queries) GetOidcCode(ctx context.Context, codeHash string) (OidcCode, e
&i.RedirectURI, &i.RedirectURI,
&i.ClientID, &i.ClientID,
&i.ExpiresAt, &i.ExpiresAt,
&i.Nonce,
) )
return i, err return i, err
} }
@@ -307,7 +296,7 @@ func (q *Queries) GetOidcCode(ctx context.Context, codeHash string) (OidcCode, e
const getOidcCodeBySub = `-- name: GetOidcCodeBySub :one const getOidcCodeBySub = `-- name: GetOidcCodeBySub :one
DELETE FROM "oidc_codes" DELETE FROM "oidc_codes"
WHERE "sub" = ? WHERE "sub" = ?
RETURNING sub, code_hash, scope, redirect_uri, client_id, expires_at, nonce RETURNING sub, code_hash, scope, redirect_uri, client_id, expires_at
` `
func (q *Queries) GetOidcCodeBySub(ctx context.Context, sub string) (OidcCode, error) { func (q *Queries) GetOidcCodeBySub(ctx context.Context, sub string) (OidcCode, error) {
@@ -320,13 +309,12 @@ func (q *Queries) GetOidcCodeBySub(ctx context.Context, sub string) (OidcCode, e
&i.RedirectURI, &i.RedirectURI,
&i.ClientID, &i.ClientID,
&i.ExpiresAt, &i.ExpiresAt,
&i.Nonce,
) )
return i, err return i, err
} }
const getOidcCodeBySubUnsafe = `-- name: GetOidcCodeBySubUnsafe :one const getOidcCodeBySubUnsafe = `-- name: GetOidcCodeBySubUnsafe :one
SELECT sub, code_hash, scope, redirect_uri, client_id, expires_at, nonce FROM "oidc_codes" SELECT sub, code_hash, scope, redirect_uri, client_id, expires_at FROM "oidc_codes"
WHERE "sub" = ? WHERE "sub" = ?
` `
@@ -340,13 +328,12 @@ func (q *Queries) GetOidcCodeBySubUnsafe(ctx context.Context, sub string) (OidcC
&i.RedirectURI, &i.RedirectURI,
&i.ClientID, &i.ClientID,
&i.ExpiresAt, &i.ExpiresAt,
&i.Nonce,
) )
return i, err return i, err
} }
const getOidcCodeUnsafe = `-- name: GetOidcCodeUnsafe :one const getOidcCodeUnsafe = `-- name: GetOidcCodeUnsafe :one
SELECT sub, code_hash, scope, redirect_uri, client_id, expires_at, nonce FROM "oidc_codes" SELECT sub, code_hash, scope, redirect_uri, client_id, expires_at FROM "oidc_codes"
WHERE "code_hash" = ? WHERE "code_hash" = ?
` `
@@ -360,13 +347,12 @@ func (q *Queries) GetOidcCodeUnsafe(ctx context.Context, codeHash string) (OidcC
&i.RedirectURI, &i.RedirectURI,
&i.ClientID, &i.ClientID,
&i.ExpiresAt, &i.ExpiresAt,
&i.Nonce,
) )
return i, err return i, err
} }
const getOidcToken = `-- name: GetOidcToken :one const getOidcToken = `-- name: GetOidcToken :one
SELECT sub, access_token_hash, refresh_token_hash, scope, client_id, token_expires_at, refresh_token_expires_at, nonce FROM "oidc_tokens" SELECT sub, access_token_hash, refresh_token_hash, scope, client_id, token_expires_at, refresh_token_expires_at FROM "oidc_tokens"
WHERE "access_token_hash" = ? WHERE "access_token_hash" = ?
` `
@@ -381,13 +367,12 @@ func (q *Queries) GetOidcToken(ctx context.Context, accessTokenHash string) (Oid
&i.ClientID, &i.ClientID,
&i.TokenExpiresAt, &i.TokenExpiresAt,
&i.RefreshTokenExpiresAt, &i.RefreshTokenExpiresAt,
&i.Nonce,
) )
return i, err return i, err
} }
const getOidcTokenByRefreshToken = `-- name: GetOidcTokenByRefreshToken :one const getOidcTokenByRefreshToken = `-- name: GetOidcTokenByRefreshToken :one
SELECT sub, access_token_hash, refresh_token_hash, scope, client_id, token_expires_at, refresh_token_expires_at, nonce FROM "oidc_tokens" SELECT sub, access_token_hash, refresh_token_hash, scope, client_id, token_expires_at, refresh_token_expires_at FROM "oidc_tokens"
WHERE "refresh_token_hash" = ? WHERE "refresh_token_hash" = ?
` `
@@ -402,13 +387,12 @@ func (q *Queries) GetOidcTokenByRefreshToken(ctx context.Context, refreshTokenHa
&i.ClientID, &i.ClientID,
&i.TokenExpiresAt, &i.TokenExpiresAt,
&i.RefreshTokenExpiresAt, &i.RefreshTokenExpiresAt,
&i.Nonce,
) )
return i, err return i, err
} }
const getOidcTokenBySub = `-- name: GetOidcTokenBySub :one const getOidcTokenBySub = `-- name: GetOidcTokenBySub :one
SELECT sub, access_token_hash, refresh_token_hash, scope, client_id, token_expires_at, refresh_token_expires_at, nonce FROM "oidc_tokens" SELECT sub, access_token_hash, refresh_token_hash, scope, client_id, token_expires_at, refresh_token_expires_at FROM "oidc_tokens"
WHERE "sub" = ? WHERE "sub" = ?
` `
@@ -423,7 +407,6 @@ func (q *Queries) GetOidcTokenBySub(ctx context.Context, sub string) (OidcToken,
&i.ClientID, &i.ClientID,
&i.TokenExpiresAt, &i.TokenExpiresAt,
&i.RefreshTokenExpiresAt, &i.RefreshTokenExpiresAt,
&i.Nonce,
) )
return i, err return i, err
} }
@@ -454,7 +437,7 @@ UPDATE "oidc_tokens" SET
"token_expires_at" = ?, "token_expires_at" = ?,
"refresh_token_expires_at" = ? "refresh_token_expires_at" = ?
WHERE "refresh_token_hash" = ? WHERE "refresh_token_hash" = ?
RETURNING sub, access_token_hash, refresh_token_hash, scope, client_id, token_expires_at, refresh_token_expires_at, nonce RETURNING sub, access_token_hash, refresh_token_hash, scope, client_id, token_expires_at, refresh_token_expires_at
` `
type UpdateOidcTokenByRefreshTokenParams struct { type UpdateOidcTokenByRefreshTokenParams struct {
@@ -482,7 +465,6 @@ func (q *Queries) UpdateOidcTokenByRefreshToken(ctx context.Context, arg UpdateO
&i.ClientID, &i.ClientID,
&i.TokenExpiresAt, &i.TokenExpiresAt,
&i.RefreshTokenExpiresAt, &i.RefreshTokenExpiresAt,
&i.Nonce,
) )
return i, err return i, err
} }

View File

@@ -8,7 +8,6 @@ import (
"crypto/sha256" "crypto/sha256"
"crypto/x509" "crypto/x509"
"database/sql" "database/sql"
"encoding/base64"
"encoding/json" "encoding/json"
"encoding/pem" "encoding/pem"
"errors" "errors"
@@ -42,26 +41,19 @@ var (
) )
type ClaimSet struct { type ClaimSet struct {
Iss string `json:"iss"` Iss string `json:"iss"`
Aud string `json:"aud"` Aud string `json:"aud"`
Sub string `json:"sub"` Sub string `json:"sub"`
Iat int64 `json:"iat"` Iat int64 `json:"iat"`
Exp int64 `json:"exp"` Exp int64 `json:"exp"`
Name string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
EmailVerified bool `json:"email_verified,omitempty"`
PreferredUsername string `json:"preferred_username,omitempty"`
Groups []string `json:"groups,omitempty"`
Nonce string `json:"nonce,omitempty"`
} }
type UserinfoResponse struct { type UserinfoResponse struct {
Sub string `json:"sub"` Sub string `json:"sub"`
Name string `json:"name,omitempty"` Name string `json:"name"`
Email string `json:"email,omitempty"` Email string `json:"email"`
PreferredUsername string `json:"preferred_username,omitempty"` PreferredUsername string `json:"preferred_username"`
Groups []string `json:"groups,omitempty"` Groups []string `json:"groups"`
EmailVerified bool `json:"email_verified,omitempty"`
UpdatedAt int64 `json:"updated_at"` UpdatedAt int64 `json:"updated_at"`
} }
@@ -80,7 +72,6 @@ type AuthorizeRequest struct {
ClientID string `json:"client_id" binding:"required"` ClientID string `json:"client_id" binding:"required"`
RedirectURI string `json:"redirect_uri" binding:"required"` RedirectURI string `json:"redirect_uri" binding:"required"`
State string `json:"state" binding:"required"` State string `json:"state" binding:"required"`
Nonce string `json:"nonce"`
} }
type OIDCServiceConfig struct { type OIDCServiceConfig struct {
@@ -216,9 +207,6 @@ func (service *OIDCService) Init() error {
for id, client := range service.config.Clients { for id, client := range service.config.Clients {
client.ID = id client.ID = id
if client.Name == "" {
client.Name = utils.Capitalize(client.ID)
}
service.clients[client.ClientID] = client service.clients[client.ClientID] = client
} }
@@ -300,7 +288,6 @@ func (service *OIDCService) StoreCode(c *gin.Context, sub string, code string, r
RedirectURI: req.RedirectURI, RedirectURI: req.RedirectURI,
ClientID: req.ClientID, ClientID: req.ClientID,
ExpiresAt: expiresAt, ExpiresAt: expiresAt,
Nonce: req.Nonce,
}) })
return err return err
@@ -362,7 +349,7 @@ func (service *OIDCService) GetCodeEntry(c *gin.Context, codeHash string) (repos
return oidcCode, nil return oidcCode, nil
} }
func (service *OIDCService) generateIDToken(client config.OIDCClientConfig, user repository.OidcUserinfo, scope string, nonce string) (string, error) { func (service *OIDCService) generateIDToken(client config.OIDCClientConfig, sub string) (string, error) {
createdAt := time.Now().Unix() createdAt := time.Now().Unix()
expiresAt := time.Now().Add(time.Duration(service.config.SessionExpiry) * time.Second).Unix() expiresAt := time.Now().Add(time.Duration(service.config.SessionExpiry) * time.Second).Unix()
@@ -380,20 +367,12 @@ func (service *OIDCService) generateIDToken(client config.OIDCClientConfig, user
return "", err return "", err
} }
userInfo := service.CompileUserinfo(user, scope)
claims := ClaimSet{ claims := ClaimSet{
Iss: service.issuer, Iss: service.issuer,
Aud: client.ClientID, Aud: client.ClientID,
Sub: user.Sub, Sub: sub,
Iat: createdAt, Iat: createdAt,
Exp: expiresAt, Exp: expiresAt,
Name: userInfo.Name,
Email: userInfo.Email,
EmailVerified: userInfo.EmailVerified,
PreferredUsername: userInfo.PreferredUsername,
Groups: userInfo.Groups,
Nonce: nonce,
} }
payload, err := json.Marshal(claims) payload, err := json.Marshal(claims)
@@ -417,14 +396,8 @@ func (service *OIDCService) generateIDToken(client config.OIDCClientConfig, user
return token, nil return token, nil
} }
func (service *OIDCService) GenerateAccessToken(c *gin.Context, client config.OIDCClientConfig, codeEntry repository.OidcCode) (TokenResponse, error) { func (service *OIDCService) GenerateAccessToken(c *gin.Context, client config.OIDCClientConfig, sub string, scope string) (TokenResponse, error) {
user, err := service.GetUserinfo(c, codeEntry.Sub) idToken, err := service.generateIDToken(client, sub)
if err != nil {
return TokenResponse{}, err
}
idToken, err := service.generateIDToken(client, user, codeEntry.Scope, codeEntry.Nonce)
if err != nil { if err != nil {
return TokenResponse{}, err return TokenResponse{}, err
@@ -444,18 +417,17 @@ func (service *OIDCService) GenerateAccessToken(c *gin.Context, client config.OI
TokenType: "Bearer", TokenType: "Bearer",
ExpiresIn: int64(service.config.SessionExpiry), ExpiresIn: int64(service.config.SessionExpiry),
IDToken: idToken, IDToken: idToken,
Scope: strings.ReplaceAll(codeEntry.Scope, ",", " "), Scope: strings.ReplaceAll(scope, ",", " "),
} }
_, err = service.queries.CreateOidcToken(c, repository.CreateOidcTokenParams{ _, err = service.queries.CreateOidcToken(c, repository.CreateOidcTokenParams{
Sub: codeEntry.Sub, Sub: sub,
AccessTokenHash: service.Hash(accessToken), AccessTokenHash: service.Hash(accessToken),
RefreshTokenHash: service.Hash(refreshToken), RefreshTokenHash: service.Hash(refreshToken),
ClientID: client.ClientID, ClientID: client.ClientID,
Scope: codeEntry.Scope, Scope: scope,
TokenExpiresAt: tokenExpiresAt, TokenExpiresAt: tokenExpiresAt,
RefreshTokenExpiresAt: refrshTokenExpiresAt, RefreshTokenExpiresAt: refrshTokenExpiresAt,
Nonce: codeEntry.Nonce,
}) })
if err != nil { if err != nil {
@@ -484,15 +456,9 @@ func (service *OIDCService) RefreshAccessToken(c *gin.Context, refreshToken stri
return TokenResponse{}, ErrInvalidClient return TokenResponse{}, ErrInvalidClient
} }
user, err := service.GetUserinfo(c, entry.Sub)
if err != nil {
return TokenResponse{}, err
}
idToken, err := service.generateIDToken(config.OIDCClientConfig{ idToken, err := service.generateIDToken(config.OIDCClientConfig{
ClientID: entry.ClientID, ClientID: entry.ClientID,
}, user, entry.Scope, entry.Nonce) }, entry.Sub)
if err != nil { if err != nil {
return TokenResponse{}, err return TokenResponse{}, err
@@ -586,8 +552,6 @@ func (service *OIDCService) CompileUserinfo(user repository.OidcUserinfo, scope
if slices.Contains(scopes, "email") { if slices.Contains(scopes, "email") {
userInfo.Email = user.Email userInfo.Email = user.Email
// We can set this as a configuration option in the future but for now it's a good idea to assume it's true
userInfo.EmailVerified = true
} }
if slices.Contains(scopes, "groups") { if slices.Contains(scopes, "groups") {
@@ -679,21 +643,10 @@ func (service *OIDCService) Cleanup() {
} }
func (service *OIDCService) GetJWK() ([]byte, error) { func (service *OIDCService) GetJWK() ([]byte, error) {
hasher := sha256.New()
der := x509.MarshalPKCS1PublicKey(&service.privateKey.PublicKey)
if der == nil {
return nil, errors.New("failed to marshal public key")
}
hasher.Write(der)
jwk := jose.JSONWebKey{ jwk := jose.JSONWebKey{
Key: service.privateKey, Key: service.privateKey,
Algorithm: string(jose.RS256), Algorithm: string(jose.RS256),
Use: "sig", Use: "sig",
KeyID: base64.URLEncoding.EncodeToString(hasher.Sum(nil)),
} }
return jwk.Public().MarshalJSON() return jwk.Public().MarshalJSON()

View File

@@ -1,8 +1,6 @@
package loaders package loaders
import ( import (
"os"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/traefik/paerser/cli" "github.com/traefik/paerser/cli"
"github.com/traefik/paerser/file" "github.com/traefik/paerser/file"
@@ -18,16 +16,11 @@ func (f *FileLoader) Load(args []string, cmd *cli.Command) (bool, error) {
return false, err return false, err
} }
// I guess we are using traefik as the root name (we can't change it) // I guess we are using traefik as the root name
configFileFlag := "traefik.experimental.configfile" configFileFlag := "traefik.experimental.configFile"
envVar := "TINYAUTH_EXPERIMENTAL_CONFIGFILE"
if _, ok := flags[configFileFlag]; !ok { if _, ok := flags[configFileFlag]; !ok {
if value := os.Getenv(envVar); value != "" { return false, nil
flags[configFileFlag] = value
} else {
return false, nil
}
} }
log.Warn().Msg("Using experimental file config loader, this feature is experimental and may change or be removed in future releases") log.Warn().Msg("Using experimental file config loader, this feature is experimental and may change or be removed in future releases")

View File

@@ -5,10 +5,9 @@ INSERT INTO "oidc_codes" (
"scope", "scope",
"redirect_uri", "redirect_uri",
"client_id", "client_id",
"expires_at", "expires_at"
"nonce"
) VALUES ( ) VALUES (
?, ?, ?, ?, ?, ?, ? ?, ?, ?, ?, ?, ?
) )
RETURNING *; RETURNING *;
@@ -46,10 +45,9 @@ INSERT INTO "oidc_tokens" (
"scope", "scope",
"client_id", "client_id",
"token_expires_at", "token_expires_at",
"refresh_token_expires_at", "refresh_token_expires_at"
"nonce"
) VALUES ( ) VALUES (
?, ?, ?, ?, ?, ?, ?, ? ?, ?, ?, ?, ?, ?, ?
) )
RETURNING *; RETURNING *;
@@ -74,6 +72,7 @@ WHERE "refresh_token_hash" = ?;
SELECT * FROM "oidc_tokens" SELECT * FROM "oidc_tokens"
WHERE "sub" = ?; WHERE "sub" = ?;
-- name: DeleteOidcToken :exec -- name: DeleteOidcToken :exec
DELETE FROM "oidc_tokens" DELETE FROM "oidc_tokens"
WHERE "access_token_hash" = ?; WHERE "access_token_hash" = ?;

View File

@@ -4,8 +4,7 @@ CREATE TABLE IF NOT EXISTS "oidc_codes" (
"scope" TEXT NOT NULL, "scope" TEXT NOT NULL,
"redirect_uri" TEXT NOT NULL, "redirect_uri" TEXT NOT NULL,
"client_id" TEXT NOT NULL, "client_id" TEXT NOT NULL,
"expires_at" INTEGER NOT NULL, "expires_at" INTEGER NOT NULL
"nonce" TEXT DEFAULT ""
); );
CREATE TABLE IF NOT EXISTS "oidc_tokens" ( CREATE TABLE IF NOT EXISTS "oidc_tokens" (
@@ -15,8 +14,7 @@ CREATE TABLE IF NOT EXISTS "oidc_tokens" (
"scope" TEXT NOT NULL, "scope" TEXT NOT NULL,
"client_id" TEXT NOT NULL, "client_id" TEXT NOT NULL,
"token_expires_at" INTEGER NOT NULL, "token_expires_at" INTEGER NOT NULL,
"refresh_token_expires_at" INTEGER NOT NULL, "refresh_token_expires_at" INTEGER NOT NULL
"nonce" TEXT DEFAULT ""
); );
CREATE TABLE IF NOT EXISTS "oidc_userinfo" ( CREATE TABLE IF NOT EXISTS "oidc_userinfo" (

View File

@@ -22,7 +22,3 @@ sql:
go_type: "string" go_type: "string"
- column: "sessions.ldap_groups" - column: "sessions.ldap_groups"
go_type: "string" go_type: "string"
- column: "oidc_codes.nonce"
go_type: "string"
- column: "oidc_tokens.nonce"
go_type: "string"