> ## Documentation Index
> Fetch the complete documentation index at: https://tbd-6fc993ce-hypeship-docker-sandboxes-integration.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Credentials

> Automate authentication with stored credentials

Credentials allow you to store login information securely and enable Kernel's automated re-authentication without requiring user interaction.

**There are three ways to provide credentials:**

* **Automatically save during login** — Capture credentials directly from the user when they log in via [Hosted UI](/auth/hosted-ui) or [Programmatic](/auth/programmatic)
* **Pre-store in Kernel** — Create credentials before any login for fully headless automation
* **Connect 1Password** — Use credentials from your existing 1Password vaults

<Card title="1Password Integration" icon="key" href="/integrations/1password">
  Connect your 1Password vaults to automatically use existing credentials with Managed Auth. Credentials are automatically matched by domain.
</Card>

## Save credentials during login

By default, credentials entered during login are automatically saved for re-authentication. No extra parameters are needed:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const login = await kernel.auth.connections.login(auth.id);
  ```

  ```python Python theme={null}
  login = await kernel.auth.connections.login(auth.id)
  ```
</CodeGroup>

Once saved, browser profiles stay authenticated automatically. When the session expires, Kernel re-authenticates using the stored credentials. Credentials are updated after every successful login. One-time codes (TOTP, SMS, etc.) are not saved.

To opt out of credential saving, set `save_credentials: false` when creating the connection:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const auth = await kernel.auth.connections.create({
    domain: 'example.com',
    profile_name: 'my-profile',
    save_credentials: false,
  });
  ```

  ```python Python theme={null}
  auth = await kernel.auth.connections.create(
      domain="example.com",
      profile_name="my-profile",
      save_credentials=False,
  )
  ```
</CodeGroup>

## Pre-store credentials

For fully automated flows where no user is involved, create credentials upfront:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const credential = await kernel.credentials.create({
    name: 'my-netflix-login',
    domain: 'netflix.com',
    values: {
      email: 'user@netflix.com',
      password: 'secretpassword123',
    },
  });
  ```

  ```python Python theme={null}
  credential = await kernel.credentials.create(
      name="my-netflix-login",
      domain="netflix.com",
      values={
          "email": "user@netflix.com",
          "password": "secretpassword123",
      },
  )
  ```
</CodeGroup>

Then link the credential when creating a connection:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const auth = await kernel.auth.connections.create({
    domain: 'netflix.com',
    profile_name: 'my-profile',
    credential: { name: credential.name },
  });

  // Start login - authenticates automatically using stored credentials
  const login = await kernel.auth.connections.login(auth.id);
  ```

  ```python Python theme={null}
  auth = await kernel.auth.connections.create(
      domain="netflix.com",
      profile_name="my-profile",
      credential={"name": credential.name},
  )

  # Start login - authenticates automatically using stored credentials
  login = await kernel.auth.connections.login(auth.id)
  ```
</CodeGroup>

### 2FA with TOTP

For sites with authenticator app 2FA, include `totp_secret` to fully automate login:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const credential = await kernel.credentials.create({
    name: 'my-login',
    domain: 'github.com',
    values: {
      username: 'my-username',
      password: 'my-password',
    },
    totp_secret: 'JBSWY3DPEHPK3PXP',  // From authenticator app setup
  });
  ```

  ```python Python theme={null}
  credential = await kernel.credentials.create(
      name="my-login",
      domain="github.com",
      values={
          "username": "my-username",
          "password": "my-password",
      },
      totp_secret="JBSWY3DPEHPK3PXP",  # From authenticator app setup
  )
  ```
</CodeGroup>

### SSO / OAuth

For sites with "Sign in with Google/GitHub/Microsoft", set `sso_provider` and Kernel automatically clicks the matching SSO button and completes OAuth.

Common SSO provider domains (Google, Microsoft, Okta, Auth0, GitHub, etc.) are automatically allowed — you don't need to add them to `allowed_domains`:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const credential = await kernel.credentials.create({
    name: 'my-google-login',
    domain: 'accounts.google.com',
    sso_provider: 'google',
    values: {
      email: 'user@gmail.com',
      password: 'password',
    },
  });

  const auth = await kernel.auth.connections.create({
    domain: 'target-site.com',
    profile_name: 'my-profile',
    credential: { name: credential.name },
  });
  ```

  ```python Python theme={null}
  credential = await kernel.credentials.create(
      name="my-google-login",
      domain="accounts.google.com",
      sso_provider="google",
      values={
          "email": "user@gmail.com",
          "password": "password",
      },
  )

  auth = await kernel.auth.connections.create(
      domain="target-site.com",
      profile_name="my-profile",
      credential={"name": credential.name},
  )
  ```
