Admin login loops back to the login screen
You log in, the admin panel flashes, and you are back at the login screen. The credentials are right. In self-hosted deployments this is nearly always a cookie that never gets set: Strapi is behind an HTTPS reverse proxy, does not know the request was HTTPS, and refuses to set the secure session cookie. Before changing config, open the network tab and watch the login POST. Whether there is a Set-Cookie on the response, and whether it survives to the next request, tells you which of the causes below you are in.
00· Before anything
First: watch the login POST in the network tab
Open the browser network tab, attempt to log in, and read the login POST and the request that follows it. Three observations split every cause apart before you touch config.
No Set-Cookie on the login response points at the proxy, or at the v5 proxy syntax. A redirect_uri starting http:// in the request to your identity provider points at SSO. A cookie that is set and then absent on the very next request points at an admin served from a different host. Nothing changed yet, and three causes are already eliminated.
Likely causes · The order I check them
Cause 01 of 04
Self-hosted behind an HTTPS reverse proxy
Login succeeds, then bounces straight back to the login screen. Works over plain HTTP locally, fails once there is a proxy terminating TLS.
Look for Set-Cookie on the login POST response. If it is missing, Strapi decided the request was not secure and refused to set the cookie.
Behind a TLS-terminating proxy, Strapi sees an HTTP request and will not set a secure cookie unless you tell it to trust the proxy. It needs proxy.koa: true, and the proxy has to forward x-forwarded-proto.
Set proxy: { koa: true } in config/server, and make sure the proxy forwards x-forwarded-proto: https.
export default ({ env }) => ({
proxy: { koa: true },
url: env('PUBLIC_URL', 'https://admin.example.com'),
});proxy.koa is documented on the server configuration page, as is the note that trusting proxy headers is separate from url. The requirement that the proxy forward x-forwarded-proto is not in the docs; it is confirmed on maintainer issue strapi/strapi#24452 (shipped).
Cause 02 of 04
v4 proxy syntax carried into v5
You set proxy: true, exactly as an older guide or your v4 project did, and nothing changed.
proxy: true was the v4 form. v5 expects proxy: { koa: true }. The old key is silently ignored, so it looks configured and does nothing.
Change proxy: true to proxy: { koa: true } in config/server.
The v4 to v5 proxy change has its own breaking-changes page, which makes this fully citable. It is the detail most blog posts on this get wrong.
Cause 03 of 04
SSO: the OAuth callback comes out as http://
SSO login fails at the identity provider with a redirect-URI mismatch, and the redirect_uri in the request starts http://.
Read the request to the IdP in the network tab. An http:// redirect URI against an https:// registered URI is the mismatch.
Set an absolute https:// server url in config/server, and if the callback is still wrong, set url in config/admin as well.
The config/admin step is an observed workaround, in mild tension with the docs: the SSO docs point at getStrategyCallbackURL() and never show a hardcoded absolute URL, and the admin-panel docs imply an absolute server URL should be enough. Verify it against your setup rather than assuming it.
Cause 04 of 04
On 5.53.0, access_token stopped being appended to the OAuth callback
SSO worked, then broke after upgrading to 5.53.0. The integration that reads the token off the callback URL takes its no-token branch and bounces the user back to login.
On 5.53.0, access_token stopped being appended to the OAuth callback query string. Integrations reading it from the URL find nothing.
This is live and under investigation on strapi/strapi#27648. Check the issue's current status and fixed-in version before acting; if you are blocked, pin to a version before the change while it is resolved.
05
Two of the causes here are moving targets. The x-forwarded-proto requirement rests on a maintainer-confirmed issue rather than the docs, and the 5.53.0 callback change was unresolved at the time of writing. Check the current status of both before relying on them.
Likely causes · The order I check them
Cause 01 of 01
Admin on a different host from the API
The cookie is set on the login response and then absent on the very next request.
When the admin panel is served from a different host than the API and url / auth.domain are not set in config/admin, the session cookie is scoped to the wrong domain and never comes back.
Set url and, where the hosts differ, auth.domain in config/admin so the cookie is scoped to a domain the admin actually sends it back from.
07
What's documented, and what's observed
proxy.koa, the separation of proxy-header trust from url, and the requirement that admin cookies use HTTPS are all documented on the server configuration page. The v4 to v5 proxy syntax change has its own breaking-changes page. Two things are not documented: the exact x-forwarded-proto requirement, confirmed on maintainer issue strapi/strapi#24452, and the 5.53.0 callback change, tracked on strapi/strapi#27648. Treat those as observed and verify their status.
Common questions
That is the v4 syntax. Strapi 5 wants proxy: { koa: true } and silently ignores the old boolean form, so it looks configured but does nothing.
Watch the login POST in the network tab. A 200 with no Set-Cookie header means the credentials were fine and Strapi refused to set the session cookie, which is the proxy case.
Check whether you moved to 5.53.0. A change there stopped appending access_token to the OAuth callback, which breaks integrations that read the token off the URL. Confirm the current status of the tracking issue before pinning a version.
Diagnosed everything and still stuck?
S/01 — Performance & Architecture Rescue.
A fixed-scope week that finds the cause and fixes what's causing it.