Skip to content

Sign-in options

ShipLean supports email and password sign-in by default. You can instead let an identity-aware reverse proxy sign people in. In either mode, users still need project membership before they can access its work.

Sign in with the email address and password that an instance admin gave you. A one-time password sends you to the password-change form before you can do anything else.

Ten incorrect passwords lock the account for 15 minutes. ShipLean also refuses more than 20 attempts for one email address in 15 minutes. That refusal looks the same as a wrong password. A separate limit allows 30 login requests per minute from each client address. Requests over that limit receive a rate-limit response. Set the trusted proxy addresses so ShipLean sees the real client address and applies these limits correctly. See reverse proxy settings.

The shiplean.auth cookie is HttpOnly and uses SameSite=Lax. It is Secure over HTTPS. It expires after 14 days without activity, and each active request extends the expiry. Changing a password or choosing Sign out other sessions ends sessions at once. Disabling an account or changing an admin-managed security setting also ends that account’s sessions. To sign out every other browser, use Sign out other sessions in your profile. Your current session stays active. A session on another instance may take up to a minute to notice an administrative change.

Signing out clears the cookie in the current browser. It does not invalidate a copied cookie by itself. If you think a cookie was stolen, change your password or sign out other sessions.

Use an identity proxy when it already signs people in and can send ShipLean a signed JWT. Token mode is recommended. On every request, ShipLean verifies the token’s signature, issuer, and expiry. It also verifies the audience when one is configured. Set the audience along with the issuer. Without an audience check, another token from the same issuer may be accepted.

The first request with a valid identity creates a ShipLean user. ShipLean adopts an existing user with the same email, and that user keeps its project memberships and history. Email matching ignores case. A disabled user stays disabled. After a successful proxy sign-in, ShipLean issues the same 14-day sliding cookie that it uses for password sign-in.

Set SHIPLEAN_ADMIN_EMAIL to the identity’s email address. If that user already exists, ShipLean makes them an instance admin at startup, provided no instance admin exists. If the user does not exist yet, ShipLean makes them an admin on their first proxy sign-in. In proxy mode, ShipLean ignores SHIPLEAN_ADMIN_PASSWORD and logs a warning. After an admin exists, the email setting has no effect.

Do not publish ShipLean’s port to the public network. Put it on a private network that only the reverse proxy can reach. Set SHIPLEAN_TRUSTED_PROXIES to the address or CIDR range that ShipLean sees for that proxy. This prevents direct access to the backend, and it means forwarded client addresses can be trusted.

Configure the proxy to skip its login check for these paths. Each path uses its own credentials or discovery behavior:

Path Why it bypasses the proxy login
/mcp MCP clients authenticate through the MCP OAuth flow.
/oauth/token, /oauth/register, /oauth/revoke These OAuth endpoints manage agent credentials.
/.well-known/ OAuth client discovery and metadata.
/api/webhooks/ GitHub and GitLab verify each delivery with a shared secret. The sender must post JSON.
/api/uploads/, /api/downloads/ MCP attachment transfer URLs carry their own short-lived credential in the path.

Keep /oauth/authorize behind the proxy, because a person must be signed in to approve an agent. A bypassed path can be reached without a proxy session. For attachment transfer URLs, the token in the path is the credential. An upload URL works once, for 10 minutes. A download URL works until it expires. Proxy middleware must pass these paths to ShipLean without requiring a login or adding proxy identity. Other protected routes still verify any identity token that ShipLean receives. See integrations for webhook setup.

In proxy mode, other authenticated /api writes must include a JSON body or the X-ShipLean-Client header, even when the proxy has already authenticated the request. Attachment upload URLs are the exception. Their short-lived token in the path is the credential, so they need no client header. GitHub and GitLab webhook deliveries use JSON.

Each example includes the ShipLean environment settings and the proxy configuration to adapt. Store secrets in your deployment’s secret store. The examples are standalone reference files. Download them from the repository.

When oauth2-proxy forwards directly to ShipLean, pass_access_token puts the access token in X-Forwarded-Access-Token. That header works only when the access token is a signed JWT with an email claim. If the provider issues opaque access tokens or omits the email claim, pass the ID token as Authorization: Bearer … instead. Configure the matching ShipLean header and audience. With oauth2-proxy’s auth_request integration, also enable set_xauthrequest, and copy X-Auth-Request-Access-Token to the upstream header.

