Skip to content

[BUG] Safe redirects fail when using private DNS zones without a public suffix #1006

Description

@cirogargatagli

Describe the Bug

When using a private DNS zone without a public suffix (for example home), TinyAuth derives the cookie domain as the full hostname instead of the parent domain.

Example:

APPURL=https://tinyauth.home

Results in:

CookieDomain = .tinyauth.home

instead of:

CookieDomain = .home

Because isRedirectSafe() validates redirects against runtime.CookieDomain, redirects to sibling subdomains are rejected even when they are configured as applications.

This causes redirects such as:

https://app.home

to be rejected with:

Unsafe redirect URI detected, ignoring

How to Reproduce

  1. Configure TinyAuth with:

APPURL=https://tinyauth.home

  1. Configure an application:

TINYAUTH_APPS_HOMEPAGE_CONFIG_DOMAIN=app.home

  1. Protect https://app.home using Caddy ForwardAuth.

  2. Authenticate using OAuth.

  3. After successful login TinyAuth redirects to:

https://tinyauth.home/continue?redirect_uri=https://app.home/

  1. TinyAuth rejects the redirect with:

Unsafe redirect URI detected

Expected Behavior

When subdomains are enabled, sibling subdomains within the same private DNS zone should be considered safe redirects.

For example:

APPURL=https://tinyauth.home

should allow redirects to:

https://app.home
https://jellyfin.home
https://immich.home

just as public domains already work.

Currently this only works for domains with a public suffix (example.com), but not for private DNS zones commonly used in homelabs.

Additional Context

The issue appears to originate from GetCookieDomain().

For APPURL=https://tinyauth.home, hostname becomes:

tinyauth.home

Since len(parts) == 2, the function immediately returns the hostname instead of the parent domain.

As a consequence:

runtime.CookieDomain = tinyauth.home

and isRedirectSafe() rejects redirects to sibling subdomains because they are not subdomains of tinyauth.home.

The existing unit tests for isRedirectSafe() indicate that sibling subdomains are expected to work when the cookie domain is the parent domain.

Logs

WRN Unsafe redirect URI detected, ignoring redirect_uri=https://app.home/

Operating System

Debian 13

Browser

Chrom

Tinyauth Version

v5.0.7

Docker Version (if applicable)

29.4.2

Human Written Confirmation

  • I confirm this issue was written by me and not generated by an LLM or AI assistant.

Activity

  1. dosubot commented on Jul 15, 2026

    @dosubot

    Hi @cirogargatagli! I'm Dosu and I'm helping the Tinyauth team.

    This is a valid bug. The root cause is exactly as you identified — in GetCookieDomain() [1], when the hostname has exactly 2 parts (like tinyauth.home), the function always returns the full hostname unchanged, regardless of whether SubdomainsEnabled is true. The len(parts) == 2 branch short-circuits before any subdomain stripping can happen:

    For tinyauth.home, parts = ["tinyauth", "home"], so len(parts) == 2 triggers immediately, returning tinyauth.home as the cookie domain. Then isRedirectSafe() [2] checks whether redirect targets like app.home end with .tinyauth.home — which they don't — so they're rejected.

    For this to work as expected, the cookie domain should be .home so that app.home, jellyfin.home, etc. all pass the subdomain suffix check. The fix would need to handle the case where a 2-part hostname with subdomains enabled and a private (non-public-suffix) TLD should strip the leftmost label, similar to how 3+-part hostnames are handled.

    There is currently no configuration option to manually override the cookie domain [3] — it's always derived automatically from AppURL. A related discussion about OAuth with private .home domains was raised recently in Discussion #994, and several recent PRs have improved homelab support (PR #710, PR #950, PR #1000), but this specific edge case with 2-part private hostnames wasn't addressed.

    To reply, just mention @dosu.


    Share context across your team and agents. Try Dosu.

    Leave Feedback Learn about tinyauth with Dosu Add Dosu to your team

  2. steveiliop56 commented on Jul 15, 2026

    @steveiliop56
    Member

    @cirogargatagli This is expected behavior. Tinyauth is not designed to set cookies for .home, .lan or any TLD. We only allow domains like tinyauth.home to pass the check in case you want your apps to be under app.tinyauth.home. Ideally you would want to have Tinyauth under tinyauth.foo.home and your app under app.foo.home following the recommended domain configuration in the getting started guide.

  3. cirogargatagli commented on Jul 21, 2026

    @cirogargatagli
    Author

    Thanks for the clarification.

    I understand the security concern and the current behavior makes sense for public domains.

    Would it be possible to add an explicit configuration override for advanced/private DNS setups?

    For example:

    TINYAUTH_COOKIE_DOMAIN=".home"

    or:

    TINYAUTH_COOKIE_DOMAIN="home"

    The default behavior could remain unchanged, but users running private DNS zones (homelabs, internal domains, split DNS, etc.) could manually define the cookie scope.

    The administrator would be responsible for ensuring that the domain is controlled and trusted.

    This would allow setups like:

    tinyauth.home
    jellyfin.home
    immich.home

    to share the same authentication session without requiring an additional artificial parent domain.

    Something similar to how many reverse proxies allow explicit cookie domain configuration would be very useful.

    Thanks!

  4. steveiliop56 commented on Jul 21, 2026

    @steveiliop56
    Member

    Unfortunately this is not possible. The public suffix list is not only used by Tinyauth but by browsers as well. This means that even if I allowed Tinyauth to set cookies for .home, browsers would immediately ignore it. I suggest either buying a domain name or just using something like app.lab.home.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions