Extension Chat Message returns 401 authentication failed

Oh you did base64 decode your extension secret before using it to encode the JWT?

The only thing I do different is for pubsub I use, (javascript but easy enough to convert to PHP)

const sigPubSubPayload = {
    "exp": Math.floor(new Date().getTime() / 1000) + 60,
    "user_id": config.owner,
    "role": "external",
    "channel_id": "all",
    "pubsub_perms": {
        "send": [
            "global"
        ]
    }
}

And chat

    var sigPayload = {
        'exp':          Math.floor(new Date().getTime() / 1000) + 60,
        'user_id':      config.twitch.streamer_id,
        'role':         'broadcaster'
    }

Since you’ve tried both PubSub and chat, and got the same issue, I bet you forgot (or didn’t know) to base decode your secret before passing it to the encoder