Remote OAuth2 Token request failed with 401

Updates to OAuth documentation coming soon.

:smile:

1 Like

Hi @earlenceferns,

I’m going to PM you for some more information and see if we can get you up and running. We’ll then make sure any current platform gaps are identified if that’s the case, or clarify the documentation as needed.

Thanks!

1 Like

Hi Jim,
Can you please post the information you plan to PM? Others (myself) are having the same issue.

Thanks!

1 Like

This may be helpful if you are self-OAuthing…

Of course. Also we’ll obviously update the documentation.

1 Like

We’re working through the final writing of the docs for this. We’ll need to edit/review, so it will probably be a couple days yet. But here’s a summarized/just-the-facts rundown preview for you. Docs will be coming soon, but figured the sooner people know the better. Much of this info isn’t new and has been helpfully shared by @tgauchat (thanks Terry!), but there are a few subtle changes worth noting.

TL;DR

Use https://graph.api.smartthings.com to get the access code, token, and endpoints. Then use the returned uri and append any paths to it to make calls.

More details below:

Get Authorization Code

GET https://graph.api.smartthings.com/oauth/authorize?
        response_type=code&
        client_id=YOUR-SMARTAPP-CLIENT-ID&
        scope=app&
        redirect_uri=YOUR-SERVER-URI

This will require the user to log in with their ST credentials, choose a Location, and select what devices may be accessed. An authorization code will be returned that lasts for 24 hours.

Note that when a location is chosen, SmartThings will attempt to find a SmartApp with the requested client ID on the specific server associated with that location. If one cannot be found, it will fail to load the devices, with a message about no SmartApp being found for that client ID. This is what is happening with SmartApps that are not published to all servers, or if they are using client IDs/secrets for a different server.

Get Access Token

Use the authorization code, along with the client ID and secret, to get the access token.

POST https://graph.api.smartthings.com/oauth/token

The following parameters should be sent on the request:

  • grant_type: use “code” for this flow.
  • authorization_code: this is the authorization code obtained from the previous step.
  • client_id: this is the client id of the SmartApp. It is the identifier for the SmartApp.
  • client_secret: the OAuth client secret of the SmartApp.
  • redirect_uri: the URI of the server that will receive the token. This must match the URI you used to obtain the authorization code.

GET requests to https://graph.api.smartthings.com/oauth/token will also work, but POST is preferred.

That will return a response like:

{
  "access_token": "XXXXXXXXXXX",
  "expires_in": 1576799999,
  "token_type": "bearer"
}

The token is long-lived (50 years) and doesn’t support refresh tokens. Refresh tokens will be supported in a future release.

The access token should be kept securely by the third party.

Get SmartApp Endpoints

Using the access token, get the endpoint for the SmartApp:

GET -H "Authorize: Bearer ACCESS-TOKEN" "https://graph.api.smartthings.com/api/smartapps/endpoints"

A successful response will look like this (we will probably remove sending back the client secret soon, and the url is there for legacy purpose - use the uri):

{
    "oauthClient": {
        "clientSecret": "CLIENT-SECRET",
        "clientId": "CLIENT-ID"
    },
    "uri": "BASE-URL/api/smartapps/installations/INSTALLATION-ID",
    "base_url": "BASE-URL",
    "url": "/api/smartapps/installations/INSTALLATION-ID"
}

Make API Calls

Use the uri to make REST calls, appending any path mappings for your specific SmartApp. Previously, we could just assume the SmartApp was installed on https://graph.api.smartthings.com, and we would append the url to it. Now, because the SmartApp may be installed on different servers for different locations, the uri should be used.

I hope that helps people even though the docs aren’t finalized yet, thanks for being patient :smile:

1 Like

Thanks for the heads-up notes, Jim!

  1. Because the access_token is uniquely generated by the Account holder (user / customer) at the time of SmartApp authorization (i.e., via a web page executing the steps you list), is there any vulnerability exposed if that Account holder (user / customer) is given this particular access_token? Automatic login to directly served web services SmartApps is facilitated by allowing the user to use their access_token (at their discretion) in their URI.

  2. If the third-party suspects that one, many, or all of their users’ access tokens have been compromised, what is the recommended process for the vendor to coordinate between themselves, SmartThings, and the affected users? e.g., IFTTT has a major security breach. Should users just delete their IFTTT accounts? Uninstall the IFTTT connector SmartApp? Call their local police department? :oncoming_police_car:

(You’re welcome to respond privately, if preferable.)

@slagle or @Jim

Should the URI that is returned include both the HTTPS:// and be followed by the port :443? Like this

https://graph.api.smartthings.com:443

