Express quick start example fails due to incorrect whoami request port
Preflight checklist
- [X] I could not find a solution in the existing issues, docs, nor discussions.
- [X] I agree to follow this project's Code of Conduct.
- [X] I have read and am following this repository's Contribution Guidelines.
- [X] This issue affects my Ory Cloud project.
- [ ] I have joined the Ory Community Slack.
- [ ] I am signed up to the Ory Security Patch Newsletter.
Describe the bug
https://www.ory.sh/docs/guides/protect-page-login/expressjs#require-login-to-access-the-home-page
.toSession seems to want to make a call to /.ory/.../whoami through the proxy. However i think axios wants to make this call at localhost port 80, leading to the following error
[0] Error: connect ECONNREFUSED ::1:80
[0] at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1161:16) {
[0] errno: -61,
[0] code: 'ECONNREFUSED',
[0] syscall: 'connect',
[0] address: '::1',
[0] port: 80,
[0] config: {
[0] url: '/.ory/sessions/whoami',
[0] method: 'get',
[0] headers: {
[0] Accept: 'application/json, text/plain, */*',
[0] Cookie: '__cflb=0pg1QYeUHkKyPHC72r3PJ1fj2WK6WMwzqHhgHXum; csrf_token_a5d02dd42b4ef065bbbd5ed674b19b5d2e6dc4f2a3e4acc8684f15ae24c19b97=JGnPuz6b+Jqy10PCRqwvR2dgrw2UXJ1K96SHlDCWSag=; ory_session_greatgoldwasserlbe7q6kfiv=MTY1MDMwMTk3MnxnSmhfWkRBM2lSVkJwX1JpY0oyYUpGV21lbm9jel9PWkl0a2RwVzJ0eGRJT1lLSm9JMlZUUjZyc0xYalJyMS1naC0zS2FleWxaM0lsT0pxMjNSRkRGQVlTbjU2ZUtaYTAxVEQ4MWxoZUlfcFR6Rml3YkM4bE1XdmVQQms3SjhZR0NaQ2UwMklqcXc9PXygWBBkEKzVhZUiBc1uzDEO0KmKCRdEUET-qIkFgs5LkQ==',
So we need to tell axios it should match the port we used when we started the proxy
"dev:proxy": "ory proxy --no-jwt --port 8000 http://localhost:8001/"
some solutions at the doc level
- insist we pass a proxy to axios in development environments
.toSession(undefined, req.header('cookie'), {
proxy: {
host: 'localhost',
port: 8000
}
})
- in development make sure we pass the full base path inclusive of port
const ory = new orySDK.V0alpha2Api(
new orySDK.Configuration(
// @ts-ignore
{basePath: 'http://localhost:8000/.ory',
baseOptions: {
withCredentials: true
}
}
)
)
These both work and i am also wondering
- if there is a way to detect if we are proxying and on what port so this could be done automatically somehow
- perhaps having this as an envar like the sdk url
https://github.com/ory/docs/blob/master/code-examples/protect-page-login/expressjs/routes/index.js
Reproducing the bug
- follow example on https://www.ory.sh/docs/guides/protect-page-login/expressjs
- register a user
- observe redirect loop once user registered due to failing whoami request
Relevant log output
No response
Relevant configuration
No response
Version
"@ory/client": "^0.0.1-alpha.167"
On which operating system are you observing this issue?
macOS
In which environment are you deploying?
Ory Cloud
Additional Context
No response
also happy to contribute the fix!!
that would be lovely, @Benehiko can you please assist?
Strange, we have e2e tests for this which are green on master, so not sure how this is failing here. Maybe there is a missing configuration somewhere. https://github.com/ory/docs/blob/master/tests/playwright/protect-page-login.spec.ts
Are the e2e tests using the exact same instructions as the OP suggested?
I believe so, since we check that the session exists afterwards containing the registered email here.
I don't see how we would have a redirect loop then if we return to the application "dashboard" showing the session information.
So do the docs or e2e tests need to be adjusted to follow the same commands?
We should just update the documentation, it seems we don't give enough in the step by step process to build the example correctly. We should also indicate that the sdk will call whichever url the browser is currently requesting from, e.g. browser is on http://localhost:4000 and thus the sdk will match that. So if this is setup incorrectly, e.g. the node application is running on localhost:80 and the browser is requesting the node application directly, we will end up in an error state.
@ammanvedi could you please copy the code given on GitHub directly? You can find the project here https://github.com/ory/docs/tree/master/code-examples/protect-page-login/expressjs
Try reproduce the error and take note of the differences in code that you currently have vs the GitHub clone. I think the steps given in the guide isn't specific enough.
@Benehiko sure i will try !
Sorry for the delay i will try this tonight
Okay i have tried this and here are my steps
git clone https://github.com/ory/docs.git
cd docs/code-examples/protect-page-login/expressjs
npm install
i then edit the proxy npm script so it contains the sdk url envar which is the same as it would be in the tests
"proxy": "ORY_SDK_URL=https://playground.projects.oryapis.com ory proxy --no-jwt --port 4000 http://localhost:3000/"
then
npm run proxy
npm run start
then in my browser i visit http://localhost:4000/
and this works fine. i can sign up etc.
However if i use my own sdk url
"proxy": "ORY_SDK_URL=https://ABCDEF.projects.oryapis.com ory proxy --no-jwt --port 4000 http://localhost:3000/"
then it breaks;
https://user-images.githubusercontent.com/1761300/165363228-39436e9a-0900-49da-96ff-90058bae363c.mov
WHY?
i think it has something to do with
// code-examples/protect-page-login/expressjs/routes/index.js
baseUrl: '/.ory'
this baseUrl property is not specified by the sdk config, the config actually accepts basePath. When basePath is not found the default becomes
// code-examples/protect-page-login/expressjs/node_modules/@ory/client/base.ts
export const BASE_PATH = "https://playground.projects.oryapis.com".replace(/\/+$/, "");
this.basePath = configuration.basePath || this.basePath;
i think this could be why the tests work because the base path that gets set is not a local path, its an absolute url, because it gets defaulted to that, and the SDK_URL in tests is playground also
SOLUTION
the solution could be to make the following change
var ory = new sdk.V0alpha2Api(
new sdk.Configuration({
basePath: 'http://localhost:4000/.ory'
})
)
- baseUrl -> basePath
- /.ory -> 'http://localhost:4000/.ory'
would probably need to match the ports in express app to the test setup so this url work in both places
cd code-examples/protect-page-login/expressjs && \
PORT=4002 npm run start &
ory proxy --no-jwt --port 3002 http://localhost:4002/ &
was a bit of rabbit hole but would appreciate a sanity check on this
Hi @ammanvedi
Thank you for the detailed write-up. I will take a look today at it using the steps you provided
It seems like the SDK is not getting the current origin the browser is on e.g. localhost:4000 and so it defaults to localhost:80 which obviously doesn't have anything hosted on it and thus the express middleware ends up in a redirect loop trying to go back to the login screen.
Here is an example of the error that is caught just before redirecting to /.ory/ui/login.
Error: connect ECONNREFUSED 127.0.0.1:80
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1187:16) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 80,
config: {
url: '/.ory/sessions/whoami',
We need to update the example to something like the go example
https://github.com/ory/docs/blob/master/code-examples/protect-page-login/go/main.go#L16-L24
Nice find, thank you @Benehiko ! Could you make those changes to the example? :)
Yeah I'll work on that soon, could you assign me to the issue?