Home Coding Embedding Home Assistant Dashboard into a Flutter App

Embedding Home Assistant Dashboard into a Flutter App

by khomkrit
1.5K views

If we want to open the Home Assistant web interface from within our application without having to log in again to Home Assistant, we can use External Authentication provided by Home Assistant.

crop dealer touching screen on smartphone with trading application
Photo by Liza Summer on Pexels.com

The idea is to use jschannel to communicate between the Flutter WebView and the Home Assistant web interface. When we open Home Assistant from the WebView, it will invoke the jschannel named getExternalAuth, which we need to define in the code when initializing the WebView. Then, the getExternalAuth function should return the access token back to the Home Assistant web interface for further usage. If the token is correct, we can access the Home Assistant web interface without logging in.

Based on the aforementioned concept, the workflow would be as follows:

  1. Create a Long-Lived Access Token from the user settings page in Home Assistant.
  2. Create a jschannel named getExternalAuth to be invoked by Home Assistant.
  3. Write code to call the externalAuthSetToken jschannel (defined in the Home Assistant web interface) to return the access token created in step 1.

Create Long-Lived Access Tokens

Go to the user settings page, where various settings such as theme color can be found. At the bottom, there is a section for creating Long-Lived Access Tokens. Create a token and copy it before closing the page because it won’t be visible again once closed.

Create jschannel in the Flutter side

controller.addJavaScriptChannel('getExternalAuth',
    onMessageReceived: (JavaScriptMessage message) { }
);

Call jschannel back to the Home Assistant side

const token = 'long-lived-access-token';
controller.runJavaScript(
    "window.externalAuthSetToken(true, { access_token: '$token', expires_in: 1800 });",
);

Flutter WebView uses WebViewWidget and WebViewController to configure various settings for the WebViewWidget. Therefore, the resulting code would be something like this:

final WebViewController controller = WebViewController();
controller.setJavaScriptMode(JavaScriptMode.unrestricted);
controller.addJavaScriptChannel('getExternalAuth',
    onMessageReceived: (JavaScriptMessage message) {
    const token = 'long-lived-access-token';
    controller.runJavaScript(
        "window.externalAuthSetToken(true, { access_token: '$token', expires_in: 1800 });",
    );
});
controller.loadRequest(Uri.parse(homeAssistantUrl));

From a technical standpoint, we can add additional logic to decide which user’s long-lived token to send, without necessarily hard-coding the token.

You may also like