# Provisioning with Amazon Cognito

Provision credentials using Amazon Cognito.

By enabling Krypton for Amazon Cognito, you can easily request temporary credentials from a Cognito Identity Pool. Krypton implements the **Enhanced Authflow** Identity Pool Authentication Flow detailed in the [Amazon Cognito Developer Guide](https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html) documentation.

![Enhanced Authflow](https://docs.aws.amazon.com/cognito/latest/developerguide/images/amazon-cognito-dev-auth-enhanced-flow.png)

Krypton uses SIM authentication to call Amazon Cognito's `GetOpenIdTokenForDeveloperIdentity` API to receive an OpenID token. Krypton then uses the token with the `GetCredentialsForIdentity` API in order to request temporary AWS credentials.

After temporary credentials have been issued, your device will be able to securely access AWS services such as Amazon S3, without having to install credentials on the device beforehand. Moreover, credentials issued by Cognito through Krypton are valid for any network connection, allowing you to utilize ethernet or Wifi as a primary backhaul, and utilize the Soracom Air cellular connection as a backup.

## Configuring Amazon Cognito

In order to enable Amazon Cognito integration, your AWS account must be configured to provide Krypton with programmatic access to Amazon Cognito. This process only needs to be performed once, and involves the following steps:

1. Create and configure an **Amazon Cognito Identity Pool**.
2. Create an **IAM User** with access for issuing OpenID tokens, and generate an **Access key ID** and **Secret access key** credential set.
3. Register the **credential set** on Soracom, and **configure Krypton**.

---

### Creating a Cognito Identity Pool

1. Sign in to the [AWS Management Console](https://console.aws.amazon.com/). From the Services menu, open the **Cognito** dashboard.

   ![Missing](https://docs.soracom.io/_astro/krypton-cognito11.DvBYHrjM_Z7YvBi.webp)

2. Click the **Manage Identity Pools** button.

   ![Missing](https://docs.soracom.io/_astro/krypton-cognito12.BPPBm8dF_RgaXh.webp)

3. Click the **Create new identity pool** button.

   ![Missing](https://docs.soracom.io/_astro/krypton-cognito13.B65E7Fom_kqdMB.webp)

4. Enter an **Identity pool name**. Then set a Custom Authentication provider, and set the **Developer provider name** as `krypton.soracom.io`.

   ![Missing](https://docs.soracom.io/_astro/krypton-cognito14.2KL0gkzC_Z1edTIp.webp)

5. Click the **Create Pool** button.

6. Cognito will give you the option of choosing which policies are applied to a device when it successfully authenticates using the identity pool. By default, Cognito will create new IAM roles to use with the identity pool, however you can specify a different role, or edit the role later if needed.

   Click the **Allow** button to finish creating the identity pool.

Once the identity pool has been created, Amazon Cognito will display its details. Make a note of the **Identity pool ID**, as it is required when configuring Krypton.

![Missing](https://docs.soracom.io/_astro/krypton-cognito15.cL7pC-Yu_F17IY.webp)

---

### Creating an IAM User

1. From the AWS Services menu, open the **IAM** dashboard.

   ![Missing](https://docs.soracom.io/_astro/krypton-cognito21.p9uR0LMl_Z2gcCfg.webp)

2. Click the **Users** section, then click the **Add user** button.

   ![Missing](https://docs.soracom.io/_astro/krypton-cognito22.CFdmYneG_Z158ELX.webp)

3. Enter a **User name**, and enable **Programmatic access**. Then click the **Next: Permissions** button.

   ![Missing](https://docs.soracom.io/_astro/krypton-cognito23.snGJL5Dg_ZqTXpN.webp)

Our IAM user reqiures permission in order to utilize Cognito. This permission is provided by an AWS policy, which we will attach to our user:

4. Under the Set permission section, click **Attach existing policies directly**.

5. Search for the `AmazonCognitoDeveloperAuthenticatedIdentities` policy and click its **☑** to attach it to the new user.

   ![Missing](https://docs.soracom.io/_astro/krypton-cognito24.BVKyU7Ww_ZvMvV.webp)

6. Continue the **Add user** wizard by clicking the **Next** buttons, keeping the default values for the remaining sections. Then click **Create user** to complete the wizard.

   ![Missing](https://docs.soracom.io/_astro/krypton-cognito25.Bda4GO3p_57Frs.webp)

Once the new user has been created, it will appear along with its **Access key ID** and **Secret access key**. Save these keys in a secure location.

![Missing](https://docs.soracom.io/_astro/krypton-cognito26.CN1wSOD5_LAEbF.webp)

---

### Configuring Krypton

Once your AWS account has been configured using the above steps, you will have the following information:

- Amazon Cognito **Identity pool ID**
- IAM user **Access key ID** and **Secret access key**

You can then use this information to configure Krypton using the [Krypton Configuration](https://docs.soracom.io/en/services/krypton/configuration) documentation, following the instructions for integrating Krypton with Amazon Cognito.

Once Krypton has been configured, your devices can begin using Krypton's provisioning service.

## Example Provisioning Process

The following NodeJS project demonstrates the typical bootstrap process utilizing Krypton to request temporary credentials from Amazon Cognito in order to access Amazon S3.

Requirements:

- NodeJS 8.10 or higher

### Project Installation

Download the [Krypton Example Project for NodeJS](https://soracom-files.s3.amazonaws.com/kryptonExamples.zip) to your device and extract it. This will create a `/kryptonExamples` directory containing an `cognito-auth.js` NodeJS project file.

Open the `/kryptonExamples` directory and install package dependencies:

```bash
npm install
```

---

### Authentication Method

The `cognito-auth.js` file expects a `krypton-cognito` script which will perform device authentication. Our example project includes the following authentication scripts:

- **krypton-cognito-cellular** - Authenticate using Soracom Air for Cellular
- **krypton-cognito-endorse-go** - Authenticate using Soracom Endorse and [Krypton Client for Go](https://github.com/soracom/krypton-client-go/releases)
- **krypton-cognito-endorse-java** - Authenticate using Soracom Endorse and [Krypton Client for Java](https://github.com/soracom/soracom-krypton-client-for-java/releases)

Let's make a symlink for one of these scripts:

**Cellular**

```bash
ln -sf krypton-cognito-cellular krypton-cognito
```

**Endorse (Go)**

```bash
ln -sf krypton-cognito-endorse-go krypton-cognito
```

**Endorse (Java)**

```bash
ln -sf krypton-cognito-endorse-java krypton-cognito
```

If using Air authentication, ensure that your modem is connected.

If using Endorse authentication, you will also need to download and extract the corresponding Krypton Client to the same `/kryptonExamples` directory. Refer to the [Krypton Overview](https://docs.soracom.io/en/services/krypton) documentation and Krypton Client repositories for installation requirements and instructions.

---

### Bootstrap

Now let's run the `cognito-auth.js` script:

```bash
node cognito-auth.js
```

As the script runs, it will perform the following:

- Perform device authentication using Soracom Air or Soracom Endorse.
- Provision using Krypton and receive temporary credentials from Amazon Cognito.

Once the device has received credentials from Amazon Cognito, the NodeJS script will output `Successfully obtained AWS credentials`. You can also verify that the subscriber IMSI appears in in the Cognito identity pool by using the Amazon Cognito Identity Browser.

![Missing](https://docs.soracom.io/_astro/krypton-cognito38.DLgMnvMk_Z1Gd7bc.webp)

---

### Accessing AWS Resources

The `cognito-auth.js` script can be quickly modified to begin accessing AWS resources using the temporary credentials provided through Soracom Krypton and Amazon Cognito.

For example, to access the list of objects in an S3 bucket in your AWS account, edit the `cognito-auth.js` script to enable the following section:

```js
initializeCredentials().then(() => {
  console.log("Successfully obtained AWS credentials");

  const s3 = new AWS.S3();

  s3.listObjects({Bucket: 'my-s3-bucket'}, (err, data) => {
    if (err) console.error(err);
    console.log(data);
  });
});
```

Make sure to replace `my-s3-bucket` with the name of your bucket. The IAM role attached to the device must also have the appropriate AWS policy for accessing S3 resources. Then simply re-run the script from your device to test that your device can successfully retrieve the list of objects.
