Skip to content

Commit

Permalink
Add redirect auth server URL option
Browse files Browse the repository at this point in the history
Update default to https
  • Loading branch information
brbeaird committed Oct 25, 2021
1 parent b67b0aa commit 5877af2
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 11 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 4.1.2 (2021-10-25)

### Added
- Added ability to specify redirect auth server

### Changed
- Changed default redirect auth URL to https

## 4.1.1 (2021-09-30)

### Fixed
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@ If you have not set up the GitHub integration yet or do not know about it, take
In the future, should you wish to update, simply repeat steps 2 and 3. The only difference is you will see the device types/SmartApp show up in the "Obsolete (updated in GitHub)" column instead.

### Authentication
First of all, special thanks to hjdhjd and the work at [homebridge-myq](https://github.com/hjdhjd/homebridge-myq) for figuring all of this out and documenting it so well.
First of all, special thanks to hjdhjd and the work at [homebridge-myq](https://github.com/hjdhjd/homebridge-myq) for figuring all of this out and documenting it so well.
The newest version of the MyQ API uses an OAuth flow. The SmartApp can handle most of this on its own, but there is one step that requires halting a web redirect to grab a code out of the URL. This is something the SmartThings groovy implemlentation cannot do. As a workaround, I now have the SmartApp make a callout to a 3rd-party endpoint I am hosting (http://brbeaird.herokuapp.com/getRedirectCode). The SmartApp passes in a URL and cookie from an auth'd MyQ session, and in return, the endpoint passes back a code. The SmartApp then uses that code to generate the OAuth access code and refresh token. It is important to note that because no part of your email, password, or the SmartApp-generated PKCE challenge verifier is passed over, the endpoint does not have the ability to login as you or generate a token itself. Also note that the endpoint is only called when a refresh token is not available, which is typically only upon initial install. Otherwise, callouts should be very rare, and the SmartApp will be able to cycle through refresh tokens on its own.

If you would like to host this auth redirect server yourself, you can find the code at https://github.com/brbeaird/MyQRedirectCode. You can then specify your server's URL in the "Advanced (optional)" section on the Username/password input page of the SmartApp setup.

Still, if you would prefer to avoid the need to make this callout, I have left in the option to generate a refresh token on your own and provide it to the SmartApp. I also included some javascript code and pre-compiled binaries to do that. Instructions are below.

### Manual Token Auth (Optional)
Expand All @@ -61,12 +63,12 @@ This involves logging into MyQ to get an access token. You can then enter that t
2. On Linux or MacOS, you will need run the appropriate chmod commands and enable it to be run. For MacOS:
1. Make sure your system allows running these files: System preferences > Security & Privacy > give permission to run
2. From the terminal, navigate to the directory of the utility and run `chmod u+x myqtokengenerator-macos`
3. Run `./myqtokengenerator-macos`
3. Run `./myqtokengenerator-macos`
4. On Windows, double-click and run, granting permissions as needed.
5. At the prompt, enter your MyQ username and password. If successful, the utility will output an access token.
![SmartApp List](/icons/TokenGenerator.png "Token Generator")
![SmartApp List](/icons/TokenGenerator.png "Token Generator")
6. Back in the SmartApp setup, choose the "Manual Token" Login method, then paste in your token. You might find it easier to do this via web browser of the computer you used to generate the token (https://my.smartthings.com).


### Overview
This SmartApp integrates Chamberlain/LiftMaster MyQ doors and plug-in lamp module controllers into SmartThings. It creates a garage door device and/or a light device in your list of Things and allows you to control the device...
Expand Down
2 changes: 1 addition & 1 deletion installerManifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"iconUrl": "https://raw.githubusercontent.com/brbeaird/SmartThings_MyQ/master/icons/myq.png",
"published": true,
"oAuth": true,
"version": "4.1.1",
"version": "4.1.2",
"appSettings": {},
"appUrl": "smartapps/brbeaird/myq-lite.src/myq-lite.groovy"
},
Expand Down
18 changes: 12 additions & 6 deletions smartapps/brbeaird/myq-lite.src/myq-lite.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import groovy.transform.Field

include 'asynchttp'

String appVersion() { return "4.1.1" }
String appModified() { return "2021-09-30"}
String appVersion() { return "4.1.2" }
String appModified() { return "2021-10-25"}
String appAuthor() { return "Brian Beaird" }
String gitBranch() { return "brbeaird" }
String getAppImg(imgName) { return "https://raw.githubusercontent.com/${gitBranch()}/SmartThings_MyQ/master/icons/$imgName" }
Expand Down Expand Up @@ -187,9 +187,13 @@ def prefLogIn(params) {
return dynamicPage(name: "prefLogIn", title: "Connect to MyQ", nextPage:"loginResultPage", uninstall:false, install: false, submitOnChange: true) {
if (loginMethod == "Email/Password"){
section("Login Credentials"){
input("username", "email", title: "Username", description: "MyQ Username (email address)")
input("password", "password", title: "Password", description: "MyQ password")
}
input("username", "email", title: "Username", description: "MyQ Username (email address)")
input("password", "password", title: "Password", description: "MyQ password")
}
section("Advanced (optional)", hideable: true, hidden:true){
paragraph "Specify the auth server to get the redirect code"
input "authRedirectServer", "text", required: false, title: "Server URL", defaultValue: "https://brbeaird.herokuapp.com"
}
}
else{
section("Advanced (optional)"){
Expand Down Expand Up @@ -1276,10 +1280,12 @@ private getNewAccessToken(){
//This step requires halting the redirect and grabbing the code from MyQ. Because we cannot do this with Groovy, we hand off the cookie and redirectURL to a cloud-hosted app.
// Note that the challenge verifier is NOT passed over, so the cloud app will not be able to login or actually generate a token for your account
log.trace "uri: ${authEndpoint + redirectUrl}, headers: ${redirectHeaders}"
def url = authRedirectServer ? authRedirectServer : "https://brbeaird.herokuapp.com"
log.debug "Getting redirect code from ${url}/getRedirectCode"
def code
def scope
try {
httpPostJson([ uri: "http://brbeaird.herokuapp.com", path: "/getRedirectCode", headers: ["Content-Type": "application/json"], body: ["redirectUrl": authEndpoint + redirectUrl, "cookie": loginCookie]]) { response ->
httpPostJson([ uri: url, path: "/getRedirectCode", headers: ["Content-Type": "application/json"], body: ["redirectUrl": authEndpoint + redirectUrl, "cookie": loginCookie]]) { response ->
//log.trace "Redirect response: ${response.status}\n${response.data}"
if (response.status == 200) {
code = response.data.code
Expand Down

0 comments on commit 5877af2

Please sign in to comment.