# OAuth User Token without Server

**URL:** <https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577>\
**Category:** API\
**Created:** [June 19, 2020, 8:45pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577 "2020-06-19T20:45:45Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Winder](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/winder/32/9273_2.png) [@Winder](https://discuss.dev.twitch.com/u/Winder)\
**Post date:** [June 19, 2020, 8:45pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/1 "2020-06-19T20:45:45Z")

</div>

Hi there!

I’m working on a script for Twitch streams with OBS. This script shall display the stream chat in the stream and write a message to welcome new followers.  
For writing a message into the stream chat, the script needs a user token. And therefor, I need a redirect URL. And that’s the problem.

This script shall work as a single script (pure JavaScript, HTML and some CSS), which can be selected as an OBS local browser source. There shall be no server, no port listening or anything else. Just the script.

Due to atomic redirects and cross origin policy, the script is unable to get the user token. It doesn’t work in Chrome or Firefox. Though it does currently work in OBS (propably due to missing or deactivated security policies), I want to fix this in case OBS fixes these security issues.

The script is open source. You can view it on GitLab ([https://gitlab.com/Winder/winders-obs-chat-bot-for-twitch](https://gitlab.com/Winder/winders-obs-chat-bot-for-twitch)).

I hope you can help me. I’m working on this issue for weeks and am running out on ideas.

---

<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:** [June 19, 2020, 8:49pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/2 "2020-06-19T20:49:51Z")

</div>

> [@Winder](#):
>
> I’m working on a script for Twitch streams with OBS. This script shall display the stream chat in the stream and write a message to welcome new followers.

You need a proper bot really.

Also followers don’t _really_ like to be welcomed in chat especially lurkers. But do what works for the stream

> [@Winder](#):
>
> This script shall work as a single script (pure JavaScript, HTML and some CSS), which can be selected as an OBS local browser source. There shall be no server, no port listening or anything else. Just the script.

You need implicit auth, since you need chat write powers/ability to login to chat to send the thanks for follow message

> **[Getting OAuth Access Tokens](https://dev.twitch.tv/docs/authentication/getting-tokens-oauth/)**
>
> Getting OAuth Access Tokens

Example:

> <https://github.com/BarryCarlyon/twitch_misc/tree/main/authentication/implicit_auth>
>
> //github.com/BarryCarlyon/twitch\_misc/tree/main/authentication/implicit\_auth

> [@Winder](#):
>
> I hope you can help me. I’m working on this issue for weeks and am running out on ideas.

I _really_ wouldn’t do it like this. But it can be made to work like this.

Server side using webhooks for follow notification and repeat follow de-duplication and a long running bot would fit better.

> [@Winder](#):
>
> Due to atomic redirects and cross origin policy, the script is unable to get the user token. It doesn’t work in Chrome or Firefox. Though it does currently work in OBS (propably due to missing or deactivated security policies), I want to fix this in case OBS fixes these security issues.

A lot of stuff like this is disabled in the browser source, since it’s essentially a headless browser and “workarounds”/alternative access is needed

---

<div class="post-metadata">

**Author:** ![Winder](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/winder/32/9273_2.png) [@Winder](https://discuss.dev.twitch.com/u/Winder)\
**Post date:** [June 19, 2020, 8:54pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/3 "2020-06-19T20:54:52Z")

</div>

Wow, thanks for the (very) quick response!

I’ll try this implicit authorization and write a new reply with the result.

---

<div class="post-metadata">

**Author:** ![Winder](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/winder/32/9273_2.png) [@Winder](https://discuss.dev.twitch.com/u/Winder)\
**Post date:** [June 20, 2020, 3:10pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/4 "2020-06-20T15:10:38Z")

</div>

I’m afraid, but authorization via implicit code flow doesn’t work. The script in your example doesn’t work either. I’m still getting redirected and am not able to get the token, because on my local machine is nothing listening on a port (so redirect fails) and the script is not able to access the window’s location hash (due to cross origin policy).

---

<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:** [June 20, 2020, 3:21pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/5 "2020-06-20T15:21:05Z")

</div>

If it doesn’t work then you’ll need to do it another way. I’m assuming you are on `file://` instead of having it served from a server, so you are probably out of luck here. I do all my stuff via server since it’s just easier to manage the keys

Auth is better held on a remote server so it can be auto refreshed/managed nicely. Without leaking your secret

> [@BarryCarlyon](#):
>
> I _really_ wouldn’t do it like this. But it can be made to work like this.

The alternative is that a user gets a token from somewhere and manually pastes it into your code/query string argument in OBS, but then when the key dies (even using implicit) it’ll require user interaction, as manual copy paste probably means implicit auth and when that key dies you don’t have a refresh token to auto renew,

---

<div class="post-metadata">

**Author:** ![Winder](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/winder/32/9273_2.png) [@Winder](https://discuss.dev.twitch.com/u/Winder)\
**Post date:** [June 20, 2020, 7:53pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/6 "2020-06-20T19:53:38Z")

</div>

> [@BarryCarlyon](#):
>
> I’m assuming you are on `file://` instead of having it served from a server

Yes, that’s exactly the case. That’s why I have all this problems. Do you - or any other - know a solution to my problem?

---

<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:** [June 20, 2020, 7:56pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/7 "2020-06-20T19:56:18Z")

</div>

I’d use a server as then you have better control over token management.

---

<div class="post-metadata">

**Author:** ![Winder](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/winder/32/9273_2.png) [@Winder](https://discuss.dev.twitch.com/u/Winder)\
**Post date:** [June 20, 2020, 8:00pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/8 "2020-06-20T20:00:00Z")

</div>

I can’t use a server, because the script is ment to run on local machines. The idea behind the script is, that it runs without any third party (even without my own server as a third party).  
Even if anyone else want to use the script, he / she just has to get the script, enter the credentials and it works.

---

<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:** [June 20, 2020, 8:03pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/9 "2020-06-20T20:03:36Z")

</div>

Then you are stuck as you need to use a server to get the token, even if that token is then copied and pasted to the script.

The alternative to this is a downloadable program, as something like electron can capture the return in various ways, and then serve the content/script off a local webserver.

But it’s just _easier_ to remote host it all in my opinion.

---

<div class="post-metadata">

**Author:** ![Winder](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/winder/32/9273_2.png) [@Winder](https://discuss.dev.twitch.com/u/Winder)\
**Post date:** [June 20, 2020, 8:06pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/10 "2020-06-20T20:06:42Z")

</div>

> [@BarryCarlyon](#):
>
> Then you are stuck as you need to use a server to get the token, even if that token is then copied and pasted to the script.

That’s exactly the reason why I came to this forum. I couldn’t find a solution for myself and am asking for help.

---

<div class="post-metadata">

**Author:** ![WLG3R](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/wlg3r/32/6985_2.png) [@WLG3R](https://discuss.dev.twitch.com/u/WLG3R)\
**Post date:** [June 26, 2020, 12:03am UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/11 "2020-06-26T00:03:03Z")

</div>

The only option is have your oauth url redirect time local host which doesn’t exist, but the auth token will be in the url, then have them copy paste that into your webpage as a query string then embed it, but they will have to redo that manually around every 60 days or so.

---

<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:** [June 26, 2020, 12:07am UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/12 "2020-06-26T00:07:11Z")

</div>

> [@BarryCarlyon](#):
>
> Then you are stuck as you need to use a server to get the token, even if that token is then copied and pasted to the script.

> [@WLG3R](#):
>
> The only option is have your oauth url redirect time local host which doesn’t exist, but the auth token will be in the url, then have them copy paste that into your webpage as a query string then embed it, but they will have to redo that manually around every 60 days or so.

I suggest that already 😃

---

<div class="post-metadata">

**Author:** ![Winder](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/winder/32/9273_2.png) [@Winder](https://discuss.dev.twitch.com/u/Winder)\
**Post date:** [June 26, 2020, 4:31pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/13 "2020-06-26T16:31:20Z")

</div>

> [@WLG3R](#):
>
> The only option is have your oauth url redirect time local host which doesn’t exist, but the auth token will be in the url, then have them copy paste that into your webpage as a query string then embed it, but they will have to redo that manually around every 60 days or so.

That won’t work, due to cross origin policy.  
Because Twitch doesn’t allow the login page to be embedded in an iframe, I have to use a new window. But I can’t access the window’s location, due to cross origin.

But thanks to you, I got a new idea, which I didn’t try yet. I’ll write the result as a new reply next week (because I’ll get a busy weekend).

---

<div class="post-metadata">

**Author:** ![Winder](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/winder/32/9273_2.png) [@Winder](https://discuss.dev.twitch.com/u/Winder)\
**Post date:** [July 9, 2020, 8:11pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/15 "2020-07-09T20:11:48Z")

</div>

Hi there,

I’m sorry, but due to the new chat security feature, which disallows embedding the chat in an iframe, if no parent is provided, I had no time to work on this problem, but rather worked on that new one.

I let you know whether my idead works as soon as I have tested it!

---

<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:** [July 9, 2020, 9:32pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/16 "2020-07-09T21:32:34Z")

</div>

yeah file:// is not supported for chat embeds.

And in your case, I’d of thought you’d be connected to chat as the bot and processing/display the chat so no need to embed the iframe.

---

<div class="post-metadata">

**Author:** ![Winder](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/winder/32/9273_2.png) [@Winder](https://discuss.dev.twitch.com/u/Winder)\
**Post date:** [July 10, 2020, 2:59pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/17 "2020-07-10T14:59:38Z")

</div>

> [@BarryCarlyon](#):
>
> And in your case, I’d of thought you’d be connected to chat as the bot and processing/display the chat so no need to embed the iframe.

Yes, that’s right. But I did embed it. Now, I’m working on an own way to display the chat messages I receive. And I’m nearly done.

---

<div class="post-metadata">

**Author:** ![Winder](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/winder/32/9273_2.png) [@Winder](https://discuss.dev.twitch.com/u/Winder)\
**Post date:** [July 19, 2020, 9:41am UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/18 "2020-07-19T09:41:20Z")

</div>

Hi there,

finally, I had time to work on the idea I got. Unfortunately, it did not work.

I tried, like WLG3R wrote above, to let the redirect go to a localhost, which doesn’t exist. But I could find no way to retrieve the URL from that redirect. I tried it with XMLHttpRequest, the new Fetch API and an iframe. None of them did reveal the URL of the failed redirect.

---

<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:** [July 19, 2020, 11:46am UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/19 "2020-07-19T11:46:40Z")

</div>

> [@BarryCarlyon](#):
>
> The alternative to this is a downloadable program, as something like electron can capture the return in various ways, and then serve the content/script off a local webserver.

Electron the desktop program can capture the failiure.

Or you get the user to

> [@BarryCarlyon](#):
>
> even if that token is then copied and pasted to the script.

copy and paste the token from the URL of the broken redirect

Or you throw a page up on GitHub like this

[https://barrycarlyon.github.io/twitch\_misc/authentication/implicit\_auth/](https://barrycarlyon.github.io/twitch_misc/authentication/implicit_auth/)

Which’ll return the users oAuth token after implicit auth for the user to copy and paste from GitHub to your program

---

<div class="post-metadata">

**Author:** ![Winder](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/winder/32/9273_2.png) [@Winder](https://discuss.dev.twitch.com/u/Winder)\
**Post date:** [July 20, 2020, 7:13pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/20 "2020-07-20T19:13:12Z")

</div>

> [@BarryCarlyon](#):
>
> Electron the desktop program can capture the failiure.

I don’t want to use a third party software or a desktop program. Just JavaScript.

> [@BarryCarlyon](#):
>
> copy and paste the token from the URL of the broken redirect

That is not really a solution, because the UserToken is valid only for a couple of ours. In a 24 hours stream, the user would have to open the script and enter a new token, multiple times.

> [@BarryCarlyon](#):
>
> Or you throw a page up on GitHub like this
> 
> [https://barrycarlyon.github.io/twitch\_misc/authentication/implicit\_auth/](https://barrycarlyon.github.io/twitch_misc/authentication/implicit_auth/)

Same answer like the first one.

Thanks for all of your help. But it seems, there is not even one way to get it done without a server or anything equivalent (like third parties).

---

<div class="post-metadata">

**Author:** ![WLG3R](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/wlg3r/32/6985_2.png) [@WLG3R](https://discuss.dev.twitch.com/u/WLG3R)\
**Post date:** [July 20, 2020, 9:28pm UTC](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577/21 "2020-07-20T21:28:30Z")

</div>

Implicit lasts about 60 days. You won’t have to worry about it mid stream if you just generated it. And on load check the validity of it’s short or expired ask to login again.

[Next page](https://discuss.dev.twitch.com/t/oauth-user-token-without-server/26577.md?page=2)
