external-auth-server: [BUG] uncaughtException: Cannot read properties of undefined (reading 'match')

Heyo!

I have a EAS installation running in a kubernetes cluster in HA-mode.

I have multiple providers/configurations hooked up to a keycloak instance for authenticating users for a SPA.

Direct sign-in using a keycloak user works. Signing in with a SSO backed by another keycloak instance also works. But a final SSO backed by Active directory seems to cause the EAS to crash with the following error:

uncaughtException: Cannot read properties of undefined (reading 'match')
TypeError: Cannot read properties of undefined (reading 'match')
    at Object.parse (/home/eas/app/node_modules/uri-js/dist/es5/uri.all.js:874:29)
    at OpenIdConnectPlugin.get_authorization_redirect_uri (/home/eas/app/src/plugin/oauth/index.js:2514:27)
    at handle_auth_callback_request (/home/eas/app/src/plugin/oauth/index.js:1649:45)
    at OpenIdConnectPlugin.verify (/home/eas/app/src/plugin/oauth/index.js:1924:29)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async processPipeline (/home/eas/app/src/server.js:399:13)

I changed the log-level to silly and reproduced the error:

[
  {
    "jsonPayload": {
      "message": "verify request details: {\"url\":\"/verify?config_token_store_id=<id>&config_token_id_query_engine=jq&config_token_id_query=.parentRequestInfo.parsedUri.host+%7C+split%28%22.%22%29%5B0%5D\",\"params\":{},\"query\":{\"config_token_store_id\":\"<id>\",\"config_token_id_query_engine\":\"jq\",\"config_token_id_query\":\".parentRequestInfo.parsedUri.host | split(\\\".\\\")[0]\"},\"http_method\":\"GET\",\"http_version\":\"1.1\",\"headers\":{\"host\":\"<host>.svc.cluster.local\",\"user-agent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36\",\"accept\":\"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\",\"accept-encoding\":\"gzip, deflate, br\",\"accept-language\":\"nl-NL,nl;q=0.9,en-US;q=0.8,en;q=0.7\",\"cache-control\":\"max-age=0\",\"cookie\":\"_hjSessionUser_3324444=eyJ***fQ==; _pk_id.4.0605=ba5*****7.1677162909.\",\"sec-ch-ua\":\"\\\"Chromium\\\";v=\\\"110\\\", \\\"Not A(Brand\\\";v=\\\"24\\\", \\\"Google Chrome\\\";v=\\\"110\\\"\",\"sec-ch-ua-mobile\":\"?0\",\"sec-ch-ua-platform\":\"\\\"Windows\\\"\",\"sec-fetch-dest\":\"document\",\"sec-fetch-mode\":\"navigate\",\"sec-fetch-site\":\"cross-site\",\"upgrade-insecure-requests\":\"1\",\"x-forwarded-for\":\"10.0.0.1\",\"x-forwarded-host\":\"<domain>.com\",\"x-forwarded-method\":\"GET\",\"x-forwarded-port\":\"443\",\"x-forwarded-proto\":\"https\",\"x-forwarded-server\":\"traefik-production-869bc86644-vzp7s\",\"x-forwarded-uri\":\"/?__eas_oauth_handler__=authorization_callback&state=43ff******b546&session_state=c1****-****-****-****-*********59c&code=7*******-****-****-****-***********6d.c1*****-****-****-****-*********59c.e*****-****-****-****-**********40b\",\"x-real-ip\":\"10.0.0.1\"},\"body\":{}}",
      "level": "silly",
      "timestamp": "2023-03-09T06:57:16.354Z",
      "service": "external-auth-server"
    }
  },
  {
    "jsonPayload": {
      "message": "starting verify pipeline",
      "service": "external-auth-server",
      "timestamp": "2023-03-09T06:57:16.354Z",
      "level": "info"
    }
  },
  {
    "jsonPayload": {
      "timestamp": "2023-03-09T06:57:16.354Z",
      "message": "verify params: {\"config_token_store_id\":\"<id>\",\"config_token_id_query_engine\":\"jq\",\"config_token_id_query\":\".parentRequestInfo.parsedUri.host | split(\\\".\\\")[0]\"}",
      "level": "silly",
      "service": "external-auth-server"
    }
  },
  {
    "jsonPayload": {
      "message": "server-side config_token_id query info - query: .parentRequestInfo.parsedUri.host | split(\".\")[0], query_engine: jq, data: {\"req\":{\"headers\":{\"host\":\"<host>.svc.cluster.local\",\"user-agent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36\",\"accept\":\"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\",\"accept-encoding\":\"gzip, deflate, br\",\"accept-language\":\"nl-NL,nl;q=0.9,en-US;q=0.8,en;q=0.7\",\"cache-control\":\"max-age=0\",\"cookie\":\"_hjSessionUser_3324444=ey******Q==; _pk_id.4.0605=b****477.1677162909.\",\"sec-ch-ua\":\"\\\"Chromium\\\";v=\\\"110\\\", \\\"Not A(Brand\\\";v=\\\"24\\\", \\\"Google Chrome\\\";v=\\\"110\\\"\",\"sec-ch-ua-mobile\":\"?0\",\"sec-ch-ua-platform\":\"\\\"Windows\\\"\",\"sec-fetch-dest\":\"document\",\"sec-fetch-mode\":\"navigate\",\"sec-fetch-site\":\"cross-site\",\"upgrade-insecure-requests\":\"1\",\"x-forwarded-for\":\"10.0.0.1\",\"x-forwarded-host\":\"<domain>.com\",\"x-forwarded-method\":\"GET\",\"x-forwarded-port\":\"443\",\"x-forwarded-proto\":\"https\",\"x-forwarded-server\":\"traefik-production-869bc86644-vzp7s\",\"x-forwarded-uri\":\"/?__eas_oauth_handler__=authorization_callback&state=43****&session_state=c1...&code=7a....c1...4\",\"x-real-ip\":\"10.0.0.1\"},\"cookies\":{\"_hjSessionUser_3324444\":\"ey...Q==\",\"_pk_id.4.0605\":\"ba59...9.\"},\"signedCookies\":{},\"query\":{\"config_token_store_id\":\"dap2\",\"config_token_id_query_engine\":\"jq\",\"config_token_id_query\":\".parentRequestInfo.parsedUri.host | split(\\\".\\\")[0]\"},\"method\":\"GET\",\"httpVersionMajor\":1,\"httpVersionMinor\":1,\"httpVersion\":\"1.1\"},\"parentRequestInfo\":{\"uri\":\"https://<domain>.com/?__eas_oauth_handler__=authorization_callback&state=4...&session_state=c...&code=7...\",\"parsedUri\":{\"scheme\":\"https\",\"host\":\"<domain>.com\",\"path\":\"/\",\"query\":\"__eas_oauth_handler__=authorization_callback&state=4...&session_state=c...&code=...\",\"reference\":\"absolute\"},\"parsedQuery\":{\"__eas_oauth_handler__\":\"authorization_callback\",\"code\":\"7...\",\"session_state\":\"c...\",\"state\":\"4...\"},\"method\":\"GET\"},\"parentReqInfo\":{\"uri\":\"https://<domain>.com/?__eas_oauth_handler__=authorization_callback&state=4...46&session_state=c...c&code=7...0b\",\"parsedUri\":{\"scheme\":\"https\",\"host\":\"<domain>.com\",\"path\":\"/\",\"query\":\"__eas_oauth_handler__=authorization_callback&state=4...6&session_state=ci...&code=7...b\",\"reference\":\"absolute\"},\"parsedQuery\":{\"__eas_oauth_handler__\":\"authorization_callback\",\"code\":\"7...b\",\"session_state\":\"c1...c\",\"state\":\"4...6\"},\"method\":\"GET\"}}",
      "service": "external-auth-server",
      "level": "debug",
      "timestamp": "2023-03-09T06:57:16.355Z"
    }
  },
  {
    "jsonPayload": {
      "level": "info",
      "service": "external-auth-server",
      "timestamp": "2023-03-09T06:57:16.389Z",
      "message": "sever-side token: store=<id>, id=<domain>"
    }
  },
  {
    "jsonPayload": {
      "service": "external-auth-server",
      "level": "debug",
      "timestamp": "2023-03-09T06:57:16.389Z",
      "message": "adapter config: {\"adapter\":\"sql\",\"options\":{\"config\":{\"client\":\"pg\",\"connection\":{\"database\":\"eas_db\",\"host\":\"10.87.64.3\",\"password\":\"2******\",\"user\":\"******\"},\"pool\":{\"idleTimeoutMillis\":60000,\"max\":10,\"min\":0}},\"query\":\"SELECT token AS token FROM config_tokens WHERE tenant = ? AND client_id = '<id>' AND revoked = False\"}}"
    }
  },
  {
    "jsonPayload": {
      "message": "cache key: config_token_adapater:sql:connections:c4ff***********3c",
      "timestamp": "2023-03-09T06:57:16.389Z",
      "service": "external-auth-server",
      "level": "verbose"
    }
  },
  {
    "jsonPayload": {
      "service": "external-auth-server",
      "timestamp": "2023-03-09T06:57:16.390Z",
      "level": "verbose",
      "message": "cached SQL connection"
    }
  },
  {
    "jsonPayload": {
      "timestamp": "2023-03-09T06:57:16.413Z",
      "level": "debug",
      "service": "external-auth-server",
      "message": "server-side config token: e....I"
    }
  },
  {
    "jsonPayload": {
      "level": "debug",
      "timestamp": "2023-03-09T06:57:16.414Z",
      "message": "config token: {\"eas\":{\"plugins\":[{\"type\":\"oidc\",\"issuer\":{\"discover_url\":\"https://auth.<domain>/auth/realms/<id>/.well-known/openid-configuration\"},\"client\":{\"client_id\":\"<id>\",\"client_secret\":\"8****1\"},\"scopes\":[\"openid\",\"email\",\"profile\"],\"features\":{\"cookie_expiry\":true,\"userinfo_expiry\":true,\"session_expiry\":172800,\"session_expiry_refresh_window\":86400,\"session_retain_id\":true,\"refresh_access_token\":true,\"fetch_userinfo\":true,\"introspect_access_token\":false,\"authorization_token\":\"access_token\"},\"assertions\":{\"exp\":true,\"nbf\":true,\"iss\":true,\"userinfo\":[],\"id_token\":[]},\"cookie\":{\"name\":\"_<name>_session\",\"path\":\"/\"},\"xhr\":{\"redirect_http_code\":401,\"use_referer_as_redirect_uri\":true},\"csrf_cookie\":{\"enabled\":false},\"custom_error_headers\":{},\"custom_service_headers\":{\"X-Token\":{\"source\":\"access_token\",\"query_engine\":\"jp\",\"query\":\"$\",\"query_opts\":{\"single_value\":true}}}}]},\"iat\":1673253928,\"audMD5\":\"216********b3\"}",
      "service": "external-auth-server"
    }
  },
  {
    "jsonPayload": {
      "message": "starting verify for plugin: oidc",
      "service": "external-auth-server",
      "timestamp": "2023-03-09T06:57:16.414Z",
      "level": "info"
    }
  },
  {
    "jsonPayload": {
      "timestamp": "2023-03-09T06:57:16.414Z",
      "service": "external-auth-server",
      "level": "verbose",
      "message": "parent request info: {\"uri\":\"https://<domain>.com/?__eas_oauth_handler__=authorization_callback&state=4....46&session_state=c...9c&code=7***0b\",\"parsedUri\":{\"scheme\":\"https\",\"host\":\"<domain>.com\",\"path\":\"/\",\"query\":\"__eas_oauth_handler__=authorization_callback&state=4...6&session_state=c...c&code=7...b\",\"reference\":\"absolute\"},\"parsedQuery\":{\"__eas_oauth_handler__\":\"authorization_callback\",\"code\":\"7...b\",\"session_state\":\"c...c\",\"state\":\"4....6\"},\"method\":\"GET\"}"
    }
  },
  {
    "jsonPayload": {
      "level": "verbose",
      "message": "audMD5: 2....3",
      "service": "external-auth-server",
      "timestamp": "2023-03-09T06:57:16.414Z"
    }
  },
  {
    "jsonPayload": {
      "service": "external-auth-server",
      "level": "verbose",
      "timestamp": "2023-03-09T06:57:16.414Z",
      "message": "cookie name: _dap2_session"
    }
  },
  {
    "jsonPayload": {
      "message": "decocded state pointer: {\"request_uri\":\"https://<domain>.com/\",\"aud\":\"2...3\",\"csrf\":\"c...0\",\"req\":{\"headers\":{}},\"request_is_xhr\":false,\"iat\":167688102}",
      "service": "external-auth-server",
      "level": "verbose",
      "timestamp": "2023-03-09T06:57:16.415Z"
    }
  },
  {
    "jsonPayload": {
      "level": "verbose",
      "message": "retrieving state: state:oauth:undefined",
      "timestamp": "2023-03-09T06:57:16.415Z",
      "service": "external-auth-server"
    }
  },
  {
    "jsonPayload": {
      "timestamp": "2023-03-09T06:57:16.418Z",
      "service": "external-auth-server",
      "message": "retrieved encrypted state content: null",
      "level": "verbose"
    }
  },
  {
    "jsonPayload": {
      "service": "external-auth-server",
      "level": "verbose",
      "timestamp": "2023-03-09T06:57:16.418Z",
      "message": "failed to decrypt state"
    }
  },
  {
    "jsonPayload": {
      "service": "external-auth-server",
      "message": "decoded state: false",
      "level": "verbose",
      "timestamp": "2023-03-09T06:57:16.418Z"
    }
  },
  {
    "jsonPayload": {
      "message": "audMD5: 2....3",
      "service": "external-auth-server",
      "timestamp": "2023-03-09T06:57:16.418Z",
      "level": "verbose"
    }
  },
  {
    "jsonPayload": {
      "timestamp": "2023-03-09T06:57:16.418Z",
      "level": "verbose",
      "service": "external-auth-server",
      "message": "cookie name: _dap2_session"
    }
  },
  {
    "jsonPayload": {
      "message": "begin token fetch with authorization code",
      "service": "external-auth-server",
      "timestamp": "2023-03-09T06:57:16.418Z",
      "level": "verbose"
    }
  },
  {
    "jsonPayload": {
      "stack": "TypeError: Cannot read properties of undefined (reading 'match')\n    at Object.parse (/home/eas/app/node_modules/uri-js/dist/es5/uri.all.js:874:29)\n    at OpenIdConnectPlugin.get_authorization_redirect_uri (/home/eas/app/src/plugin/oauth/index.js:2514:27)\n    at handle_auth_callback_request (/home/eas/app/src/plugin/oauth/index.js:1649:45)\n    at OpenIdConnectPlugin.verify (/home/eas/app/src/plugin/oauth/index.js:1924:29)\n    at runMicrotasks (<anonymous>)\n    at processTicksAndRejections (node:internal/process/task_queues:96:5)\n    at async processPipeline (/home/eas/app/src/server.js:399:13)",
      "timestamp": "2023-03-09T06:57:16.418Z",
      "message": "Cannot read properties of undefined (reading 'match')",
      "level": "error",
      "service": "external-auth-server"
    }
  },
  {
    "jsonPayload": {
      "service": "external-auth-server",
      "timestamp": "2023-03-09T06:57:16.419Z",
      "message": "end verify pipeline with status: 503",
      "level": "info"
    }
  },
]

Surely I’m simply doing something silly here with the SSO configuration that i have overlooked. Though having trouble pin-pointing exactly what is causing it.

In addition, i think a check is missing here: https://github.com/travisghansen/external-auth-server/blob/master/src/plugin/oauth/index.js#L1919 Either as a check for null/undefined on the decodedStatePointer.state_id property Or as a check on the resulting statePayload

More will follow as i dive deeper… In the meantime any advice?

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Comments: 37 (16 by maintainers)

Most upvoted comments

Yeah for sure we shouldn’t crash, I’m pretty sure I have fix queued up for that already but will make sure it’s in the next release no matter.

Do you have specific logic built into the SPA to handle api failures and redirect? In the case of a SPA there may be some strange behavior due to the concurrent nature of api requests etc but I’d have to think it through more thoroughly to say for sure 😦