Homeyscript for bearer token

Hi,

I have a Homey script that I use to fetch my Bearer Token, I need that for the “Realtime Homey logger” and “Flow Viewer” webpages made by irritanterik.

I found the script through this wonderfull website: Getting a bearer token - Homey (solweb.no)

This worked flawlessly for ages, but now when I run it on the my.homey.app (the original homeyscript.homey.app page automaticly redirects you to my.homey.app) it gives me an error.

Anyone is having the same problem?
Anyone knows of another (easy) way to get the bearer token?

Thanks in advance!

1 Like
  • Go to website: Homey Developer Tools
  • In browser open Web Console or use F12
  • Select all in Web Console to view all data
  • Login to Homey Developer Tools
  • Use search option in Web Console to find bearer
  • You’ll find authorization: Bearer 123…789 and can copy it to your config.js

Thanks Hansie,

I am aware of that method, but was hoping for a simpler solution. The script was awsome; with a flow I would get my token automaticaly. (/me is lazy :wink: )

1 Like

Nice Script! haven’t tested it yet.
Did you maybe enable 2 factor authentication?

No I didn’t.

I agree it’s a very nice, even ingenious script Andreas made. I guess Athom changed something to the accounts.athom.com/authorise page (maybe due to the 2FA solution) but in my memory I has still worked for some time after 2FA was introduced.

After looking at the script again I doubt that it has anything to do with the redirection to my.homey.app.
I’ve taken another look at it, but it is beyond my skills to repair the script :sweat:

Hansie’s method will do of course, but the script was an easy way to automaticaly update the bearer token in the config.js of the realtime logger config.js.

It looks like the issue is with fetch() behaving differently.

Here’s a fixed version:

// -------- o - Configure these parameters -------- o -------- o 
let email = 'REPLACEME'
let password = 'REPLACEME'
let client_id = REPLACEME
let client_secret = 'REPLACEME'
let redirect_url = 'http://localhost'
let cloudid = 'REPLACEME'
// -------- o -------- o -------- o -------- o -------- o 

const between = function(str, strf, strt) {
    return str.split(strf).pop().split(strt)[0].trim();
}

const authurl = 'https://accounts.athom.com/login'
console.log("POST authentication " + authurl)
const response2 = await fetch(authurl, {
  "headers": {
    "accept": "application/json, text/javascript, */*; q=0.01",
    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
  },
  "referrerPolicy": "no-referrer-when-downgrade",
  "body": 'email=' +encodeURIComponent(email) + '&password=' + encodeURIComponent(password) + '&otptoken=',
  "method": "POST",
  "mode": "cors",
  "credentials": "omit"
})
const body2 = await response2.text()
const token = JSON.parse(body2)

const authorizeurl = 'https://accounts.athom.com/oauth2/authorise?client_id=' + client_id + 
    '&redirect_uri=' + encodeURIComponent(redirect_url) + '&response_type=code&user_token=' + token.token


console.log(" Response from accounts.athom.com/login ", body2)
console.log("GET Authorization " + authorizeurl)

const response3 = await fetch(authorizeurl, {
  "headers": {
  },
  "method": "GET",
  "mode": "cors",
  "credentials": "include"
})
const body3 = await response3.text()
let csrf = between(body3, 'name="_csrf" value="', '">')
let cookiecsrf = null;
let raw = response3.headers.raw()['set-cookie'];
for (let cookie of raw) {
  if (cookie.startsWith('_csrf=')) {
    cookiecsrf = cookie.match(/=(.+?);/)[1];
    break;
  }
}

let cookie4 = '_csrf=' + cookiecsrf
// console.log("Cookie4", cookie4)
console.log(" CSRF input parameter", csrf)
console.log(" CSRF cookie", cookiecsrf)

