最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

typescript - Slack WebClient: "unable to verify certificate" through proxy despite rejectUnauthorized = false

programmeradmin1浏览0评论
  1. I'm using below code for creating Slack web client on-demand in some typescript REST endpoint of some webservice. The client uses https agent for communicating with slack API via proxy (mitmproxy is used):
 private createProxyAwareSlackClient(token: any) {
    const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
    const slackClientOptions = { logLevel: LogLevel.DEBUG };

    if (proxyUrl) {
      slackClientOptions['agent'] =
        new URL(proxyUrl).protocol === 'http' ? new HttpProxyAgent(proxyUrl, {rejectUnauthorized: false}) : new HttpsProxyAgent(proxyUrl, {rejectUnauthorized: false});
    }

    return new WebClient(token, slackClientOptions);
  }

  async firstHandshake(settings: any) {
    const slackWebClient = this.createProxyAwareSlackClient(undefined);
    let response: WebAPICallResult;
    try {
      response = await slackWebClient.oauth.v2.access({
        client_id: process.env.SLACK_CLIENT_ID,
        client_secret: process.env.SLACK_CLIENT_SECRET,
        code: settings.slack_code,
        redirect_uri: settings.redirect_uri
      });
    } catch (e) {
      logger.error(e);
      throw createError(500, 'Cannot get slack api key');
    }
  1. rejectUnauthorized: false is used while instantiating the agent to avoid validating of the slack certificate. Nevertheless, the certificate validation occurs and fails with below error in the client (rest endpoint source code):
[WARN]  web-api:WebClient:8 http request failed unable to verify the first certificate
[DEBUG]  web-api:WebClient:8 http request url: .v2.access
[DEBUG]  web-api:WebClient:8 http request body: {"client_id":"id","client_secret":"secret","code":"some_code","redirect_uri":"some_url"}
[DEBUG]  web-api:WebClient:8 http request headers: {}
[WARN]  web-api:WebClient:8 http request failed unable to verify the first certificate

and below error is seen in the mitmproxy logs:


[23:02:09.731][127.0.0.1:59940] client connect
[23:02:09.826][127.0.0.1:59940] server connect slack:443 (some_ip:443)
[23:02:09.911][127.0.0.1:59940] Client TLS handshake failed. The client disconnected during the handshake. If this happens consistently for slack, this may indicate that the client does not trust the proxy's certificate.
[23:02:09.913][127.0.0.1:59940] client disconnect
[23:02:09.914][127.0.0.1:59940] server disconnect slack:443 (some_ip:443)

It's important to note that:

HTTPS_PROXY env var is https://localhost:8080 (where mitmproxy listens)

How to skip slack certificate validation when slack webclient is accessing it via a proxy?

There's no issue and slack API is successfully accessed via the proxy without certificate validation if NODE_TLS_REJECT_UNAUTHORIZED=0 env var is present in the web service environment. However, it's a bad practice to disable certificate validation globally.

  1. I'm using below code for creating Slack web client on-demand in some typescript REST endpoint of some webservice. The client uses https agent for communicating with slack API via proxy (mitmproxy is used):
 private createProxyAwareSlackClient(token: any) {
    const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
    const slackClientOptions = { logLevel: LogLevel.DEBUG };

    if (proxyUrl) {
      slackClientOptions['agent'] =
        new URL(proxyUrl).protocol === 'http' ? new HttpProxyAgent(proxyUrl, {rejectUnauthorized: false}) : new HttpsProxyAgent(proxyUrl, {rejectUnauthorized: false});
    }

    return new WebClient(token, slackClientOptions);
  }

  async firstHandshake(settings: any) {
    const slackWebClient = this.createProxyAwareSlackClient(undefined);
    let response: WebAPICallResult;
    try {
      response = await slackWebClient.oauth.v2.access({
        client_id: process.env.SLACK_CLIENT_ID,
        client_secret: process.env.SLACK_CLIENT_SECRET,
        code: settings.slack_code,
        redirect_uri: settings.redirect_uri
      });
    } catch (e) {
      logger.error(e);
      throw createError(500, 'Cannot get slack api key');
    }
  1. rejectUnauthorized: false is used while instantiating the agent to avoid validating of the slack certificate. Nevertheless, the certificate validation occurs and fails with below error in the client (rest endpoint source code):
[WARN]  web-api:WebClient:8 http request failed unable to verify the first certificate
[DEBUG]  web-api:WebClient:8 http request url: https://slack/api/oauth.v2.access
[DEBUG]  web-api:WebClient:8 http request body: {"client_id":"id","client_secret":"secret","code":"some_code","redirect_uri":"some_url"}
[DEBUG]  web-api:WebClient:8 http request headers: {}
[WARN]  web-api:WebClient:8 http request failed unable to verify the first certificate

and below error is seen in the mitmproxy logs:


[23:02:09.731][127.0.0.1:59940] client connect
[23:02:09.826][127.0.0.1:59940] server connect slack:443 (some_ip:443)
[23:02:09.911][127.0.0.1:59940] Client TLS handshake failed. The client disconnected during the handshake. If this happens consistently for slack, this may indicate that the client does not trust the proxy's certificate.
[23:02:09.913][127.0.0.1:59940] client disconnect
[23:02:09.914][127.0.0.1:59940] server disconnect slack:443 (some_ip:443)

It's important to note that:

HTTPS_PROXY env var is https://localhost:8080 (where mitmproxy listens)

How to skip slack certificate validation when slack webclient is accessing it via a proxy?

There's no issue and slack API is successfully accessed via the proxy without certificate validation if NODE_TLS_REJECT_UNAUTHORIZED=0 env var is present in the web service environment. However, it's a bad practice to disable certificate validation globally.

Share Improve this question edited Jan 22 at 11:03 Guillaume Outters 2,0381 gold badge15 silver badges20 bronze badges asked Jan 19 at 21:31 rokpotorokpoto 10.8k19 gold badges84 silver badges146 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 0

With this instruction, the client may be instructed to short-circuit the certificate of the proxy, instead of the certificate of the end server.

Would you test adding rejectUnauthorized directly to the slackClientOptions (in addition to the already set one)?

if (proxyUrl) {
      slackClientOptions['agent'] =
        new URL(proxyUrl).protocol === 'http:' ? new HttpProxyAgent(proxyUrl, {rejectUnauthorized: false}) : new HttpsProxyAgent(proxyUrl, {rejectUnauthorized: false});
        //--- Here we add: ---
        slackClientOptions.rejectUnauthorized = false;
        //---  (finished)  ---
    }

This looks like to relate to issue #35 of HttpsProxyAgent, although it is not clear wether it has been solved.

Using tunnel npm package solved the issue for me.

  import tunnel from 'tunnel';

  private createProxyAwareSlackClient(token: any) {
    const proxyUrl = process.env.TEST_HTTPS_PROXY || process.env.TEST_HTTP_PROXY;
    const basicAuthCredentials =
      process.env.TEST_HTTP_PROXY_BASIC_AUTH || process.env.ENGINE_HTTP_PROXY_BASIC_AUTH_DETAILS;
    const slackClientOptions: Record<string, any> = { logLevel: LogLevel.DEBUG };

    if (proxyUrl) {
      const { hostname, port } = new URL(proxyUrl); // Extract host and port

      const tunnelOptions = {
        keepAlive: true,
        keepAliveMsecs: 1000,
        maxFreeSockets: 256,
        maxSockets: 256,
        proxy: {
          host: hostname,
          port: port ? parseInt(port, 10) : 80,
          proxyAuth: basicAuthCredentials
        },
        rejectUnauthorized: false
      };

      slackClientOptions.agent = tunnel.httpsOverHttp(tunnelOptions);
    }

    return new WebClient(token, slackClientOptions);
  }

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论