The example uses the current skip_auth_routes option. It exempts only MCP, OAuth token-management, discovery, webhook, and attachment-transfer paths. Do not use a broad exemption for all /oauth/ routes.

Files: oauth2-proxy.cfg and ShipLean environment values. See the oauth2-proxy configuration reference for pass_access_token, set_xauthrequest, and skip_auth_route.

Cloudflare Access sends the signed application JWT in Cf-Access-Jwt-Assertion. Use your team domain as the issuer, the Access certs endpoint for JWKS, and your application’s AUD tag as the audience. Access does not send a name claim, so ShipLean names new users after the part of their email address before @.

Create Access policies for the bypass paths in cloudflare-access.md, including /api/uploads/* and /api/downloads/*. A bypass means those paths do not require a user login at Access. The backend must stay private, and ShipLean still applies its own endpoint checks. Cloudflare recommends validating the assertion header against the signing keys published at the certs URL.

File: cloudflare-access.md. See Cloudflare’s JWT validation guide and Access policies.

Enable pass_identity_headers on the protected ShipLean route. Pomerium sends its signed assertion in X-Pomerium-Jwt-Assertion. Configure the matching issuer and audience for that route. Set SHIPLEAN_AUTH_PROXY_TOKEN_JWKS_URL to Pomerium’s published /.well-known/pomerium/jwks.json endpoint. Pomerium serves the JWKS directly. It does not serve an OIDC discovery document at the issuer’s /.well-known/openid-configuration path. The example uses the URI issuer format, so the issuer is https://shiplean.example.com/. It also defines route path patterns for the public bypass routes, including /api/uploads/{token} and /api/downloads/{token}.

Files: pomerium.yaml and ShipLean environment values. See Pomerium’s JWT identity verification, route path matching, JWT issuer format, and public access documentation.

Use this only if your proxy cannot send a signed token. Authelia’s trusted-header flow returns Remote-Email and Remote-Name to the reverse proxy. The reverse proxy must set them on its request to ShipLean. Set SHIPLEAN_TRUSTED_PROXIES to the reverse proxy’s address, not Authelia’s.

The NGINX example sets client_max_body_size 40m. NGINX defaults this request-body limit to 1 MB. A default-size MCP attachment takes about 33.4 MiB after base64 encoding. If you raise SHIPLEAN_ATTACHMENT_MAX_BYTES, raise the NGINX limit to at least the resulting base64 request cap, which is 4 × ceil(file_limit / 3) + 64 KiB. See the NGINX directive reference.

Files: authelia-nginx.conf and ShipLean environment values. See Authelia’s trusted-header SSO and NGINX integration documentation.

Set SHIPLEAN_AUTH_PROXY_SIGN_OUT_URL to the identity proxy’s sign-out URL. It can be a path such as /oauth2/sign_out or an absolute HTTP or HTTPS URL. Without it, ShipLean hides Sign out, because the proxy would sign the person in again right away. Sign out other sessions stays available. It invalidates the other ShipLean cookies.

Set SHIPLEAN_AUTH_PROXY_EMAIL_HEADER to the trusted email header. SHIPLEAN_AUTH_PROXY_NAME_HEADER is optional. ShipLean reads these headers only from loopback addresses and from addresses listed in SHIPLEAN_TRUSTED_PROXIES. It ignores them from any other peer. Never set the email header and the token header together. Header mode does not check that the email address is verified. Proxy sign-in also has no password, password-change, or one-time-password flows.

For token mode, set SHIPLEAN_AUTH_PROXY_TOKEN_HEADER and SHIPLEAN_AUTH_PROXY_TOKEN_ISSUER, which is required. ShipLean discovers the JWKS URL from the issuer unless you set it explicitly. SHIPLEAN_AUTH_PROXY_TOKEN_AUDIENCE is optional, but you should set it. The email and name claims default to email and name. A present email_verified claim must be true. ShipLean accepts a token that has no email_verified claim. See all sign-in settings.