Skip to content

[Feature Request] Support explicit 'BaseUrl' configuration to replace unreliable request inspection #185

Description

@leric

https://github.com/logto-io/go/blob/97fd30d2fad12575f34e76895026465130948f0a/client/util.go#L11C1-L13C2

The current implementation of GetOriginRequestUrl in client/util.go relies on inspecting HTTP headers (like X-Forwarded-Proto and Host) to deduce the original request URL.

This approach is fragile and problematic for several reasons:

  • Unreliable behind Reverse Proxies: In complex architectures (e.g., Cloudflare -> AWS ALB -> Nginx -> Go App), the X-Forwarded-Proto header may contain multiple values (e.g., https,http) or be modified unexpectedly. The current naive splitting logic can easily fail to determine the correct scheme.
  • Security Risks: Relying on the Host header or untrusted X-Forwarded-* headers can leave the application vulnerable to Host Header Injection attacks, potentially generating malicious redirect URIs.
  • Violation of 12-Factor App Principles: An application should know its public address via explicit configuration (environment variables), not by guessing from incoming requests.

I recently encountered an issue where the SDK incorrectly judged https vs http behind a multi-layer gateway, causing the OIDC redirect loop to fail.


I propose adding an optional BaseUrl (or ExternalUrl) field to the logto.Config struct (or the Client constructor options).

If this field is provided, the SDK should use it directly to construct the Redirect URI, bypassing the GetOriginRequestUrl logic entirely.

Example usage:

logtoConfig := &logto.LogtoConfig{
    Endpoint:  "https://logto.dev",
    AppId:     "foo",
    AppSecret: "bar",
    // New proposed field
    BaseUrl:   "https://my-app.com", 
}
// OR via constructor options if preferred

This change is fully backward compatible:

If BaseUrl is set -> Use it.

If BaseUrl is empty -> Fallback to the current GetOriginRequestUrl logic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions