MattTW/BlinkMonitorProtocol

token auth

Closed this issue · 24 comments

Hi,
I'm trying to write the api in Java.

I can login and verify pin. When I try to load homescreen, I get {"message":"Unauthorized Access","code":101}
I can parse out token.
It is probably the token, I send wrong.

In the readme's the curl examples it says --header 'token-auth: xxxx
But in the python files it is TOKEN_AUTH.

I am confused here. Does curl and/or python convert that to some header. That looks like two different header names to me.

I'm having the same issue using golang. I'm able to auth but nothing after that. I get the same code when trying to get to the homescreen. BTW, this was working for me before. It has stopped working.

Maybe we should investigate if the python scripts that float around still works.
Or if there is an API change that caused it.

The python script uses v4 login. And v5 login returns a completely different json structure.

In v4 the token is at "authtoken"."authtoken".
In v5 it is placed in "account"."auth"."token"

I suspect the way token is passed in subsequent api calls has changed too...

Any update on this issue?

Yes, have a look at this issue : #49

Concerning the use of reauth in login payload, as well as other headers. In particular the code at the end. When I have time, I'm going to rewrite my code with that as inspiration, and see if it fixes things.

Yes, have a look at this issue : #49

Concerning the use of reauth in login payload, as well as other headers. In particular the code at the end. When I have time, I'm going to rewrite my code with that as inspiration, and see if it fixes things.

I'm new to programming. Can you explain more what I need to do? I had this working until the change. THANKS!

I have now homescreen working (and probably other calls will work too). When I get some time, I will detail the steps here.

I have now homescreen working (and probably other calls will work too). When I get some time, I will detail the steps here.

GREAT! Thanks

I have now homescreen working (and probably other calls will work too). When I get some time, I will detail the steps here.

Hi larxxor, I still haven't been able to find a way to make this work. I hope you can give some details. Thanks!

Login code (Java)

`
String json = "{"app_version":"6.1.6 (9289) #8fee5f53c-mod", "password":""+passwd+"", "reauth":"true", "os_version":"14.4", "device_identifier":"iPhone11,8", "unique_id": ""+unique_id+"","client_type":"ios", "email":""+email+"", "client_name":"iPhone xxx"}";

    // add json header
    HttpRequest request = HttpRequest.newBuilder()
            .POST(HttpRequest.BodyPublishers.ofString(json))
            .uri(URI.create(loginTier+post_login))
            .setHeader("User-Agent", "Java_HttpClient") // add request header
            .header("Content-Type", "application/json")
            .header("APP-BUILD", "IOS_9289")
            .build();

    // get response
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); `

post_login = /api/v5/account/login
Extract token + clientId + accountid + tier from response. Token is a new one every login, the others does not seem to change.
Email + password are your credentials. UUID can be created with an online uuid generator, needs to be the same always.
Login tier is https://rest-prod.immedia-semi.com
All the client info mimicing an iphone is maybe not needed.

First time a pin is sent to you, it needs to be verified

Verify code (java)

`
String json = "{"pin":""+pin+"", "app_version":"6.1.6 (9289) #8fee5f53c-mod", "reauth":"true", "os_version":"14.4", "device_identifier":"iPhone11,8", "unique_id": ""+unique_id+"","client_type":"ios", "client_name":"iPhone xxx"}";

    // add json header
    HttpRequest request = HttpRequest.newBuilder()
            .POST(HttpRequest.BodyPublishers.ofString(json))
            .uri(URI.create(europeTier+"/api/v4/account/"+accountId+"/client/"+clientId+"/pin/verify"))
            .setHeader("User-Agent", "Java_HttpClient") // add request header
            .header("Content-Type", "application/json")
            .header("APP-BUILD", "IOS_9289")
            .header("TOKEN_AUTH", this.authToken)
            .build();

HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());`

Clientid + accountId from login response, I am on tier prde, so europeTier = https://rest-prde.immedia-semi.com
authToken from login response. pin I receive over sms.

Now I can retrieve homescreen.

Homescreen code (java)

`
HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(URI.create(europeTier+"/api/v3/accounts/"+accountId+"/homescreen"))
.setHeader("User-Agent", "Java_HttpClient") // add request header
.header("Content-Type", "application/json")
.header("APP-BUILD", "IOS_9289")
.header("TOKEN_AUTH", this.authToken)
.build();

HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

`

europeTies as in verify, authToken from login

Login code (Java)

`
String json = "{"app_version":"6.1.6 (9289) #8fee5f53c-mod", "password":""+passwd+"", "reauth":"true", "os_version":"14.4", "device_identifier":"iPhone11,8", "unique_id": ""+unique_id+"","client_type":"ios", "email":""+email+"", "client_name":"iPhone xxx"}";

    // add json header
    HttpRequest request = HttpRequest.newBuilder()
            .POST(HttpRequest.BodyPublishers.ofString(json))
            .uri(URI.create(loginTier+post_login))
            .setHeader("User-Agent", "Java_HttpClient") // add request header
            .header("Content-Type", "application/json")
            .header("APP-BUILD", "IOS_9289")
            .build();

    // get response
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); `

post_login = /api/v5/account/login
Extract token + clientId + accountid + tier from response. Token is a new one every login, the others does not seem to change.
Email + password are your credentials. UUID can be created with an online uuid generator, needs to be the same always.
Login tier is https://rest-prod.immedia-semi.com
All the client info mimicing an iphone is maybe not needed.

First time a pin is sent to you, it needs to be verified

Verify code (java)

`
String json = "{"pin":""+pin+"", "app_version":"6.1.6 (9289) #8fee5f53c-mod", "reauth":"true", "os_version":"14.4", "device_identifier":"iPhone11,8", "unique_id": ""+unique_id+"","client_type":"ios", "client_name":"iPhone xxx"}";

    // add json header
    HttpRequest request = HttpRequest.newBuilder()
            .POST(HttpRequest.BodyPublishers.ofString(json))
            .uri(URI.create(europeTier+"/api/v4/account/"+accountId+"/client/"+clientId+"/pin/verify"))
            .setHeader("User-Agent", "Java_HttpClient") // add request header
            .header("Content-Type", "application/json")
            .header("APP-BUILD", "IOS_9289")
            .header("TOKEN_AUTH", this.authToken)
            .build();

HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());`

Clientid + accountId from login response, I am on tier prde, so europeTier = https://rest-prde.immedia-semi.com
authToken from login response. pin I receive over sms.

Now I can retrieve homescreen.

Homescreen code (java)

`
HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(URI.create(europeTier+"/api/v3/accounts/"+accountId+"/homescreen"))
.setHeader("User-Agent", "Java_HttpClient") // add request header
.header("Content-Type", "application/json")
.header("APP-BUILD", "IOS_9289")
.header("TOKEN_AUTH", this.authToken)
.build();

HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

`

europeTies as in verify, authToken from login

This worked. Thanks!!!!

Login code (Java)

`
String json = "{"app_version":"6.1.6 (9289) #8fee5f53c-mod", "password":""+passwd+"", "reauth":"true", "os_version":"14.4", "device_identifier":"iPhone11,8", "unique_id": ""+unique_id+"","client_type":"ios", "email":""+email+"", "client_name":"iPhone xxx"}";

    // add json header
    HttpRequest request = HttpRequest.newBuilder()
            .POST(HttpRequest.BodyPublishers.ofString(json))
            .uri(URI.create(loginTier+post_login))
            .setHeader("User-Agent", "Java_HttpClient") // add request header
            .header("Content-Type", "application/json")
            .header("APP-BUILD", "IOS_9289")
            .build();

    // get response
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); `

post_login = /api/v5/account/login
Extract token + clientId + accountid + tier from response. Token is a new one every login, the others does not seem to change.
Email + password are your credentials. UUID can be created with an online uuid generator, needs to be the same always.
Login tier is https://rest-prod.immedia-semi.com
All the client info mimicing an iphone is maybe not needed.

