RESOLVED : Feel free to refer to my notion page (link) for all the steps I had to take.
Original Post
I’m not a programmer, but I wanted to set up keyboard shortcuts to control my Samsung TV (power on/off, switch HDMI, etc), and Perplexity helped me write the scripts that I can use with keyboard shortcut software (BetterTouchTool on Mac). I got the scripts to work as intended, but I learned that a personal token only lasts for 24 hours. Now I want to make it a more permanent solution.
I spent the last 2 hours trying to obtain an OAuth2 token, and I’m not getting anywhere.
Installed the SmartThings CLI on my MacBook via Terminal
Got a temporary webhoook.site redirection URL
Created an OAuth-In app via Terminal (smartthings apps:create then verified with smartthings apps:oauth 1)
Display Name TV
App Id 42431bd0-bfa2-...
App Name atv-f0c8a261-...
Description TV
Single Instance true
Classifications CONNECTED_SERVICE
App Type API_ONLY
Scope r:devices:$,r:devices:*,r:hubs:*,r:installedapps,r:locations:*,r:rules:*,r:scenes:*,w:devices:$,w:devices:*,w:installedapps,w:locations:*,w:rules:*,x:devices:$,x:devices:*,x:locations:*,x:scenes:*
Redirect Uris https://webhook.site/9ac56e98-....
From my browser, I see This URL has no default content configured error message, and from webhoook.site, I see under Query strings, error "server_error"
I have tried a few other troubleshooting solutions offered by Perplexity, but I’m stuck in a loop. Any recommendation?
Here is a description I wrote showing in basic terms how you can get access tokens and then how you can refresh them.
It looks like you are certainly on the right path but it may be worth taking webhook.site out of the loop as you are really just interested in the URL.
I had the same idea - a “quick” SmartThings OAuth setup for a Samsung TV (and some lights). Agony. I finally got it working, and here are my findings, in addition to the excellent instructions from orangebucket). Some of these notes are for ‘later in your journey’ - when you want to keep using access tokens …
Here’s the URL that worked for me (client_id obfuscated, https://httpbin.org/get was my nominated redirect)… https://api.smartthings.com/oauth/authorize?client_id=6e98456b-8532-4d0e-b187-b8df44eff0c1&response_type=code&redirect_uri=https://httpbin.org/get&scope=r:devices:*%20w:devices:*%20x:devices:*%20r:locations:*%20w:locations:*%20r:scenes:*%20x:scenes:*%20r:installedapps:*%20w:installedapps:*
I didn’t have &state=xyz on my URL.
If Edge is your default browser some steps may not work (it failed for me) - it messes up the login process on the CLI, and (consequently) the redirect when that’s supposed happen. I changed to Chrome and it logged in and redirected. Before that I was getting a lot of those “server error” messages.
Each and every access token is only valid for 24 hours so you have to refresh it every day if you want continuous access (86399 seconds = 23:59:59). I have an iOS Shortcut automation that runs every day to do this.
Each refresh token is single-use. So when you use it to refresh, you need to keep the new refresh token (from the response) and discard the one you just used. It has to be an unbroken chain of refresh token usage.
The access token expires when you refresh (or after 24 hours, whichever is the sooner). So you need to keep the new access token (from the response) and discard the one you have been using.
If you refresh using an automated POST call (as I do in my daily shortcut, or you might in Python), you need the {client_id}:{secret} in a base64 encoded state. I use Data Jar in iOS Shortcuts to store:
Current refresh token (replaced with new value each day)
Current access token (replaced with new value each day)
If you refresh using curl, you don’t need base64 encoding, and the command will be:
curl -X POST “https://api.smartthings.com/oauth/token” ^
-u “{client_id}:{secret}” ^
-H “Content-Type: application/x-www-form-urlencoded” ^
-d “grant_type=refresh_token&client_id={client_id}&refresh_token={current refresh token}”
Hope this helps.
PS this is my first post, so apologies for any conventions or etiquette I have transgressed.
It is optional. For those not familiar with it, the state query parameter will be appended to the query string when the OAuth server (SmartThings in this case) redirects to your redirect_uri.
It doesn’t really gain you anything in the basically manual flow being described in this thread. However in an app where the flows are automated the state can be helpful in validating that the callback is genuine, and also help tie it to a specific request.
worked flawlessly with Docker Desktop installed on my Mac, and an installation of Httpbin docker image, along with Port forwarding to my laptop. Not sure if this entire setup was necessary, but this setup gave me the 6 digit token I needed from my Mac Safari Browser.
Perplexity gave me this step-by-step guide to automate SmartThings token renewal using Google Cloud, store tokens in Google Drive, and use them with BetterTouchTool. but I find it overwhelming, and am looking for a simpler solution.
The real charm of AI is that it gives you the answer before you even figure out what you’re actually asking. You’re still just as confused, just with a solution in hand.
@fpenguin not sure if you’ve got what you need yet, but in case it’s useful to have some notes for an iOS Shortcuts approach:
I have a shortcut that refreshes my access and refresh tokens. It’s based on the suite of useful SmartThings shortcuts created by @rambo350z[referenced here].
My “Get contents of URL” does look different from yours. I’ll include some screenshots that might show how.
Given the need for a persistent store for the access token and refresh token, I use Data Jar to store these. I also store the full ‘response’ each time I run the refresh, and the values I’ll need to construct the URL call:
… where ‘Renamed_item’ is the renamed text object ‘grant_type=refresh_token&client_id={Client_ID}&refresh_token={Refresh_Token}’ shown in a screenshot above. I don’t know if all that renaming is necessary… I have it working so I’m unwilling to fiddle with it.
The “Authorization” header uses the base64 encoding of the {client_id}:{secret}. I used https://www.base64encode.org/ to create this.
{"error":"invalid_grant","error_description":"Invalid refresh token requested by clientId: 6e98456a-8532-4d0e-b187-b8df44eff0c1 with grantType: refresh_token, e.cause: no cause"}
Edit: I forgot to include the screenshot of what I do next: I store the response as a dictionary, extract the values for access_token and refresh_token, and finally store these in Data Jar so that I can use these for authorisation and refresh a day later:
Glad I could help. I didn’t know that there was a built-in base64 encoder – I’ll use that in future. So, thanks to you @fpenguin.
Incidentally, I have a Wordpress site that shows some summary information gleaned from ST such as the temperature at an elderly relative’s house, with conditional colours (blue, white, amber, red), so we know he’s okay. That obviously needs the access-code, so I’ve added a ‘POST’ API to my Wordpress website which updates the stored access-code; and a ‘GET’ to read the value.
Let me know if that’s of interest and I’ll post some details.
I tried to send in the url without ”&scope”.
Then I got further in the web UI and was asked to select the scope in different optional check boxes. After that I received the 6 digit code
Now everything works great. I receive new tokens when running your iOS shortcut,
”SmartThings Token refresh” with values stored in ”Data Jar”