From 595cd99bdfe2ea92fb20995615df6dcad01a6c86 Mon Sep 17 00:00:00 2001 From: Roman Iakoubtchik Date: Mon, 19 Oct 2015 02:21:05 -0400 Subject: [PATCH] Remove Authorization, Manual Token Update Since Wink does not currently allow ST to authorize using their API, we can remove the authorization and manually hard-code the access & refresh tokens. Using Advanced REST client (Chrome, Firefox) we set the following: URL: https://winkapi.quirky.com/oauth2/token Request: POST Payload: {"client_id":"c22d82a7fc3d6faf06dcff1bcf0feb52","client_secret":"bd44c524a1df9dce134235d174350603","username":"wink-app@email.com","password":"wink-app-pass","grant_type":"password"} Content-Type: application/json --- Quirky-Connect-Service-Manager.groovy | 63 +++++++++++++++------------ 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/Quirky-Connect-Service-Manager.groovy b/Quirky-Connect-Service-Manager.groovy index da5a456..cfaa7d7 100644 --- a/Quirky-Connect-Service-Manager.groovy +++ b/Quirky-Connect-Service-Manager.groovy @@ -72,15 +72,14 @@ import java.text.DecimalFormat import groovy.json.JsonSlurper // Wink API stuff -private apiUrl() { "https://winkapi.quirky.com/" } +private apiUrl() { "https://winkapi.quirky.com/" } private getVendorName() { "Quirky Wink" } private getVendorAuthPath() { "https://winkapi.quirky.com/oauth2/authorize?" } -private getVendorTokenPath(){ "https://winkapi.quirky.com/oauth2/token?" } +private getVendorTokenPath() { "https://winkapi.quirky.com/oauth2/token?" } private getVendorIcon() { "https://s3.amazonaws.com/smartapp-icons/Partner/quirky@2x.png" } -private getClientId() { "c22d82a7fc3d6faf06dcff1bcf0feb52" } // Dan Lieberman's -private getClientSecret() { "bd44c524a1df9dce134235d174350603" } - -private getServerUrl() { "https://graph.api.smartthings.com" } +private getClientId() { appSettings.clientId } +private getClientSecret() { appSettings.clientSecret } +private getServerUrl() { appSettings.serverUrl } // Automatically generated. Make future change here. @@ -93,23 +92,29 @@ definition( iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/quirky.png", iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/quirky@2x.png", oauth: true -) +) { + appSetting "clientId" + appSetting "clientSecret" + appSetting "serverUrl" + appSetting "vendorAccessToken" + appSetting "vendorRefreshToken" +} mappings { - path("/receivedToken") { action:[ POST: "receivedToken", GET: "receivedToken"] } - path("/receiveToken") { action:[ POST: "receiveToken", GET: "receiveToken"] } + path("/receivedToken") { action:[ POST: "receivedToken", GET: "receivedToken"] } + path("/receiveToken") { action:[ POST: "receiveToken", GET: "receiveToken"] } path("/propaneTankCallback") { action:[ POST: "propaneTankEventHandler", GET: "subscriberIdentifyVerification"]} path("/airConditionerCallback") { action:[ POST: "airConditionerEventHandler", GET: "subscriberIdentifyVerification"]} - path("/powerstripCallback") { action:[ POST: "powerstripEventHandler", GET: "subscriberIdentifyVerification"]} - path("/sensor_podCallback") { action:[ POST: "sensor_podEventHandler", GET: "subscriberIdentifyVerification"]} - path("/piggy_bankCallback") { action:[ POST: "piggy_bankEventHandler", GET: "subscriberIdentifyVerification"]} - path("/eggtrayCallback") { action:[ POST: "eggtrayEventHandler", GET: "subscriberIdentifyVerification"]} - path("/cloud_clockCallback") { action:[ POST: "cloud_clockEventHandler", GET: "subscriberIdentifyVerification"]} + path("/powerstripCallback") { action:[ POST: "powerstripEventHandler", GET: "subscriberIdentifyVerification"]} + path("/sensor_podCallback") { action:[ POST: "sensor_podEventHandler", GET: "subscriberIdentifyVerification"]} + path("/piggy_bankCallback") { action:[ POST: "piggy_bankEventHandler", GET: "subscriberIdentifyVerification"]} + path("/eggtrayCallback") { action:[ POST: "eggtrayEventHandler", GET: "subscriberIdentifyVerification"]} + path("/cloud_clockCallback") { action:[ POST: "cloud_clockEventHandler", GET: "subscriberIdentifyVerification"]} } preferences { page(name: "Credentials", title: "Fetch OAuth2 Credentials", content: "authPage", install: false) - page(name: "listDevices", title: "Quirky Devices", content: "listDevices", install: false) + page(name: "listDevices", title: "Quirky Devices", content: "listDevices", install: false) } def installed() { @@ -427,7 +432,7 @@ def createWinkSubscription(path, suffix) uri : apiUrl(), path: path, body: ['callback': callbackUrl], - headers : ['Authorization' : 'Bearer ' + state.vendorAccessToken] + headers : ['Authorization' : 'Bearer ' + appSettings.vendorAccessToken] //state.vendorAccessToken ],) { response -> log.debug "Created subscription ID ${response.data.data.subscription_id}" @@ -535,7 +540,7 @@ def deleteWinkSubscription(path, subscriptionId) httpDelete([ uri : apiUrl(), path: path + subscriptionId, - headers : [ 'Authorization' : 'Bearer ' + state.vendorAccessToken ] + headers : [ 'Authorization' : 'Bearer ' + appSettings.vendorAccessToken ] //state.vendorAccessToken ],) { response -> log.debug "Subscription ${subscriptionId} deleted" @@ -559,7 +564,7 @@ def checkToken() { try { httpGet([ uri : apiUrl(), path : "/users/me/wink_devices", - headers : [ 'Authorization' : 'Bearer ' + state.vendorAccessToken ] + headers : [ 'Authorization' : 'Bearer ' + appSettings.vendorAccessToken ] //state.vendorAccessToken ]) { response -> debugOut "Response is: ${response.status}" @@ -580,7 +585,7 @@ def checkToken() { def tokenParams = [ client_id : getClientId(), client_secret : getClientSecret(), grant_type : "refresh_token", - refresh_token : state.vendorRefreshToken ] + refresh_token : appSettings.vendorRefreshToken ] //state.vendorRefreshToken def tokenUrl = getVendorTokenPath() + toQueryString(tokenParams) @@ -626,7 +631,7 @@ def apiGet(String path, Closure callback) httpGet([ uri : apiUrl(), path : path, - headers : [ 'Authorization' : 'Bearer ' + state.vendorAccessToken ] + headers : [ 'Authorization' : 'Bearer ' + appSettings.vendorAccessToken ] //state.vendorAccessToken ]) { response -> @@ -653,7 +658,7 @@ def apiPut(String path, cmd, Closure callback) uri : apiUrl(), path: path, body: cmd, - headers : [ 'Authorization' : 'Bearer ' + state.vendorAccessToken ] + headers : [ 'Authorization' : 'Bearer ' + appSettings.vendorAccessToken ] //state.vendorAccessToken ]) { @@ -1287,7 +1292,7 @@ def authPage() { if(canInstallLabs()) { def description = null - if (state.vendorAccessToken == null) { + if (appSettings.vendorAccessToken == null) { //state.vendorAccessToken log.debug "About to create access token." createAccessToken() @@ -1361,15 +1366,17 @@ def receiveToken() { /* OAuth Step 2: Request access token with our client Secret and OAuth "Code" */ try { - httpPost(params) { response -> + //httpPost(params) { response -> - def data = response.data.data + //def data = response.data.data - state.vendorRefreshToken = data.refresh_token //these may need to be adjusted depending on depth of returned data - state.vendorAccessToken = data.access_token - log.debug "Vendor Access Token: ${state.vendorAccessToken}" + //state.vendorRefreshToken = data.refresh_token //these may need to be adjusted depending on depth of returned data + //state.vendorAccessToken = data.access_token + state.vendorRefreshToken = appSettings.vendorRefreshToken + state.vendorAccessToken = appSettings.vendorAccessToken + log.debug "Vendor Access Token: ${state.vendorAccessToken}" log.debug "Vendor Refresh Token: ${state.vendorRefreshToken}" - } + //} } catch(Exception e) {