# Invalid transport and auth combination error

**URL:** <https://discuss.dev.twitch.com/t/invalid-transport-and-auth-combination-error/59864>\
**Category:** API\
**Created:** [August 12, 2024, 10:57pm UTC](https://discuss.dev.twitch.com/t/invalid-transport-and-auth-combination-error/59864 "2024-08-12T22:57:33Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![ION606](https://avatars.discourse-cdn.com/v4/letter/i/3ec8ea/32.png) [@ION606](https://discuss.dev.twitch.com/u/ION606)\
**Post date:** [August 12, 2024, 10:57pm UTC](https://discuss.dev.twitch.com/t/invalid-transport-and-auth-combination-error/59864/1 "2024-08-12T22:57:33Z")

</div>

Please lmk if this isn’t a question for here (I’m really new to this).

I’m trying to subscribe to get notified whenever certain streamers go live, but for some reason I keep getting the error `{ error: 'Bad Request', status: 400, message: 'invalid transport and auth combination' }`

I’m not sure what I’m doing wrong and would really appreciate any help. I put my whole code down below, as well as the docs pages I was looking at.

```auto
import axios from 'axios';
import WebSocket from 'ws';

const clientId = '7fv78wh6keb4j3c8oeoff979ejifdh';
const clientSecret = 'SECRET';
const channelName = 'CHANNEL_HERE';

export default class wsmanager {
    /** @type { WebSocket } */
    #ws;

    #heartbeatint;

    #authheaders;

    #startHeartbeat() {
        const timeBetweenPings = 30000;
        this.#heartbeatint = setInterval(() => this.#ws.send(), timeBetweenPings);
        console.log(`heartbeat started with interval ${timeBetweenPings}ms`);
    }

    async getTwitchOAuthToken() {
        const tokenUrl = 'https://id.twitch.tv/oauth2/token';
        const params = new URLSearchParams({
            client_id: clientId,
            client_secret: clientSecret,
            grant_type: 'client_credentials',
        });

        try {
            const response = await axios.post(tokenUrl, params);
            const { access_token } = response.data;
            return access_token;
        } catch (error) {
            console.error('Error obtaining OAuth token:', error.response.data);
            throw error;
        }
    }

    async getBroadcasterUserId(username, token) {
        const userUrl = `https://api.twitch.tv/helix/users?login=${username}`;

        try {
            const response = await fetch(userUrl, {
                method: 'GET',
                headers: this.#authheaders,
            });

            if (!response.ok) {
                throw new Error(`Error fetching user data: ${response.statusText}`);
            }

            const data = await response.json();
            if (data.data.length === 0) {
                throw new Error(`User not found: ${username}`);
            }

            const userId = data.data[0].id;
            return userId;
        } catch (error) {
            console.error('Error fetching broadcaster user ID:', error);
            throw error;
        }
    }

    async connectToWebSocket(token) {
        this.#authheaders = {
            'Authorization': `Bearer ${token}`,
            'Client-Id': '7fv78wh6keb4j3c8oeoff979ejifdh',
            'Content-Type': 'application/json'
        };

        const wsUrl = 'wss://eventsub.wss.twitch.tv/ws',
            uid = await this.getBroadcasterUserId(channelName, token)

        this.#ws = new WebSocket(wsUrl);

        this.#ws.on('open', () => {
            console.log('Connected to Twitch WebSocket');
            // Optionally, you can authenticate or subscribe to events here
        });

        this.#ws.on('message', (data) => {
            const message = JSON.parse(data);

            if (message.metadata && message.metadata.message_type === 'session_welcome') {
                this.#startHeartbeat();
                this.subscribeToStreamOnline(uid, token, message.payload.session.id);
            }
        });

        this.#ws.on('close', (ev) => {
            console.log('WebSocket connection closed with code', ev);
        });

        this.#ws.on('error', (error) => {
            console.error('WebSocket error:', error);
        });
    }

    async subscribeToStreamOnline(userId, token, session_id) {
        const eventSubUrl = 'https://api.twitch.tv/helix/eventsub/subscriptions';

        const body = {
            type: 'stream.online',
            version: '1',
            condition: {
                'broadcaster_user_id': userId,
            },
            transport: {
                'method': 'websocket',
                'session_id': session_id
            },
        };

        try {
            const response = await fetch(eventSubUrl, {
                method: 'POST',
                headers: {
                    'Authorization': `Bearer ${token}`,
                    'Client-Id': clientId,
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(body),
            });

            if (!response.ok) {
                console.error(await response.json());
                throw new Error();
            }

            const data = await response.json();
            console.log('Subscription successful:', data);
        } catch (error) {
            console.error('Error subscribing to event:', error);
            throw error;
        }
    }

    async init() {
        try {
            const token = await this.getTwitchOAuthToken();
            await this.connectToWebSocket(token);
        } catch (error) {
            console.error('Failed to connect or subscribe:', error.message);
        }
    }
    constructor() { };
}

const temp = new wsmanager();
temp.init();