I think browsers, etc., automatically default port 443 for all “HTTPS” connections (just as they default to port 80 for non-SSL, http://).

1 Like

Would someone be able to help me out with this. I had a method that was working before but it looks like somethings changed but my inexperience does not tell me what. Before I was doing all of this right through my web browser.
So far I am able to receive the “CODE” using:

https://graph.api.smartthings.com/oauth/authorize?response_type=code&client_id=MYCID&scope=app&redirect_uri=https://graph.api.smartthings.com/oauth/callback

My next step was to get the token I use:

https://graph.api.smartthings.com/oauth/token?grant_type=authorization_code&client_id=MYCID&client_secret=MYSECRET&redirect_uri=https://graph.api.smartthings.com/oauth/callback&scope=app&code=MYCODE-I-GOT-FROM-ABOVE

This gives me:

{"error":"invalid_request","error_description":"Remote OAuth2 token request failed with code: 401, text: Unauthorized"}

Sorry I don’t fully understand the specifics but just knew how to get it to work by instructions given to me by another forum member. This worked perfectly in the past but now does not.

Thanks for any help you can give that may be dummy proof!

My browser does not do that, I am using the latest chrome. What I was talking about was not browser related however. In the response I get back from the server that is in the response.

Yes, I get:

https://graph.api.smartthings.com:443/api/smartapps/installations/UUID

Where the UUID is unique to the installation.

2 Likes

Thanks Brice,

I just wanted to make sure I was getting the proper response. I think having the https:// and the port is kind of redundant, but it works so who am I to complain. I just need an international user to test it now.

I believe it does, behind the covers.

i.e., When you use http://x.com the browser does not show you it is actually going to http://x.com:80.
Similarly: https://x.com the browser does not show you it is actually going to https://x.com:443.
I believe that this convention is universal and also applied for server-to-server communication (REST-API calls, etc.).

In other words, the :443 is completely redundant as long as the target server is using the default standard port for SSL https, just as :80 is completely redundant as long as the target server is using the default for http://.

Try adding :80 or :443 to your address and you’ll see typical results from many servers, such as, when I add :443 to an http:// …

Your browser sent a request that this server could not understand.
Reason: You’re speaking plain HTTP to an SSL-enabled server port.
Instead use the HTTPS scheme to access this URL, please.

It’s completely redundant unless the target server is using non-standard port(s).
This would be unlikely for a major server like SmartThings’s cloud, but very common for home servers behind NAT routers / firewalls.

I figured my issue out.

I tried using Curl with:

curl -k "https://graph.api.smartthings.com/oauth/token?grant_type=authorization_code&client_id=MYCID&client_secret=MYSECRET&code=MYCODE&redirect_uri=https%3A%2F%2Fgraph.api.smartthings.com%2Foauth%2Fcallback&scope=app"

and this worked.

Like I said I am so inexperienced with this but at least I got it to work :smile:

3 Likes

Does this problem be fixed? I’ve encountered the same problem (500 Internal server error when try to get authorization code) since Nov. 16.

This September I’ve followed the SmartThings Web Services Implementation - Developing an “API Access” Application and successfully received the access token. But currently the same SmartApp can not pass the OAuth process at the very first step.

The URL that I try to get authorization code is:
https://graph.api.smartthings.com/oauth/authorize?response_type=code&client_id=MY_OAUTH_CLIENT_ID&scope=app&redirect_uri=https://graph.api.smartthings.com/oauth/callback

The browser that I used are Chrome and Firefox, they all return the similar error:

Oh No! Something Went Wrong!
**Error:**500: Internal Server Error
URI:/oauth/callback
**Reference Id:**afb0f7b2-b903-48ab-bd00-42cc1bd962e2
**Date:**Mon Nov 16 18:06:09 UTC 2015

The customer support suggest me to post my question to the community for getting experts help. I’ve read @Jim’s post, but not sure where is my SERVER-URI. The hub that encountered OAuth problem is located at Taiwan.

Anyone can share their experience for helping me to fix my problem?

so I haven’t updated oauth codes in awhile, and now mine is broken. what is the process to manually oauth applications?

This was my old script:

first go here and put in client id from oauth from smartapp https://graph.api.smartthings.com/oauth/authorize?response_type=code&redirect_uri=http://localhost&scope=app&client_id=$clientid

copy the url http://localhost/?code=$code

use this url with client id, secret oauth key, and code https://graph.api.smartthings.com/oauth/token?grant_type=authorization_code&scope=app&redirect_uri=http://localhost&client_id=$clientid&client_secret=$clientsecret&code=$code

save access token, it is for the authentication {“access_token”:“7871b079-5392-4eef-a382-83fa3a3face3”,“token_type”:“bearer”,“expires_in”:1576799999,“scope”:“app”}

Go to this url and get smartapp ID https://graph.api.smartthings.com/api/smartapps/installations

Get all the contact sensor id’s and switch id’s.

Does your application expose an endpoint to handle receiving the code and token?

The documentation for OAuth token grants is here.

Full example code can also be found here

2 Likes

Actually i fixed it by pasting the clientid/secretid/code url into an incognito window. why does it work in incognito mode, but not just in a new browser tab? it used to work this way.

1 Like