Issue getting token in Web Services Tutorial

I’m really new to Smartthings and Ruby so please be patient if this is a dumb question!
Okay, so I’m trying my hand at a Web Service interface. I’ve been going through the tutorial and hit a snag in the /oauth/callback

The callback receives a code but then seems to fail on the client.auth_code.get_token call.

hanlde requests to /oauth/callback URL.

get ‘/oauth/callback’ do
code = params[:code]

Use the code to get the token.

response = client.auth_code.get_token(code, redirect_uri: redirect_uri, scope: ‘app’)

now that we have the access token, we will store it in the session

session[:access_token] = response.token

debug - inspect the running console for the

expires in (seconds from now), and the expires at (in epoch time)

puts 'TOKEN EXPIRES IN ’ + response.expires_in.to_s
puts 'TOKEN EXPIRES AT ’ + response.expires_at.to_s
redirect '/getswitch’
end

I receive the error: Faraday::SSLError at /oauth/callback SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

I assume the error must have something to do with an SSL setting on my machine (Windows 10) but I’m at a loss as to how to work around it. Thanks for any help!

Have you taken a look at out Sinatra app in the docs? That might be a good place to start if you haven’t.

http://docs.smartthings.com/en/latest/smartapp-web-services-developers-guide/tutorial-part2.html?highlight=webservice

Thank you for the reply. Yes, I have been following it exactly. My code is directly from the tutorial. I successfully get an authorization code by executing:

url = client.auth_code.authorize_url(redirect_uri: redirect_uri, scope: ‘app’)

Then redirecting to the URL and selecting and authorizing my devices. The code is then returned in the params passed to the /oauth/callback. It’s there that I get the SSL error when calling:

response = client.auth_code.get_token(code, redirect_uri: redirect_uri, scope: ‘app’)

I have verified that the redirect_uri passed is the same one as in the authorize_url call.
Appreciate the help.

Did you ever figure this out? I’m having the exact same problem as you.

I’m also using Windows 10

Nope. I was never able to make it work. I wasn’t able to get any technical support for the problem.

I think I encountered a similar problem whilst following the tutorial.

I receive the code without an issue but I can never get the access_token.

I contacted support and they are aware people are having issues.

Hey guys. Wondering/hoping you have time to try the stuff outlined in the GitHub issue here: https://github.com/intridea/oauth2/issues/12

I just retried this (not on windows of course) and everything seems to be working fine.

Thanks!
Dave

So I finally got my hands on a Windows 10 machine to try this out. Low and behold, I ran into the same exact error!

Here is what I’ve found out. The error is coming from the fact that you are trying to make SSL connections without a valid (localhost) certificate. Apparently, if you were to deploy the server ruby application to something like heroku (thus getting rid of localhost) it would work.

There are a few things that you can try to skirt around this.

  1. You can use a tool like OpenSSL to generate a “test” certificate against localhost. Faraday, the SSL implementation that is used in the OAuth2 module that we use in server.rb has ssl options. You should be able to set up the OAuth2 Client object with a generated cert. Add something like:
    ssl: {ca_file: 'myCert.pem'}
    to the options passed in when creating the Client object.
    I was able to get around the SSL error by simply turning SSL verification off by adding
    ssl: {verify: false}
    to the options passed into the OAuth2 Client object. Of course then I ran into the same error again when another SSL connection was trying to fire. So it is a bit of a rabbit hole.

  2. Deploy and run the server.rb file on something like Heroku.

  3. You can try to override the use of Faraday in the OAuth2 module like it says in this post here:

I changed the Faraday adapter to Typhoeus, which got me past the SSL errors.
Faraday.default_adapter = :typhoeus

There are going to be a lot of things that you are going to have to do to get that to work. You’ll have to install the typhoeus gem and any dependencies that you must along with that. When I tried this, I got stuck on an error that said that the typheous module was missing some ffi_c dependency. I guess on windows you actually have to tell bundler that you want to download and compile that module. Which leads to another rabbit hole, to be able to compile it, you must have all of the dependencies that the gem specifies it needs. I didn’t have time to try this option, maybe one of you will have more time. I don’t know why development like this on the Windows platform seems so difficult compared to other OS’s.

Has anyone been able to solve this yet? I’m trying to follow the Ruby tutorial on a Raspberry Pi but get the 500 error. I tried generating an SSL cert for my RPi as well as the option of the ssl verify false. I’m entering these options in the Options variable.

options = { site: 'https://graph-na02-useast1.api.smartthings.com', authorize_url: '/oauth/authorize', token_url: '/oauth/token', ssl: {ca_file: '/home/pi/web-app-tutorial/cert.pem'} }

I tried generating a cert using this method.

$ openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -subj '/CN=<RPi-IP>' -nodes

Thanks so much for the response. I’ve finally had time to go back to this and do some testing. I decided to go the OpenSSL route. I downloaded it and generated a localhost certificate (localkey.pem) using instructions here: Generating valid self signed certificates for localhost development | Salesforce Developers Blog .
I tried changing the OAuth2 options as follows:

options = {
site: ‘https://graph.api.smartthings.com’,
authorize_url: ‘/oauth/authorize’,
token_url: ‘/oauth/token’,
ssl: {ca_file: ‘localkey.pem’}
}
client = OAuth2::Client.new(CLIENT_ID, CLIENT_SECRET, options)

Unfortunately, that didn’t help me at all. I’m still getting (now) dreaded “Oh No! Something Went Wrong!” message in my Web Browser and a corresponding Ruby error at the command line.

I also tried the ssl:{verify:false} option to see if I could get any further in the process but with identical results.
Any suggestions would be really appreciated.

Update: Good news and bad news. Bad news is that I couldn’t get the Ruby implementation to work on localhost. The good news is that I was able to get the Node.JS example (https://github.com/schettj/SmartThings) which was referenced in the Web Services tutorial as another option to work perfectly. It actually works better for me since I have a little prior Java Script knowledge.

Here’s what I did:

  1. Downloaded the code from the link listed - StoAuth.js
  2. Downloaded and installed (the 64 bit MSI installer) NodeJS from: https://nodejs.org/en/download/
  3. Set the environment using nodevars.bat
  4. Used npm utility (installed with Nodejs) to install needed modules:
    npm install express
    npm install request
    npm install JSON
    npm install simple-oauth2

Note: I had a problem using NPM and had to open a command window with Administrator rights. From Windows Start-> Command Prompt - Right Click -> Run as Administrator

The rest of this is optional. Since I’m a DotNet guy I like using the Visual Studio Environment and the debugger works pretty well (even with Node.JS)
5) Installed the Node.JS tool for Visual Studio 2015: Tools->Extensions And Updates->Online->Node.JS Tools For Visual Studio 2015
6) New Project -> … -> Node.JS etc.
7)Paste in the StoAuth.js code
8) Under Project properties set environment variable (for my machine): NODE_PATH=c:\program files\nodejs;%APPDATA%\npm;c:\program files\nodejs\node_modules

That’s it. Simply opened localhost:3000, hit the link, signed in, selected the Smartthings to access, and viola just like the tutorial I got an access token and endpoint. Hope that helps someone!

3 Likes

Has anyone able to solve this issue? I am able to receive the OAuth Token when I am using external View but it is returning 500 Error when I am using a web view. Is there any solution to use web View and access the token? Please let me know.