0

I'm reporting states for devices using http post with a jwt generated using service account. Below is the payload for jwt

{
   "iss": "<service-account-email>",
   "scope": "https://www.googleapis.com/auth/homegraph",
   "aud": "https://accounts.google.com/o/oauth2/token",
   "iat": <current-time>,
   "exp": <current-time-plus-one-hour>
 }

after this I sign the jwt using the private key for my service account using the python library google.auth.crypt.RSASigner.from_service_account_file(path) and generate the jwt token. I am further using this token to obtain the access token from https://accounts.google.com/o/oauth/token, which is also successful. After obtaining the access token I am making a post request to https://homegraph.googleapis.com/v1/devices:reportStateAndNotification?key=api_key

with headers

{"Authorization": "Bearer <token>", "X-GFE-SSL": "yes", "Content-Type": "application/json"}

and json data

{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "agent_user_id": "1234", "payload": { "devices": { "states": { "1458765": { "on": true }, "4578964": { "on": true, "isLocked": true } } } } }

But this gives me

{'error': {'code': 403, 'message': 'The request is missing a valid API key.', 'status': 'PERMISSION_DENIED'}}

I followed the steps from https://developers.google.com/actions/smarthome/report-state is there anything i'm doing wrong? or am I missing any steps?

UPDATE: I added the api key to the uri now it gives me another error in response

{'error': {'code': 403, 'message': 'The caller does not have permission', 'status': 'PERMISSION_DENIED'}}

how do I resolve this issue?

sky9971
  • 3
  • 7
  • Are you sure you create a valid service account as explained [here](https://developers.google.com/actions/smarthome/report-state#enable_the_api_and_download_credentials)? You do not need an API key for report state call – pincopallino Jul 24 '18 at 11:07
  • if I don't add the API key I'm still getting error code 403 **The request is missing a valid API key**. And yes I followed the same steps to create a service account. However, can you please lay down few points on how to do this without any errors.. – sky9971 Jul 25 '18 at 04:58

1 Answers1

0

In order to report the state to the Home Graph you have to:

  • Create a Service Account for the token creation from your SmartHomeApp project:
  • Go to APIs & Services => Click on Credentials Go to 'APIs & Services' => Click on 'Credentials'
  • Click on Create credentials => Click on Service account key Click on 'Create credentials' => Click on 'Service account key'
  • Fill with your data creating a new New service account => Select the role Service Accounts > Service Account Token Creator Fill with your data creating a new 'New service account' => Select the role 'Service Accounts > Service Account Token Creator'
  • Download the JSON file with your keys and certificate
  • Get a valid signed JWT token:

    credentials = service_account.Credentials.from_service_account_file(service_account_file, scopes="https://www.googleapis.com/auth/homegraph")
    
    now = int(time.time())
    expires = now + 3600  # One hour in seconds
    
    payload = {
        'iat': now,
        'exp': expires,
        'aud': "https://accounts.google.com/o/oauth2/token",
        'scope': SCOPE,
        'iss': credentials.service_account_email
    }
    
    signed_jwt = google.auth.jwt.encode(credentials.signer, payload)
    
  • Obtain a valid Access token:

    headers = {"Authorization": "Bearer {}".format(signed_jwt.decode("utf-8")), "Content-Type": "application/x-www-form-urlencoded"}
    data = {"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", "assertion": signed_jwt}
    
    access_token = requests.post("https://accounts.google.com/o/oauth2/token", data=data, headers=headers).get("access_token")
    
  • Send the reported states:

    headers = {"Authorization": "Bearer {}".format(access_token), "X-GFE-SSL": "yes"}
    data = {"requestId": request_id, "agent_user_id": agent_user_id, "payload": {"devices": {"states": states}}}
    
    requests.post("https://homegraph.googleapis.com/v1/devices:reportStateAndNotification", data=json.dumps(data), headers=headers)
    

NOTE: in order to work these snippets require to import google.auth.jwt, from google.oauth2 import service_accountand import requests from google-auth, google-auth-httplib2 and requests packages.

pincopallino
  • 130
  • 2
  • 6
  • Hey, I tried this for report state But I am getting an error: 404 { "error": { "code": 404, "message": "Requested entity was not found.", "status": "NOT_FOUND" } } I read at many places this error is related to the agent user id but I tried that agent user id for request Sync and it's working properly. I couldn't find a solution for this error in my Scenario. – Sharvin26 Dec 11 '18 at 12:45
  • @SharvinShah maybe it is not the agent missing but the device. Check for the device id provided into the SYNC event – pincopallino Dec 11 '18 at 16:22
  • Actually I checked that many times still the error is persisting. I have 10 appliance and I am sending the state for one appliance. DeviceId is also perfect everything is perfect still not working. – Sharvin26 Dec 11 '18 at 19:21
  • Be sure that in the SYNC event there is agent and device ID. Try also to use the report state tool for debugging. If there are no appliance in the tool would mean that the sync failed to update the Google Home Graph and so you cannot report any devices. Give a try to https://github.com/actions-on-google/smart-home-dashboard – pincopallino Dec 12 '18 at 22:21
  • Actually, I tried that Smart Home dashboard and it's working fine for my agent user id giving me all the devices I have. Even that agent user id is working for the request sync. It's only not working for the report state code above and also for the example given in the documentation. Giving me 404 error. – Sharvin26 Dec 13 '18 at 07:04
  • Remember to activate the HomeGraph API (https://console.developers.google.com/apis/api/homegraph.googleapis.com/overview) otherwise you will continue to receive `403`. I experienced it myself just now :D – pincopallino Oct 12 '21 at 15:23