</CodeGroup>

## Partial Credentials

Credentials don't need to contain every field required by the login form. You can store what you have and collect the necessary fields from the user. `auth.connections.login()` pauses for missing values.

As an example, the below credential has email + TOTP secret stored (and automatically handled), but no password. The password is dynamically collected from the user using Kernel's Hosted UI or your Programmatic flow:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const credential = await kernel.credentials.create({
    name: 'my-login',
    domain: 'example.com',
    values: { email: 'user@example.com' },  // No password
    totp_secret: 'JBSWY3DPEHPK3PXP',
  });

  const auth = await kernel.auth.connections.create({
    domain: 'example.com',
    profile_name: 'my-profile',
    credential: { name: credential.name },
  });

  const login = await kernel.auth.connections.login(auth.id);

  // Poll until password is needed
  let state = await kernel.auth.connections.retrieve(auth.id);
  while (state.flow_status === 'IN_PROGRESS') {
    if (state.flow_step === 'AWAITING_INPUT' && state.discovered_fields?.length) {
      // Only password field will be pending (email auto-filled from credential)
      await kernel.auth.connections.submit(auth.id, {
        fields: { password: 'user-provided-password' }
      });
    }
    await new Promise(r => setTimeout(r, 2000));
    state = await kernel.auth.connections.retrieve(auth.id);
  }
  // TOTP auto-submitted from credential → SUCCESS
  ```

  ```python Python theme={null}
  credential = await kernel.credentials.create(
      name="my-login",
      domain="example.com",
      values={"email": "user@example.com"},  # No password
      totp_secret="JBSWY3DPEHPK3PXP",
  )

  auth = await kernel.auth.connections.create(
      domain="example.com",
      profile_name="my-profile",
      credential={"name": credential.name},
  )

  login = await kernel.auth.connections.login(auth.id)

  # Poll until password is needed
  state = await kernel.auth.connections.retrieve(auth.id)
  while state.flow_status == "IN_PROGRESS":
      if state.flow_step == "AWAITING_INPUT" and state.discovered_fields:
          # Only password field will be pending (email auto-filled from credential)
          await kernel.auth.connections.submit(
              auth.id,
              fields={"password": "user-provided-password"},
          )
      await asyncio.sleep(2)
      state = await kernel.auth.connections.retrieve(auth.id)
  # TOTP auto-submitted from credential → SUCCESS
  ```
</CodeGroup>

This is useful when you want to:

* Store TOTP secrets but have users enter their password each time
* Pre-fill username/email but collect password at runtime
* Merge user-provided values into an existing credential automatically on successful login

## Security

| Feature                | Description                                          |
| ---------------------- | ---------------------------------------------------- |
| **Encrypted at rest**  | Values encrypted using per-organization keys         |
| **Write-only**         | Values cannot be retrieved via API after creation    |
| **Never logged**       | Values are never written to logs                     |
| **Never shared**       | Values are never passed to LLMs                      |
| **Isolated execution** | Authentication runs in isolated browser environments |

## Notes

* The `values` object is flexible and can be used to store whatever fields the login form needs (`email`, `username`, `company_id`, etc.)
* Deleting a credential unlinks it from associated connections so they can no longer auto-authenticate
* Use one credential per account. We recommend creating separate credentials for different user accounts