First time a pin is sent to you, it needs to be verified

Verify code (java)

`
String json = "{"pin":""+pin+"", "app_version":"6.1.6 (9289) #8fee5f53c-mod", "reauth":"true", "os_version":"14.4", "device_identifier":"iPhone11,8", "unique_id": ""+unique_id+"","client_type":"ios", "client_name":"iPhone xxx"}";

    // add json header
    HttpRequest request = HttpRequest.newBuilder()
            .POST(HttpRequest.BodyPublishers.ofString(json))
            .uri(URI.create(europeTier+"/api/v4/account/"+accountId+"/client/"+clientId+"/pin/verify"))
            .setHeader("User-Agent", "Java_HttpClient") // add request header
            .header("Content-Type", "application/json")
            .header("APP-BUILD", "IOS_9289")
            .header("TOKEN_AUTH", this.authToken)
            .build();

HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());`

Clientid + accountId from login response, I am on tier prde, so europeTier = https://rest-prde.immedia-semi.com
authToken from login response. pin I receive over sms.

Now I can retrieve homescreen.

Homescreen code (java)

`
HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(URI.create(europeTier+"/api/v3/accounts/"+accountId+"/homescreen"))
.setHeader("User-Agent", "Java_HttpClient") // add request header
.header("Content-Type", "application/json")
.header("APP-BUILD", "IOS_9289")
.header("TOKEN_AUTH", this.authToken)
.build();

HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

`

europeTies as in verify, authToken from login

larxxor,

One more question. I've got the homescreen working Thank you. The problem that I'm having now is that the pin needs to be verified more than once. I'm using this as the unique_id : "00000000-0000-0000-0000-100000000001". Should I need to re verify the pin?

I generate an UUID here (version 1) https://www.uuidgenerator.net/

This is reverse engineering, I don't know anything for sure. The idea is that UUID is unique for each client. And you carry that on from login to login.

I have tried changing the uuid and not been asked to verify pin. Which is very confusing. I am not sure at all how Blink is recognizing the client.
I feel that if you test too much, with several requests right after another, it will trigger a breaker and stop working. My approach is to think and code very deliberately. Then go away and test it later.

I generate an UUID here (version 1) https://www.uuidgenerator.net/

This is reverse engineering, I don't know anything for sure. The idea is that UUID is unique for each client. And you carry that on from login to login.

I have tried changing the uuid and not been asked to verify pin. Which is very confusing. I am not sure at all how Blink is recognizing the client.
I feel that if you test too much, with several requests right after another, it will trigger a breaker and stop working. My approach is to think and code very deliberately. Then go away and test it later.

I've haven't been able to get this working. I am changing the UUID and the pin keeps coming. Any news from your side?

Once you have an UUID you should stick to that and not change it. I think user-agent is important as well.
Pay attention to the tier part, where login goes to one host, a pin arrives, amd then you perform a verify on the tier you got from login response.

Maybe share your code (minus email and password of course)

I have it working now yes, my alarm system is coded to trigger arm/disarm on blink. Works nicely again.

I got some issue to verify PIN.

I used POSTMAN for the moment.

Login is fine, retrieved my AccountID, ClientID, Token, I generated a UUID (and fixed it).

In the example sent by @larxxor, it is mentioned TOKEN_AUTH (with an underscore) where the doc mentions TOKEN-AUTH (with a dash).

I tried both and upercase/lowercase as well. But I always have a http/401:

{
    "message": "Unauthorized Access",
    "code": 101
}

Any clue?

The call done is:

curl --location --request POST 'https://rest-prod.immedia-semi.com/api/v4/account/12345/client/123456/pin/verify' \
--header 'token_auth: -1Hahsgdtmdxw_2ssldARZ' \
--header 'Content-Type: application/json' \
--data-raw '{
    "pin": "541979"
}'

You've got wrong host on verify. It is not same host as login.
Replace "prod" with tier from login response.

