Scrydon
PlatformIdentity Provider (IdP)

Gate an internal site with oauth2-proxy

Put any internal tool, dashboard, or static site behind Scrydon SSO with oauth2-proxy — no application code changes — using Scrydon as the OIDC identity provider.

Have an internal tool, dashboard, wiki, or static site you want behind your Scrydon login? You don't need to add authentication code to it. Put oauth2-proxy in front of it and point it at your Scrydon identity provider. oauth2-proxy runs the OIDC login, sets its own session cookie on your site's domain, and only forwards requests from signed-in users — restricted to whoever you allow (for example, everyone with an @your-company.com email).

This is the standard "SSO for a site that has no SSO" pattern, and because Scrydon is a full OIDC provider, the same approach works with any OIDC-compatible proxy (Authelia, Pomerium, Traefik + oauth2-proxy, NGINX auth_request, …). This guide uses oauth2-proxy.

oauth2-proxy sets its own cookie on your site's hostname, so it works no matter how Scrydon itself is hosted (subpath or subdomain routing) and no matter which subdomain your site lives on. Your site never sees the Scrydon session cookie directly.

Before you start

You need three things from Scrydon:

Register an org-scoped confidential client

Follow Register an OAuth client (Mini App). When you create it, set:

  • ScopeOrganization · SSO only. Your gateway only signs users in — it doesn't call Scrydon APIs, so it needs no workspace and gets a single org-wide client restricted to the identity scopes (openid, profile, email).
  • Client TypeConfidential · client secret. oauth2-proxy runs server-side and authenticates to the token endpoint with a client_secret.
  • Redirect URIhttps://<your-site>/oauth2/callback (oauth2-proxy's callback path). Example: https://docs.internal.example.com/oauth2/callback.

You'll receive a client ID and a client secret.

The client secret is shown exactly once, right after registration — copy it immediately. Scrydon stores only a hash, so it cannot be retrieved later. If you lose it, use Rotate in the app's detail panel to mint a new one (the old secret stops working the moment you rotate).

Copy your Discovery URL

Open Settings → Platform → Identity and copy the OIDC Discovery URL. It looks like https://<your-auth-host>/api/auth/.well-known/openid-configuration. oauth2-proxy only needs the issuer — that's the same URL without the /.well-known/openid-configuration suffix, e.g. https://<your-auth-host>/api/auth.

Always copy the host from the Identity tab — it is tenant-specific. Don't guess it.

oauth2-proxy signs its own cookie with a secret that must be exactly 16, 24, or 32 bytes:

openssl rand -base64 32 | head -c 32; echo

Configure oauth2-proxy

oauth2-proxy is configured entirely through flags or OAUTH2_PROXY_* environment variables. The minimal OIDC setup:

oauth2-proxy \
  --provider=oidc \
  --oidc-issuer-url="https://<your-auth-host>/api/auth" \
  --client-id="<your-client-id>" \
  --client-secret="<your-client-secret>" \
  --redirect-url="https://<your-site>/oauth2/callback" \
  --scope="openid email profile" \
  --email-domain="your-company.com" \
  --cookie-secret="<cookie-secret>" \
  --cookie-secure=true \
  --upstream="http://127.0.0.1:8080/" \
  --http-address="0.0.0.0:4180" \
  --reverse-proxy=true \
  --skip-provider-button=true

Key options:

OptionWhy
--oidc-issuer-urlThe issuer from your Discovery URL. oauth2-proxy fetches everything else automatically.
--redirect-urlMust exactly match the Mini App Redirect URI.
--email-domainAllow-list. Repeat the flag (or comma-separate) for several domains; * allows any signed-in Scrydon user.
--upstreamYour actual site/tool. oauth2-proxy reverse-proxies authenticated traffic here.
--reverse-proxy=trueSet when running behind your own ingress/load balancer so X-Forwarded-* is trusted.
--skip-provider-button=trueGo straight to the Scrydon login instead of an intermediate "Sign in with…" page.

