Unable to establish a websocket connection when using openid authentication

Hi there,

I am having difficulties trying to connect to a websocket-enabled server behind Tyk gateway with “use_openid” option being true. As the browser don’t allow modifying ws:// request headers, we are forced to pass the JWT token via query parameters, more specifically using the “access_token” parameter. I read somewhere in the forums that you can read the token from query parameters as a fallback when it’s not found in the request headers, therefore I have done the following in the configuration:

{
...
  "auth": {
    "use_param": true,
    "param_name": "access_token",
    "disable_header": false,
    "auth_header_name": "Authorization"
  }
...
}

Following which I have tried to test the endpoint under these situations:

  1. Sending via query parameter by appending access_token=<JWT token> in the ws:// url

This resulted in an Error 401, and the following logs can be seen emitted by the Tyk gateway container:

tyk-gateway_1     | time="Nov 24 10:35:16" level=warning msg="JWT Invalid" api_id=ntsignalrproxy api_name=ntsignalrproxy error="Validation error. The 'Authorization' header was not found or was empty." mw=OpenIDMW org_id=60f08cb4b4c0be0001a87762 origin=192.168.224.1 path="/ntsignalrproxy/"
tyk-gateway_1     | time="Nov 24 10:35:16" level=warning msg="Attempted access with invalid key." api_id=ntsignalrproxy api_name=ntsignalrproxy key="****JWT]" mw=OpenIDMW org_id=60f08cb4b4c0be0001a87762 origin=192.168.224.1 path="/ntsignalrproxy/

Which probably meant that Tyk gateway doesn’t check the access_token query parameter despite being configured that way?

  1. Sending via Authorization header by appending Bearer <JWT token>

This didn’t produce and logs but resulted in an Error 500 returned, which I am not sure how to debug further. Besides, this second approach is unfeasible because in the browser, we can’t use request headers when establishing a websocket connection. But I did so just to test what was Tyk was doing internally.

However, I have tested the same configuration but using “use_keyless” = true and changing “use_openid” = false, and it successfully connects without any authentication check which is expected, so I am led to believe that using websockets protected by open id doesn’t work well in Tyk gateway.

Any ideas would be greatly appreciated… Thank you.

Prakoso

Hi @Osokarp,

I think you want that in the oidc section

"oidc": {
      "use_param": true,
      "param_name": "access_token",
      "disable_header": false,
      "auth_header_name": "Authorization",
      }

Hi @Ubong,

I tried with the updated configuration as suggested but I still encounter the same issue in the OP. I went to look up the exhaustive types of the API definition at API Definition Objects, it doesn’t seem to have that “oidc” property.

Any ideas? Thanks!

Please share your full API definition, GW version and curl command

Hi @Ubong,

Have tried these two different API definitions:

  1. Configuring “oidc” at auth_configs.oidc
{
  "name": "ntsignalrproxy",
  "api_id": "ntsignalrproxy",
  "org_id": "60f08cb4b4c0be0001a87762",
  "use_keyless": false,
  "use_oauth2": false,
  "use_openid": true,
  "openid_options": {
    "providers": [
      {
        "issuer": "http://<IPADDR>/oidc/realms/master",
        "client_ids": {
          "Y2xpZW50": "default"
        }
      }
    ],
    "segregate_by_client": false
  },
  "definition": {
    "location": "header",
    "key": "version"
  },
  "auth_configs": {
    "oidc": {
      "use_param": true,
      "param_name": "access_token",
      "disable_header": false,
      "auth_header_name": "Authorization"
    }
  },
  "version_data": {
    "not_versioned": true,
    "versions": {
      "Default": {
        "name": "Default",
        "global_headers": {
          "X-UserName":"$tyk_context.jwt_claims_preferred_username",
          "X-Roles":"$tyk_context.jwt_claims_roles"
        }
      }
    }
  },
  "proxy": {
    "preserve_host_header": true,
    "listen_path": "/ntsignalrproxy",
    "target_url": "http://ntsignalrproxy:8080",
    "strip_listen_path": true,
    "transport": {
      "ssl_insecure_skip_verify": true,
      "ssl_force_common_name_check": false
    }
  },
  "enable_context_vars": true
}
  1. Configuring “oidc” at root object
{
  "name": "ntsignalrproxy",
  "api_id": "ntsignalrproxy",
  "org_id": "60f08cb4b4c0be0001a87762",
  "use_keyless": false,
  "use_oauth2": false,
  "use_openid": true,
  "openid_options": {
    "providers": [
      {
        "issuer": "http://<IPADDR>/oidc/realms/master",
        "client_ids": {
          "Y2xpZW50": "default"
        }
      }
    ],
    "segregate_by_client": false
  },
  "definition": {
    "location": "header",
    "key": "version"
  },
  "oidc": {
      "use_param": true,
      "param_name": "access_token",
      "disable_header": false,
      "auth_header_name": "Authorization"
    },
  "version_data": {
    "not_versioned": true,
    "versions": {
      "Default": {
        "name": "Default",
        "global_headers": {
          "X-UserName":"$tyk_context.jwt_claims_preferred_username",
          "X-Roles":"$tyk_context.jwt_claims_roles"
        }
      }
    }
  },
  "proxy": {
    "preserve_host_header": true,
    "listen_path": "/ntsignalrproxy",
    "target_url": "http://ntsignalrproxy:8080",
    "strip_listen_path": true,
    "transport": {
      "ssl_insecure_skip_verify": true,
      "ssl_force_common_name_check": false
    }
  },
  "enable_context_vars": true
}

I am currently using the Docker version of Tyk Gateway, specifically this image: docker.tyk.io/tyk-gateway/tyk-gateway:v4.1.0

As this is a websocket connection, I am not using cURL to test, instead, I use Postman to test. It just returns error code 401 when I try to establish a websocket connection passing access_token query parameter into the ws:// url. Seems like it fails at the handshake process:

Error: Unexpected server response: 401
Handshake Details
Request URL: http://<IPADDR>/ntsignalrproxy/?id=g_ZTpAP9OpwcGlNy8ynccg&access_token=<ACCESS_TOKEN>
Request Method: GET
Status Code: 401 Unauthorized
Request Headers
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: c6OVPTSfJv36ws6mJyVFAg==
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Host: <IPADDR>
Response Headers
Content-Type: application/json
X-Generator: tyk.io
Date: Tue, 29 Nov 2022 08:12:56 GMT
Content-Length: 37

Logs from Tyk Gateway when I try to connect:

tyk-gateway_1     | time="Nov 29 08:12:56" level=warning msg="JWT Invalid" api_id=ntsignalrproxy api_name=ntsignalrproxy error="Validation error. The 'Authorization' header did not have the correct format." mw=OpenIDMW org_id=60f08cb4b4c0be0001a87762 origin=172.21.0.1 path="/ntsignalrproxy/"
tyk-gateway_1     | time="Nov 29 08:12:56" level=warning msg="Attempted access with invalid 
key." api_id=ntsignalrproxy api_name=ntsignalrproxy key="****JWT]" mw=OpenIDMW org_id=60f08cb4b4c0be0001a87762 origin=172.21.0.1 path="/ntsignalrproxy/"

Hi @Osokarp,

At auth_configs.oidc is the way to go. (Config 1)

Are you including “Bearer” scheme?
&access_token=Bearer <ACCESS_TOKEN> as the query value works

Hi @Ubong,

Appending the Bearer scheme did it for me. But I had to write another pre-auth request middleware to transform it as the original access_token only contains the JWT token itself and the whole process is managed by a library.

Thanks for your help!

Prakoso