Skip to content

feat(gateway): refuse to start without user authentication unless allow_unauthenticated_users is set #4814

Description

@mrunalp

User Story

I operate OpenShell gateways. I need a gateway with no authentication configured to refuse to start, unless I have explicitly opted into unauthenticated access, so that a missing or mistyped auth config can't silently expose an admin-level API.

Problem Statement

If a gateway has no OIDC issuer, no mTLS user auth, no operator auth and no gateway_jwt, no authenticator chain is built. Every request is then given the unauthenticated-local-dev principal, which holds openshell-admin, openshell-user and openshell:all (crates/openshell-server/src/multiplex.rs:1207-1211). Because no RBAC policy exists without OIDC, every caller is a platform admin. This happens even when allow_unauthenticated_users is false. The only signal is a startup warn! saying "the gateway has no authentication mechanism" (crates/openshell-server/src/cli.rs:761-770).

In other words, leaving allow_unauthenticated_users at false doesn't take effect in exactly the case it should.

Impact / Why This Matters

  • A partial or mistyped config fails open. For example, an OIDC table under the wrong key, or a TLS client CA path that never got set, produces an admin API that anyone who can reach the port can use.
  • A warning is easy to miss in container logs, and nothing at runtime reflects the exposure.
  • Dev setups already opt in explicitly: tasks/scripts/gateway.sh, deploy/docker/gateway.toml and the CI Helm values all set allow_unauthenticated_users = true. A fail-closed default would therefore cost local development nothing.

Proposed Design

  • If the gateway would start with no user authentication mechanism (no OIDC, no mTLS user auth, no operator auth, no gateway_jwt) and allow_unauthenticated_users is not true, startup fails with a configuration error. The error names the missing mechanisms and the explicit opt-in.
  • With allow_unauthenticated_users = true, behaviour is unchanged: the local-dev principal is used and the existing warning is logged.
  • Gateways with any authenticator configured are unaffected. They already reject credential-less users unless allow_unauthenticated_users is set.

Suggested UX (if applicable)

$ openshell-gateway --config gateway.toml
Error: gateway has no user authentication configured

  No OIDC issuer, mTLS user auth, operator auth, or gateway_jwt is set, so every
  caller would be granted platform-admin access.

  Configure one of [openshell.gateway.oidc], [openshell.gateway.mtls_auth], or
  [openshell.gateway.gateway_jwt], or explicitly opt in for trusted local
  development:

    [openshell.gateway.auth]
    allow_unauthenticated_users = true

Acceptance Criteria

  • With no auth mechanism and allow_unauthenticated_users unset or false, the gateway exits non-zero at startup with the error above and binds no port.
  • With allow_unauthenticated_users = true and no auth mechanism, the gateway starts and behaves exactly as today.
  • Gateways with OIDC, mTLS, operator auth or gateway_jwt start and authenticate exactly as today.
  • mise run dev tasks, the Docker Compose gateway, Helm CI values and the e2e suites still start.
  • The release notes call out the behaviour change, and docs/how-it-works/gateways/configuration.mdx documents it.

Alternatives Considered

  • Keep the warning and add openshell doctor security (feat(cli): openshell doctor security posture check for gateways #4477). A posture check helps operators who run it, but it doesn't stop a misconfigured gateway from serving an admin API. The two are complementary.
  • Default to rejecting credential-less requests at runtime instead of failing at startup. This would also close the hole, but it gives a running gateway that refuses every user call with a less obvious cause. Failing at startup surfaces the misconfiguration where it was made.

Agent Investigation

  • When credentials are missing and an authenticator chain exists, the gateway already fails closed unless allow_unauthenticated_users is set (multiplex.rs:1158-1180). The no-chain branch at multiplex.rs:1205-1211 is the only path that injects the admin principal without the opt-in.
  • The startup condition already exists as a warning in cli.rs:761-770 and can become the error.

Activity

  1. TaylorMutch commented on Oct 22, 2026

    @TaylorMutch
    Collaborator

    I'll take this one

  2. self-assigned this
    on Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:gatewayGateway server and control-plane workstate:acceptedA maintainer decided OpenShell should pursue this issuetopic:securitySecurity issues

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions