Clarification on auth flow for subscribing to EventSub

I am writing a twitch chat bot to use EventSub over websockets. I have two accounts: account 1 is the streamer account (ex. DoomerCreatine) and a second account that is the bot (ex. BotAccount). The BotAccount has an app registered and I have the client id and secret for that. The BotAccount is also a moderator in the streamer account’s chat.

So far what I’ve done is:

  1. Navigate to user authentication url with following (url encoded):
https://id.twitch.tv/oauth2/authorize \ 
?response_type=token \ 
&client_id=<BOT CLIENT ID> \
&redirect_uri=http://localhost:3000 \
&scope=user:bot
+channel:bot
+user:read:chat
+user:write:chat
+channel:read:subscriptions \
&state=<STATE STRING>)

This is successful and returns a user token for my stream account. Per Barry’s posts, here and here, I discard this token and then request a client_credentials token for the bot account to utilize the ‘two-legged’ approach that Barry describes, where the user first authorizes the client and then the client requests client credentials.

With this token I am able to subscribe to the channel.chat.message EventSub and it returns a success. I am able to see chat messages and I can also send via the https://api.twitch.tv/helix/chat/messages endpoint from the bot account.

Connected. Session_id: <SESSION ID>
{
  "data": [
    {
      "id": "d9ab6f61-c65f-4c36-9649-65e02f1deec4",
      "status": "enabled",
      "type": "channel.chat.message",
      "version": "1",
      "condition": {
        "broadcaster_user_id": <BROADCASTER ID>,
        "user_id": <BOT ID>
      },
      "created_at": "2024-08-31T20:03:38.068156739Z",
      "transport": {
        "method": "websocket",
        "session_id": <SESSION ID>,
        "connected_at": "2024-08-31T20:03:37Z"
      },
      "cost": 0
    }
  ],
  "total": 7,
  "max_total_cost": 10,
  "total_cost": 0
}

However, if I try to subscribe with the following payload to monitor resub messages:

        data = {
            'type': 'channel.subscription.message',
            'version': '1',
            'condition': {
                'broadcaster_user_id': <BROADCASTER_ID>
            },
            "transport": {
                "method": "websocket",
                "session_id": <SESSION ID>}
        }

I receive the following response:

{
  "error": "Forbidden",
  "status": 403,
  "message": "subscription missing proper authorization"
}

Both of these subscriptions use the same headers:

headers = {
            "Authorization": "Bearer <CLIENT CREDENTIAL TOKEN>",
            "Client-Id": <CLIENT ID>,
            "Content-Type": "application/json"
        }

I’ve also tried this method with the Authorization code grant flow workflow where I obtain a code first then request a token and refresh token. This results in the same outcome: I can subscribe to messages but not subscriptions.

I appreciate any help/guidance, thanks!

The owner of the application is irrelevant. Just for the record.

You can’t use a client credentials token with websockets, and you don’t do two legged with WebSockets, straight WebSockets is all one legged. And can’t mix match.

So for your channel.chat.message EventSub you likely used the bots ID’s and the bots user token, not a client creds which is why you got a not authed for subscription message, as you used the bots oAuth token

You probably want channel.chat.notification for the described use case instead

Thank you! I knew I must’ve just had my flow wrong. I changed to obtaining a user token for the Bot Account and was able to successfully subscribe to channel.chat.notification.

So in the future I would have the streamer still authorize the bot. Then I would use the bot’s user token for the subscriptions? The code or response from the streamer authorization isn’t needed, it’s just to allow the client_id of the bot to have the appropriate scopes, do I have that right?

Depending on which topics you want to subscribe to.

The problem is what you are using EventSub overwebsockets so you would need two sockets

  • WebSocket A would use the bots oAuth token and subscribe to topics that work when the condition/authenticating user is the bot
  • WebSocket B would use the streamers oAuth token.

So websocket (a) authenticated as the bot’s user ID with the bots token would subscribe toi the chat topics we discussed

And say for channel point notifications, websocket (b) authenticated as the streamer with the streamers with the streamers userID would subscribe to the channel point topics.

Great, thanks for the explanation! Clearly I’ve got some further reading on OAuth workflows and workflow designs that I need to do. Thanks for the help :grinning:

Update in case others come across similar issues:

What I ended up doing is creating a small webserver on a raspberry pi that handled obtaining the OAuth tokens. For the streamer I requested appropriate scopes to read chat, bits, channel points redemptions, channel bot, and subscriptions. Then I used the code returned to get access and refresh tokens. These are used for making the EventSub subscriptions. Then I have a second OAuth token for the bot account that has chat read, chat write, and user bot scopes. This is used to send messages to the chat. Before running the scripts I use the validate API to check token and refresh if needed. So in short: Streamer Token/Refresh → EventSub subscriptions. Bot Token/Refresh → sending messages to chat.

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