# Credentials Login

**Usage:** `"template": "login_credentials"`

<figure><img src="https://998911913-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPk9cn4V7WnnKt7fbry%2Fuploads%2Fgit-blob-4234f47e45f08b548a2d2474bd820fe93cdaeabb%2Frituals.png?alt=media" alt=""><figcaption></figcaption></figure>

{% code title="/drivers/\<driver\_id>/driver.compose.json" %}

```javascript
{
  "name": { "en": "My Driver" },
  "images": {
    "small": "/drivers/my_driver/assets/images/small.png",
    "large": "/drivers/my_driver/assets/images/large.png"
  },
  "pair": [
    {
      "id": "login_credentials",
      "template": "login_credentials",
      "options": {
        "logo": "logo.png",
        "title": {
          "en": "Your custom title"
        },
        "usernameLabel": { "en": "E-mail address" },
        "usernamePlaceholder": { "en": "john@doe.com" },
        "passwordLabel": { "en": "Password" },
        "passwordPlaceholder": { "en": "Password" }
      }
    },
    {
      "id": "list_devices",
      "template": "list_devices",
      "navigation": { "next": "add_devices" }
    },
    {
      "id": "add_devices",
      "template": "add_devices"
    }
  ]
}
```

{% endcode %}

## **Options**

| Key                   | Type                                                                                       | Default            | Description                   |
| --------------------- | ------------------------------------------------------------------------------------------ | ------------------ | ----------------------------- |
| `title`               | [translation object](https://apps.developer.homey.app/the-basics/app/internationalization) |                    |                               |
| `logo`                | `string`                                                                                   | `null`             | A path to an image for a logo |
| `usernameLabel`       | [translation object](https://apps.developer.homey.app/the-basics/app/internationalization) | `"E-mail address"` |                               |
| `usernamePlaceholder` | [translation object](https://apps.developer.homey.app/the-basics/app/internationalization) | `"john@doe.com"`   |                               |
| `passwordLabel`       | [translation object](https://apps.developer.homey.app/the-basics/app/internationalization) | `"Password"`       |                               |
| `passwordPlaceholder` | [translation object](https://apps.developer.homey.app/the-basics/app/internationalization) | `"Password"`       |                               |

{% tabs %}
{% tab title="JavaScript" %}
{% code title="/drivers/\<driver\_id>/driver.js" %}

```javascript
const Homey = require("homey");
const DeviceAPI = require("device-api");

class Driver extends Homey.Driver {
  async onPair(session) {
    let username = "";
    let password = "";

    session.setHandler("login", async (data) => {
      username = data.username;
      password = data.password;

      const credentialsAreValid = await DeviceAPI.testCredentials({
        username,
        password,
      });

      // return true to continue adding the device if the login succeeded
      // return false to indicate to the user the login attempt failed
      // thrown errors will also be shown to the user
      return credentialsAreValid;
    });

    session.setHandler("list_devices", async () => {
      const api = await DeviceAPI.login({ username, password });
      const myDevices = await api.getDevices();

      const devices = myDevices.map((myDevice) => {
        return {
          name: myDevice.name,
          data: {
            id: myDevice.id,
          },
          settings: {
            // Store username & password in settings
            // so the user can change them later
            username,
            password,
          },
        };
      });

      return devices;
    });
  }
}

module.exports = Driver;
```

{% endcode %}
{% endtab %}

{% tab title="TypeScript" %}
{% code title="/drivers/\<driver\_id>/driver.mts" %}

```mts
import Homey from "homey";
import DeviceApi from "./device-api.mjs";

type LoginData = {
  username: string;
  password: string;
};

export default class Driver extends Homey.Driver {
  async onPair(session: Homey.Driver.PairSession): Promise<void> {
    let username = "";
    let password = "";

    session.setHandler("login", async (data: LoginData): Promise<boolean> => {
      username = data.username;
      password = data.password;

      const credentialsAreValid = await DeviceApi.testCredentials(username, password);

      // return true to continue adding the device if the login succeeded
      // return false to indicate to the user the login attempt failed
      // thrown errors will also be shown to the user
      return credentialsAreValid;
    });

    session.setHandler("list_devices", async (): Promise<object[]> => {
      const api = await DeviceApi.login(username, password);
      const myDevices = await api.getDevices();

      const devices = myDevices.map(myDevice => {
        return {
          name: myDevice.name,
          data: {
            id: myDevice.id,
          },
          settings: {
            // Store username & password in settings
            // so the user can change them later
            username: username,
            password: password,
          },
        };
      });

      return devices;
    });
  }
}

```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
{% code title="/drivers/\<driver\_id>/driver.py" %}

```python
from typing import TypedDict

from device_api import DeviceApi
from homey import driver
from homey.driver import ListDeviceProperties
from homey.pair_session import PairSession


class LoginData(TypedDict):
    username: str
    password: str


class Driver(driver.Driver):
    async def on_pair(self, session: PairSession) -> None:
        username, password = "", ""

        async def on_login(data: LoginData) -> bool:
            nonlocal username, password
            username = data["username"]
            password = data["password"]

            credentials_are_valid = await DeviceApi.test_credentials(**data)

            # return true to continue adding the device if the login succeeded
            # return false to indicate to the user the login attempt failed
            # thrown errors will also be shown to the user
            return credentials_are_valid

        async def on_list_devices() -> list[ListDeviceProperties]:
            api = await DeviceApi.login(username, password)
            my_devices = await api.get_devices()

            devices: list[ListDeviceProperties] = [
                {
                    "name": device.name,
                    "data": {"id": device.id},
                    "settings": {
                        # Store username & password in settings
                        # so the user can change them later
                        "username": username,
                        "password": password,
                    },
                }
                for device in my_devices
            ]

            return devices


homey_export = Driver

```

{% endcode %}
{% endtab %}
{% endtabs %}