Damn, it was that...

Sorry, I did not get this tier value, but this makes senses... Login is "global", but then, it is regiolanized.

Works now!

Thank you

Regarding TOKEN_AUTH vs TOKEN-AUTH vs token-auth. I have come to the conclusion that they are interchangeable.

I used TOKEN_AUTH because I found a code sample with that variety. Wonder if casing will be restricted in the future some day.

Ok. Let's hope it will be stable or at least not changed too often 🙂

Thanks

Regarding TOKEN_AUTH vs TOKEN-AUTH vs token-auth. I have come to the conclusion that they are interchangeable.

I used TOKEN_AUTH because I found a code sample with that variety. Wonder if casing will be restricted in the future some day.

I've got it working again with the new UUID code. Thanks larxxor

Hello,

I'm also having the 101 code error , what am I doing wrong ? My tier is "e004" so i tried to put this is the first url also but same issue

username = username_entry.get()
password = password_entry.get()
url = "https://rest-prod.immedia-semi.com/api/v5/account/login"

# Préparez les données à envoyer avec la requête
data = {
    "email": username,
    "password": password
}

# Envoyez la requête à l'API de Blink
response = requests.post(url, json=data)

# Vérifiez si la connexion a réussi
if response.status_code == 200:
    # Si la connexion a réussi, extraire le token d'authentification et le client_id
    auth_token = response.json().get("auth").get("token")
    client_id = response.json().get("account").get("client_id")
    account_id = response.json().get("account").get("account_id")
    region = response.json().get("account").get("region")
    tier= response.json().get("account").get("tier")
    print(response.json())
    print("region :", region)
    print("account_id ", account_id)
    print("Auth token: ", auth_token)
    print("Client id: ", client_id)
    
else:
    print("Failed to log in:", response.content)

try:
    url_homescreen=f"https://rest-{tier}.immedia-semi.com/api/v3/accounts/{account_id}/homescreen"
    headers = {"token-auth": auth_token}
    response_homescreen = requests.get(url_homescreen, headers=headers)
    print(response_homescreen.json())
except Exception as e:
    print(f"Erreur lors de l'authentification : {e}")

The code I received from response..json():
{'account': {'account_id': X
user_id': X
client_id': ****
client_trusted': False
new_account': True
tier': 'e004'
region': 'eu'
account_verification_required': False
phone_verification_required': False
client_verification_required': True
require_trust_client_device': True
country_required': False
verification_channel': 'phone'
user': {'user_id': X
country': 'FR'}
amazon_account_linked': True
braze_external_id': 'X'}
auth': {'token': ''}
phone': {'number': ''
last_4_digits': '
*'
country_calling_code': '**'
valid': True}
verification': {'email': {'required': False}
phone': {'required': True
channel': 'sms'}}
lockout_time_remaining': 0
force_password_reset': False
allow_pin_resend_seconds': 90}

There is a special sequence to acquire token on first login from device. This looks like you just do a user/passwd login. Wont work.

I have a working solution, but in java.

host to be used for login : https://rest-prod.immedia-semi.com
for all other requests use region tier url, for me that is https://rest-prde.immedia-semi.com

the data section in login should contain fields :
String json = "{"app_version":""+appVersion+"", "password":""+passwd+"", "reauth":"true", "os_version":""+osVersion+"", "device_identifier":""+deviceIdentifier+"", "unique_id": ""+unique_id+"","client_type":""+clientOs+"", "email":""+email+"", "client_name":""+clientName+""}";

Here are my values for the client settings, simulates a device :

private static String appBuild = "IOS_9289";
private static String appVersion = "6.1.6 (9289) #8fee5f53c-mod";
private static String osVersion = "14.4";
private static String deviceIdentifier = "iPhone11,8";
private static String clientName = "iPhone la";
private static String clientOs = "ios";

When login goes through, a pin code verification is sent.

Verify using /api/v4/account/<ACCOUNT_ID>/client/<CLIENT_ID>/pin/verify