To restrict to specific people rather than a whole domain, drop --email-domain and use --authenticated-emails-file=/path/to/emails.txt (one address per line).

Deploy it

Docker Compose

services:
  my-internal-site:
    image: my-internal-site:latest
    # no auth code needed in your app

  oauth2-proxy:
    image: quay.io/oauth2-proxy/oauth2-proxy:v7.7.1
    command:
      - --provider=oidc
      - --oidc-issuer-url=https://<your-auth-host>/api/auth
      - --client-id=<your-client-id>
      - --client-secret=<your-client-secret>
      - --redirect-url=https://docs.internal.example.com/oauth2/callback
      - --scope=openid email profile
      - --email-domain=your-company.com
      - --cookie-secret=<cookie-secret>
      - --cookie-secure=true
      - --http-address=0.0.0.0:4180
      - --reverse-proxy=true
      - --skip-provider-button=true
      - --upstream=http://my-internal-site:80/
    ports:
      - "4180:4180"

Point your TLS terminator / DNS for docs.internal.example.com at the oauth2-proxy container's :4180.

Kubernetes (reverse-proxy in front of a Service)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-site-oauth2-proxy
spec:
  replicas: 1
  selector:
    matchLabels: { app: my-site-oauth2-proxy }
  template:
    metadata:
      labels: { app: my-site-oauth2-proxy }
    spec:
      containers:
        - name: oauth2-proxy
          image: quay.io/oauth2-proxy/oauth2-proxy:v7.7.1
          args:
            - --provider=oidc
            - --oidc-issuer-url=https://<your-auth-host>/api/auth
            - --redirect-url=https://docs.internal.example.com/oauth2/callback
            - --scope=openid email profile
            - --email-domain=your-company.com
            - --upstream=http://my-site.default.svc.cluster.local:80/
            - --http-address=0.0.0.0:4180
            - --cookie-secure=true
            - --reverse-proxy=true
            - --skip-provider-button=true
          env:
            - name: OAUTH2_PROXY_CLIENT_ID
              valueFrom: { secretKeyRef: { name: my-site-sso, key: client-id } }
            - name: OAUTH2_PROXY_CLIENT_SECRET
              valueFrom: { secretKeyRef: { name: my-site-sso, key: client-secret } }
            - name: OAUTH2_PROXY_COOKIE_SECRET
              valueFrom: { secretKeyRef: { name: my-site-sso, key: cookie-secret } }
          ports:
            - containerPort: 4180
---
apiVersion: v1
kind: Service
metadata:
  name: my-site-oauth2-proxy
spec:
  selector: { app: my-site-oauth2-proxy }
  ports:
    - port: 4180
      targetPort: 4180

Then route your Ingress for docs.internal.example.com to the my-site-oauth2-proxy Service on port 4180 (instead of straight to your app). oauth2-proxy owns the /oauth2/* paths and proxies everything else to your upstream once the user is authenticated.

Verify

  1. Open https://docs.internal.example.com/ in a fresh browser session.
  2. You should be redirected to your Scrydon login.
  3. Sign in with an allowed account → you land on your site.
  4. An account outside the allow-list is rejected after login.

Troubleshooting

SymptomCause / fix
invalid_client at the login screenThe client ID/secret don't match a registered app, or the secret was rotated since you configured the proxy.
Redirects back to login in a loop--cookie-secure=true but the site is served over plain HTTP, or TLS isn't terminated in front of oauth2-proxy. Serve over HTTPS.
redirect_uri mismatch error--redirect-url must exactly equal the Mini App Redirect URI, including scheme and the /oauth2/callback path.
Rejected right after loginThe account's email isn't in --email-domain / the allowed-emails file.
cookie secret … must be 16, 24, or 32 bytesRegenerate the cookie secret to exactly 32 bytes.
"email not verified" rejectionThe account's email isn't verified. Verify it, or (lower assurance) add --insecure-oidc-allow-unverified-email=true.
On this page

On this page