Secure Cookie Enforcement Breaks Logins Behind Proxy
See original GitHub issueExpected Behavior
Upgrading to @backstage/plugin-auth-backend
>= 0.6.0
and resolving all of the noted breaking changes should allow the app to continue to function.
Current Behavior
After upgrading (to 0.6.1
, though the change was made in 0.6.0
), we are unable to log into the application when deployed, as the connect.sid
cookie is no longer being set, and the openid-client
Passport Strategy requires sessions.
Possible Solution
The changes made in https://github.com/backstage/backstage/pull/8592, while good from a CodeQL standpoint, were breaking changes to anybody running behind a proxy that relies on express-session
for their Passport Strategy.
The breaking change is caused due to express-session
requiring the use app.set('trust proxy', 1);
in the express
app in order to run behind a proxy if enforcing secure cookies. (https://github.com/expressjs/session#cookiesecure)
There is not currently a way (that I am aware of) to set the trust proxy
policy when using the ServiceBuilder
, meaning that short of re-implementing the logic in the ServiceBuilder
, there is nothing that can be done in the current state.
My recommendation is to revert the secure cookie change (or make it configurable) until such time as the hooks are in place to set the trust proxy
policy in the underlying express
server.
Steps to Reproduce
- Rely on a Passport Strategy that requires sessions (such as OIDC)
- Have the Backstage app running behind a proxy (AWS ALB in our case).
- Update
@backstage/plugin-auth-backend
to >=0.6.0
.
Context
We are trying to keep our implementation up to date with the Backstage project, and this problem appeared after running backstage-cli versions:bump
.
Your Environment
OS: Linux 5.4.0-1063-azure - linux/x64
node: v14.17.6
yarn: 1.22.17
cli: 0.10.5 (installed)
Dependencies:
@backstage/app-defaults 0.1.3
@backstage/backend-common 0.10.2
@backstage/catalog-client 0.5.3
@backstage/catalog-model 0.9.8
@backstage/cli-common 0.1.6
@backstage/cli 0.10.5
@backstage/config-loader 0.9.1
@backstage/config 0.1.11
@backstage/core-app-api 0.2.1, 0.3.1
@backstage/core-components 0.8.3
@backstage/core-plugin-api 0.3.1, 0.4.1
@backstage/dev-utils 0.2.16
@backstage/errors 0.1.5
@backstage/integration-react 0.1.17
@backstage/integration 0.7.0
@backstage/plugin-api-docs 0.6.21
@backstage/plugin-app-backend 0.3.21
@backstage/plugin-auth-backend 0.6.1
@backstage/plugin-catalog-backend 0.19.4
@backstage/plugin-catalog-import 0.7.8
@backstage/plugin-catalog-react 0.6.10
@backstage/plugin-catalog 0.7.7
@backstage/plugin-cost-insights 0.11.16
@backstage/plugin-explore-react 0.0.9
@backstage/plugin-explore 0.3.24
@backstage/plugin-github-actions 0.4.30
@backstage/plugin-graphiql 0.2.26
@backstage/plugin-org 0.3.33
@backstage/plugin-permission-common 0.3.0
@backstage/plugin-permission-react 0.2.1
@backstage/plugin-proxy-backend 0.2.15
@backstage/plugin-scaffolder-backend-module-cookiecutter 0.1.7
@backstage/plugin-scaffolder-backend 0.15.19
@backstage/plugin-scaffolder-common 0.1.2
@backstage/plugin-scaffolder 0.11.17
@backstage/plugin-search 0.5.4
@backstage/plugin-shortcuts 0.1.18
@backstage/plugin-sonarqube 0.2.11
@backstage/plugin-tech-radar 0.5.1
@backstage/plugin-techdocs-backend 0.12.2
@backstage/plugin-techdocs 0.12.13
@backstage/plugin-user-settings 0.3.15
@backstage/search-common 0.2.1
@backstage/techdocs-common 0.11.2
@backstage/test-utils 0.2.1
@backstage/theme 0.2.14
@backstage/types 0.1.1
@backstage/version-bridge 0.1.1
Issue Analytics
- State:
- Created 2 years ago
- Comments:6 (5 by maintainers)
Thank you for reporting, and sorry for the breakage!
So if I understand the feature from
express-session
correctly, it’s avoiding sending cookies back in HTTP requests in case someone is snooping in on those? It seems like a bit of an overly defensive check since if you’re worried about that you’d usually enforce HTTPS ahead of the session handling.I think it makes sense to revert the secure cookie change for now tbh, as we’re not storing anything particularly sensitive just yet so not too critical that it is available. Another option could be to use the
'auto'
option for now, as that will still let people use secure cookies in some cases, but it won’t work in the proxy case. Yet another option is to introduce something like abackend.trustProxy
config, it won’t fix the breakage but is probably closer to the state that we want to be at.Regarding access to the express app, we’ve pretty much settled that the
ServiceBuilder
is operating at the wrong abstraction level and needs to be broken down into pieces that compose better. Not a short-term fix ofc, but something we’re likely to look at this spring.As a workaround for now you could perhaps add a middleware before the auth backend that sets
req.secure
?Didn’t test the above so I’m not sure if
req.secure
is writable, other options arereq.connection.encrypted
andreq.headers['x-forwarded-proto'] = 'https'
, basically something that makes the check at https://github.com/expressjs/session/blob/66634e9f77132a444dfda7e279a399054e3b28df/index.js#L623 passI was able to do a workaround by registering the middleware in the
authRouter
, virtually identical to the setup in theplugin-auth-backend
router config, except changing the secure cookie toauto
. I wasn’t sure what (if any) impact having theexpress-session
middleware registered twice would have, but it would appear (at least initially) there is none.I’ll put this in place until there is a more permanent resolution to this issue. Thanks for the assistance!