Hi @46deva,
I don’t have full knowledge on the subject to help you, but the tutorial helped me a lot: Authenticating smart home Actions for the Google Assistant with Auth0 by Nick Felker and the original code: https://github.com/actions-on-google/smart-home-nodejs.
Below is my code that works:
index.ts
// Express imports
import * as express from 'express'
import * as bodyParser from 'body-parser'
import * as cors from 'cors'
import * as morgan from 'morgan'
import * as ngrok from 'ngrok'
import { AddressInfo } from 'net'
// Smart home imports
import {
smarthome,
SmartHomeV1ExecuteResponseCommands,
Headers,
} from 'actions-on-google'
// Local imports
import * as Firestore from './firestore'
import * as Auth from './auth-provider'
import * as Config from './config-provider'
const expressApp = express()
expressApp.use(cors())
expressApp.use(morgan('dev'))
expressApp.use(bodyParser.json())
expressApp.use(bodyParser.urlencoded({extended: true}))
expressApp.set('trust proxy', 1)
Auth.registerAuthEndpoints(expressApp)
let jwt
try {
jwt = require('./smart-home-key.json')
} catch (e) {
console.warn('Service account key is not found')
console.warn('Report state and Request sync will be unavailable')
}
const app = smarthome({
jwt,
debug: true,
})
// Array could be of any type
// tslint:disable-next-line
async function asyncForEach(array: any[], callback: Function) {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array)
}
}
async function getUserIdOrThrow(headers: Headers): Promise {
var userId = await Auth.getUser(headers)
if (!userId) {
console.log('>>>> getUserIdOrThrow deu Ruim ')
userId = await Auth.getUser(headers)
}
console.log('>>>> getUserIdOrThrow : ', userId)
const userExists = await Firestore.userExists(userId)
if (!userExists) {
throw new Error(`User ${userId} has not created an account, so there are no devices`)
}
return userId
}
app.onSync(async (body, headers) => {
const userId = await getUserIdOrThrow(headers)
await Firestore.setHomegraphEnable(userId, true)
const devices = await Firestore.getDevices(userId)
return {
requestId: body.requestId,
payload: {
agentUserId: userId,
devices,
},
}
})
interface DeviceStatesMap {
// tslint:disable-next-line
[key: string]: any
}
app.onQuery(async (body, headers) => {
const userId = await getUserIdOrThrow(headers)
const deviceStates: DeviceStatesMap = {}
const {devices} = body.inputs[0].payload
await asyncForEach(devices, async (device: {id: string}) => {
const states = await Firestore.getState(userId, device.id)
deviceStates[device.id] = states
})
return {
requestId: body.requestId,
payload: {
devices: deviceStates,
},
}
})
app.onExecute(async (body, headers) => {
const userId = await getUserIdOrThrow(headers)
const commands: SmartHomeV1ExecuteResponseCommands[] = [{
ids: [],
status: 'SUCCESS',
states: {},
}]
//console.log('>>>> userId <<< {
try {
const states = await Firestore.execute(userId, device.id, execution[0])
commands[0].ids.push(device.id)
commands[0].states = states
await app.reportState({
agentUserId: userId,
//requestId: Math.random().toString(),
requestId: body.requestId,
payload: {
devices: {
states: {
[device.id]: states,
},
},
},
})
return {
requestId: body.requestId,
payload: {
commands,
},
}
})
app.onDisconnect(async (body, headers) => {
const userId = await getUserIdOrThrow(headers)
await Firestore.disconnect(userId)
})
expressApp.post('/smarthome', app)
expressApp.post('/smarthome/update', async (req, res) => {
console.log(req.body)
const {userId, deviceId, name, nickname, states} = req.body
try {
await Firestore.updateDevice(userId, deviceId, name, nickname, states)
const reportStateResponse = await app.reportState({
agentUserId: userId,
requestId: Math.random().toString(),
payload: {
devices: {
states: {
[deviceId]: states,
},
},
},
})
res.status(200).send('OK')
} catch(e) {
console.error(e)
res.status(400).send(`Error reporting state: ${e}`)
}
})
expressApp.post('/smarthome/create', async (req, res) => {
console.log(req.body)
const {userId, data} = req.body
try {
await Firestore.addDevice(userId, data)
await app.requestSync(userId)
} catch(e) {
console.error(e)
} finally {
res.status(200).send('OK')
}
})
expressApp.post('/smarthome/delete', async (req, res) => {
console.log(req.body)
const {userId, deviceId} = req.body
try {
await Firestore.deleteDevice(userId, deviceId)
await app.requestSync(userId)
} catch(e) {
console.error(e)
} finally {
res.status(200).send('OK')
}
})
const appPort = process.env.PORT || Config.expressPort
const expressServer = expressApp.listen(appPort, () => {
const server = expressServer.address() as AddressInfo
const {address, port} = server
console.log(`Smart home server listening at ${address}:${port}`)
if (Config.useNgrok) {
ngrok.connect(Config.expressPort, (err, url) => {
if (err) {
console.error('Ngrok was unable to start')
console.error(err)
process.exit()
}
console.log('')
console.log('COPY & PASTE NGROK URL BELOW')
console.log(url)
console.log('')
console.log('=====')
console.log('Visit the Actions on Google console at http://console.actions.google.com')
console.log('Replace the webhook URL in the Actions section with:')
console.log(' ' + url + '/smarthome')
console.log('')
console.log('In the console, set the Authorization URL to:')
console.log(' ' + url + '/fakeauth')
console.log('')
console.log('Then set the Token URL to:')
console.log(' ' + url + '/faketoken')
console.log('')
console.log('Finally press the \'TEST DRAFT\' button')
})
}
})
auth-provider.ts
import * as express from 'express'
import * as util from 'util'
import { Headers } from 'actions-on-google'
import * as Firestore from './firestore'
import { AuthenticationClient } from 'auth0'
const auth0 = new AuthenticationClient({
domain: my-domain,
clientId: my-clientID,
clientSecret: my-clienteSecret
});
export async function getUser(headers: Headers): Promise {
const authorization = headers.authorization
const accessToken = (authorization as string).substr(7)
const {email} = await auth0.getProfile(accessToken)
const userExists = await Firestore.userExists(email)
if (!userExists) {
await Firestore.addUser(email, email)
}
return await Firestore.getUserIdByEmail(email)
}