```

> **[EventSub Subscription Types](https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types/#streamonline)**
>
> Subscription Types

> **[Reference](https://dev.twitch.tv/docs/api/reference/#create-eventsub-subscription)**
>
> Twitch Developer tools and services to integrate Twitch into your development or create interactive experience on twitch.tv.

> **[Reference](https://dev.twitch.tv/docs/api/reference/#create-eventsub-subscription)**
>
> Twitch Developer tools and services to integrate Twitch into your development or create interactive experience on twitch.tv.

> **[Handling WebSocket Events](https://dev.twitch.tv/docs/eventsub/handling-websocket-events/)**
>
> Getting Events Using WebSockets

---

<div class="post-metadata">

**Author:** ![BarryCarlyon](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/barrycarlyon/32/253_2.png) [@BarryCarlyon](https://discuss.dev.twitch.com/u/BarryCarlyon)\
**Post date:** [August 12, 2024, 11:36pm UTC](https://discuss.dev.twitch.com/t/invalid-transport-and-auth-combination-error/59864/2 "2024-08-12T23:36:36Z")

</div>

Straight websockets requires a user access token. You have used an app access

Hence the error

---

<div class="post-metadata">

**Author:** ![ION606](https://avatars.discourse-cdn.com/v4/letter/i/3ec8ea/32.png) [@ION606](https://discuss.dev.twitch.com/u/ION606)\
**Post date:** [August 12, 2024, 11:50pm UTC](https://discuss.dev.twitch.com/t/invalid-transport-and-auth-combination-error/59864/3 "2024-08-12T23:50:55Z")

</div>

ohhhh I see, thank you! Does the user access token have to be for the user who’s websocket I’m connecting to? I ask because I thought the connection was one-way so the app couldn’t change anything (please correct me if I’m wrong)

---

<div class="post-metadata">

**Author:** ![BarryCarlyon](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/barrycarlyon/32/253_2.png) [@BarryCarlyon](https://discuss.dev.twitch.com/u/BarryCarlyon)\
**Post date:** [August 13, 2024, 12:25am UTC](https://discuss.dev.twitch.com/t/invalid-transport-and-auth-combination-error/59864/4 "2024-08-13T00:25:25Z")

</div>

> [@ION606](#):
>
> Does the user access token have to be for the user who’s websocket I’m connecting to?

For public topics no, and you mean the “broadcaster ID on the topic conditions doesn’t need to match the user ID in the oAuth token”

Websockets is just a transport.

> [@ION606](#):
>
> I ask because I thought the connection was one-way so the app couldn’t change anything

Not sure what you are asking here.

Striaght websockets are _basically_ for front end applications where the user using the app logs in via implict auth or DCF, both only require a ClientID to go.

Sure you can use websockets on the server, but the same way a chatbot works with the user token of the bot.

Or under conduits but I dont think this fits your described use case.

---

<div class="post-metadata">

**Author:** ![ION606](https://avatars.discourse-cdn.com/v4/letter/i/3ec8ea/32.png) [@ION606](https://discuss.dev.twitch.com/u/ION606)\
**Post date:** [August 13, 2024, 12:35am UTC](https://discuss.dev.twitch.com/t/invalid-transport-and-auth-combination-error/59864/5 "2024-08-13T00:35:16Z")

</div>

Sorry I phrased the question strangely, I accidentally sent something to the websocket connection at some point (that wasn’t a PONG) and it return an unauthorized status, so I assumed it wouldn’t need the user access token. In terms of getting the token, I was wondering what scopes I would need to get a websocket event if the user is live (I assume it wouldn’t just be `read:user` but I might be wrong)

---

<div class="post-metadata">

**Author:** ![BarryCarlyon](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/barrycarlyon/32/253_2.png) [@BarryCarlyon](https://discuss.dev.twitch.com/u/BarryCarlyon)\
**Post date:** [August 13, 2024, 9:47am UTC](https://discuss.dev.twitch.com/t/invalid-transport-and-auth-combination-error/59864/6 "2024-08-13T09:47:27Z")

</div>

> [@ION606](#):
>
> I accidentally sent something to the websocket connection at some point

If you send anything to a websocket you get disconnected with a `4001` code and message `Client sent inbound traffic`

> [@ION606](#):
>
> In terms of getting the token, I was wondering what scopes I would need to get a websocket event if the user is live

`stream.online` requires no scopes it is a public topic.

If you connect a websocet and the userID in the condition is the same as the userID in the token then the topic is cost 0. Otherwise cost 1.

---

<div class="post-metadata">

**Author:** ![system](https://d2opxh93rbxzdn.cloudfront.net/original/2X/0/05909729875cce3b53e59d5561c4d23bb14948fc.png) [@system](https://discuss.dev.twitch.com/u/system)\
**Post date:** [September 12, 2024, 9:47am UTC](https://discuss.dev.twitch.com/t/invalid-transport-and-auth-combination-error/59864/7 "2024-09-12T09:47:46Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