let authorizeurl2 = 'https://accounts.athom.com/authorise?client_id=' + client_id +   '&redirect_uri=' + encodeURIComponent(redirect_url) + '&response_type=code&user_token=' + token.token
console.log("GET Authorization", authorizeurl2)
const response4 = await fetch(authorizeurl2, {
  "headers": {
    "content-type": "application/x-www-form-urlencoded",
    "cookie": cookie4
  },
  "redirect": "manual",
  "body": "resource=resource.homey." + cloudid + "&_csrf=" + csrf + "&allow=Allow",
  "method": "POST",
  "mode": "cors",
  "credentials": "include"
});

const body4 = await response4.text()

let code = response4.headers.get('location').split('=')[1]

console.log(" Response from authorization. Redirect to ", response4.headers.get('location'))
console.log(" Response content ", body4)
console.log(" Parsed the following code ", code)



let tokenendpoint = 'https://api.athom.com/oauth2/token'
console.log("POST token (resolve code to token) " + tokenendpoint)
const response5 = await fetch(tokenendpoint, {
  "headers": {
    "content-type": "application/x-www-form-urlencoded",
  },
  "body": 'client_id=' + encodeURIComponent(client_id) +  '&client_secret=' + encodeURIComponent(client_secret) + 
    '&grant_type=authorization_code&code=' + encodeURIComponent(code),
  "method": "POST",
  "mode": "cors",
  "credentials": "include"
});


//console.log("Response5", response5)
const body5 = await response5.text()
let accesstoken = JSON.parse(body5)





let delegationEndpoint = 'https://api.athom.com/delegation/token?audience=homey'
const response6 = await fetch(delegationEndpoint, {
  "headers": {
    "content-type": "application/x-www-form-urlencoded",
    "authorization": "Bearer " + accesstoken.access_token
  },
  "referrerPolicy": "no-referrer-when-downgrade",
  "body": "client_id=" + client_id + " &client_secret=" + client_secret + "&grant_type=refresh_token&refresh_token=" + accesstoken.refresh_token,
  "method": "POST",
  "mode": "cors",
  "credentials": "include"
});



const body6 = await response6.json()
console.log(" JWT token is " + body6)

let endpoint7 = 'https://' + cloudid + '.connect.athom.com/api/manager/users/login'
console.log("POST login endpoint " + endpoint7)
const response7 = await fetch(endpoint7, {
  "headers": {
    "content-type": "application/json",
    //"authorization": "Bearer " + accesstoken.access_token
  },
  "body": JSON.stringify({"token": body6}),
  "method": "POST"
});

const body7 = await response7.json()
console.log(" Response status " + response7.status)
console.log(" Response: " + body7)

await setTagValue("accesstoken", {type: 'string', title:'Access token'}, body7)
return true
7 Likes

Yay!!! That was quick! Many thanks RobertKlep. Really apreciated.

the format for setTagValue is also changed:
Warning: setTagValue(id, opts, value) is deprecated, please use tag(id, value)

2 Likes

I need some help with this.
I used @robertklep’s version to create the Homeyscript but when I run it I get:

❌ Script Error
⚠️ Error: invalid_type
    at Remote Process

When I use tag instead of setTagValue as remarked by @JPe4619 I still get the same error.

No problem here, with or without the change:
image

It doesn’t return a 200 for me.

image

Do you have MFA active?

[edit]
Found the issue in the output of the script.

POST authentication https://accounts.athom.com/login
 Response from accounts.athom.com/login  {"code":401,"error":"missing_otp","error_description":"The 2FA token is missing. Please append it to the password."}

So you can’t use this (in an automated way) with MFA?

I changed await setTagValue(“accesstoken”, {type: ‘string’, title:‘Access token’}, body7) to:
await tag(“accesstoken”, body7) and have no error message.

coulld be the problem, I dont use it.

Yep, that was the problem. Added it to the password and it worked.

1 Like

@Le_Cactus & @robertklep & homey.solweb.no
Just found this script: Thanks a mil, guys!!
This way it is a lot more comfortable / easy to retrieve the *%$& token :partying_face:

This bearer token is equivalent api key for homey 2016/2019?

I guess the answer can be found in an other topic, from this post onwards.