Remote OAuth2 Token request failed with 401

I’m following instructions from:

http://docs.smartthings.com/en/latest/smartapp-web-services-developers-guide/tutorial-part2.html#appendix-just-the-urls-please

First, instead of getting a “page not found error” of the first step (“getting a code”), I get a 500 internal server error. However, I still see a 6 char code in the URL

When I use that code, along with my client ID and secret in the CURL request, I get this error:

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

I’ve done this process many times before and suddenly it has stopped working.
Is anyone else facing the same issue?

The “page not found” error is normal if the redirect address you send is not a real page. I’m not sure about the 401 error. Mine are working fine, so its not a system-wide problem.

I get a 500 internal server error in place of the usual page not found error.

Oh, I see. Sorry I misread that before. I’m not sure what’s wrong.

Whom do I contact with this issue? None of the Apps I create work over OAuth. It used to work without problems. Now I only get error messages. This was the latest:

Error
500: Internal Server Error
URI
/oauth/callback
Reference Id
3904354f-039b-4362-9c5c-6ec2e81636d8
Date
Mon Nov 09 19:12:45 UTC 2015

Email Support@SmartThings.com and tag @slagle here.

You’ll be well taken care of! :grinning:

1 Like

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.