# Configuring step-ca Provisioners

Provisioners are methods of using the CA to get certificates for humans or machines.
They offer different modes of authorization for the CA.
In this section we'll discuss the different provisioners, their target use cases, and how to add, remove, and configure them.

## Overview

- [Choosing a Provisioner](/content/docs/step-ca/provisioners/#choosing-a-provisioner/index.html)
- [Authorization Scope by Provisioner](/content/docs/step-ca/provisioners/#authorization-scope-by-provisioner/index.html)
- [Provisioner Management](/content/docs/step-ca/provisioners/#provisioner-management/index.html)
- [Remote Provisioner Management](/content/docs/step-ca/provisioners/#remote-provisioner-management/index.html)
- [Provisioner Types](/content/docs/step-ca/provisioners/#provisioner-types/index.html)
  - [JWK](/content/docs/step-ca/provisioners/#jwk/index.html)
  - [OAuth/OIDC Single Sign-on](/content/docs/step-ca/provisioners/#oauthoidc-single-sign-on/index.html)
  - [X5C - X.509 Certificate](/content/docs/step-ca/provisioners/#x5c---x509-certificate/index.html)
  - [SSHPOP - SSH Certificate](/content/docs/step-ca/provisioners/#sshpop---ssh-certificate/index.html)
  - [ACME](/content/docs/step-ca/provisioners/#acme/index.html)
  - [Nebula](/content/docs/step-ca/provisioners/#nebula/index.html)
  - [SCEP](/content/docs/step-ca/provisioners/#scep/index.html)
  - [K8sSA - Kubernetes Service Account](/content/docs/step-ca/provisioners/#k8ssa---kubernetes-service-account/index.html)
  - [Cloud Provisioners](/content/docs/step-ca/provisioners/#cloud-provisioners/index.html)

## Choosing a provisioner

When choosing a provisioner for your use case,
you can narrow your options by starting from
the **types of identifiers** you need on a certificate.

| Identifier Type | JWK | OAuth | X5C | ACME `dns-01` | ACME `http-01` | ACME `tls-alpn-01` | ACME `device-attest-01` | Nebula | SCEP | K8sSA | Cloud Provisioners |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Hostname | ✔️ | 𝗫 | ✔️ | ✔️ | ✔️ | ✔️ | 𝗫 | ✔️ | ✔️ | 𝗫 | ✔️ |
| IP address | ✔️ | 𝗫 | ✔️ | 𝗫 | ✔️ | ✔️ | 𝗫 | ✔️ | ✔️ | 𝗫 | ✔️ |
| Hardware ID | ✔️ | 𝗫 | ✔️ | 𝗫 | 𝗫 | 𝗫 | ✔️ | 𝗫 | ✔️ | 𝗫 | 𝗫 |
| Service Account | ✔️ | ✔️ | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 | ✔️ | ✔️ | 𝗫 |
| Human | ✔️ | ✔️ | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 |

Besides the identifier types described above, `step-ca` also integrates with and supports [Wire](https://wire.com/) messenger application identities.
The configuration for this is described in [ACME for Wire messenger clients](/content/docs/step-ca/provisioners/#acme-for-wire-messenger-clients/index.html).

You can also narrow your provisioner options based on **trust dependencies**.
Trust dependencies are third parties you can leverage to bootstrap trust within your PKI.

| Provisioner | What Is Trusted? |
| --- | --- |
| JWK | Private key bearers |
| OAuth | An OIDC authorization server (Okta, Google, Azure, etc.) |
| X5C | Another X.509 CA |
| ACME `dns-01` | Your DNS server and network |
| ACME `http-01` | Your network, DNS, and OS privileged port protections |
| ACME `tls-alpn-01` | Your network, DNS, and OS privileged port protections |
| ACME `device-attest-01` | Security hardware manufacturer (Apple, Infineon, Yubico, etc.) |
| Cloud Provisioners | Your cloud provider (AWS, GCP, Azure) |
| SCEP | Shared secret bearers |

## Authorization scope by provisioner

Every provisioner has a slightly different scope of authorization. Below is a
table detailing the authorization capabilities of each provisioner.

| Provisioner Capabilities | x509-sign | x509-renew | x509-revoke | ssh-user-cert-sign | ssh-host-cert-sign | ssh-user-cert-renew [1](/content/docs/step-ca/provisioners/#f1/index.html) | ssh-host-cert-renew | ssh-revoke | ssh-rekey |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| JWK | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | 𝗫 | 𝗫 | ✔️ | 𝗫 |
| OIDC | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ [2](/content/docs/step-ca/provisioners/#f2/index.html) | 𝗫 | 𝗫 | ✔️ | 𝗫 |
| X5C | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫 |
| Nebula | ✔️ | ✔️ | ✔️ | ✔️ | 𝗫 | 𝗫 | 𝗫 | ✔️ | 𝗫 |
| K8sSA | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫 |
| ACME | ✔️ | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 |
| SCEP | ✔️ | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 |
| SSHPOP | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 | ✔️ | ✔️ | ✔️ |
| AWS | ✔️ | ✔️ | 𝗫 | 𝗫 | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫 |
| Azure | ✔️ | ✔️ | 𝗫 | 𝗫 | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫 |
| GCP | ✔️ | ✔️ | 𝗫 | 𝗫 | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫 |

1

By design, SSH user certificates cannot be renewed by any provisioner. You can re-use the same key to get a new certificate, however. See [smallstep/discussions#1296](https://github.com/smallstep/certificates/discussions/1296).

2

Privileged OIDC subject names can generate Host SSH Certificates. These can be configured in the [OIDC provisioner](/content/docs/step-ca/provisioners/#oauthoidc-single-sign-on/index.html).

For an example of how to interpret this table, let's take the `JWK` provisioner.
The `JWK` provisioner is capable of signing, renewing, and revoking X.509
certificates, as well signing user and host SSH certificates. A `JWK` provisioner
_cannot_ renew or rekey SSH certificates.

An `SSHPOP` provisioner _can_ revoke and rekey SSH certificates and renew SSH host
certificates. An `SSHPOP` provisioner _cannot_ sign, renew, or revoke X.509
certificates, and it _cannot_ sign SSH user and host certificates or renew SSH
user certificates.

It's important to understand the capabilities and limitations when selecting a
provisioner for a given workload.

## Provisioner management

Use the [`step ca provisioner`](/content/docs/step-cli/reference/ca/provisioner/index.html) command group to add, remove, or modify provisioner configurations. Run these commands directly on your CA machine. They need to modify the `$(step path)/config/ca.json` configuration file.

**May I edit `ca.json` directly?**

You may edit your `ca.json` configuration file directly, but we strongly recommend using [`step ca provisioner`](/content/docs/step-cli/reference/ca/provisioner/index.html) commands instead.
Fields in `ca.json` may be encoded differently than you expect.

Some provisioner options override global defaults for your CA.
For a list of global options, see the [configuration guide](/content/docs/step-ca/configuration/index.html) section for the `authority` configuration block.

A remote provisioner management API can be enabled in `step-ca`.
It is disabled by default.
With remote provisioner management, the CA's provisioner configuration is stored in the database instead of `ca.json`. (The global CA configuration remains in `ca.json`.)

This feature can be useful if you
have multiple CA administrators,
[run several load-balanced](/content/docs/step-ca/certificate-authority-server-production/#load-balancing-or-proxying-step-ca-traffic/index.html)`step-ca` instances,
or if you want to manage your provisioners remotely (eg. with Infrastructure as Code (IaC) tools; [see below](/content/docs/step-ca/provisioners/#unattended-remote-provisioner-management/index.html)).

See [Remote Provisioner Management](/content/docs/step-ca/provisioners/#remote-provisioner-management/index.html) for more.

### Common provisioner operations

Common provisioner operations include:

- [Adding a provisioner](/content/docs/step-ca/provisioners/#add-a-provisioner/index.html)
- [Removing a provisioner](/content/docs/step-ca/provisioners/#remove-a-provisioner/index.html)
- [Listing all provisioner](/content/docs/step-ca/provisioners/#list-all-provisioners/index.html)
- [Modifying the configuration of an existing provisioner](/content/docs/step-ca/provisioners/#modify-a-provisioner/index.html)

Unless you are using [remote provisioner management](/content/docs/step-ca/provisioners/#remote-provisioner-management/index.html), you must send a `SIGHUP` signal, or restart the `step-ca` process, for changes to your provisioner configuration to take effect.

#### Add a provisioner

Use [`step ca provisioner add`](/content/docs/step-cli/reference/ca/provisioner/add/index.html) to add a provisioner:

`step ca provisioner add acme --type ACME

`

See the [command reference](/content/docs/step-cli/reference/ca/provisioner/add/index.html) for complete documentation and examples.

#### Remove a provisioner

Use [`step ca provisioner remove`](/content/docs/step-cli/reference/ca/provisioner/remove/index.html) to remove provisioners:

`step ca provisioner remove acme

`

You can also edit the `ca.json` configuration file and remove the entire block
containing the provisioner you'd like to remove.

#### List all provisioners

To get a list of all of your current provisioners, use [`step ca provisioner list`](/content/docs/step-cli/reference/ca/provisioner/list/index.html) or the `/provisioners` endpoint on your CA.

#### Modify a provisioner

Use [`step ca provisioner update`](/content/docs/step-cli/reference/ca/provisioner/update/index.html) to update provisioner configurations:

`step ca provisioner update acme \
   --x509-min-dur=20m \
   --x509-max-dur=72h \
   --x509-default-dur=36h

`

In this example we've modified the minumum, maximum, and default durations for TLS certificates generated by this provisioner.

Provisioner configuration can be used to affect X.509 and SSH certificate lifetimes, extensions, and templates.
Some provisioner-specific options exist,
which are covered by the documentation for each provisioner type, below.

## Remote provisioner management

**This feature is disabled by default.**

When remote provisioner management is enabled, your provisioner configuration is
stored in the database, rather than in `ca.json`.
Provisioner configuration is managed by running [`step ca provisioner`](/content/docs/step-cli/reference/ca/provisioner/index.html) commands locally or remotely.
These commands require you to sign in as an Admin user.

### Enable remote provisioner management

#### On a new CA

To enable remote provisioner management on a new CA, pass `--remote-management` to `step ca init`. This will:

- Add an initial [JWK](/content/docs/step-ca/provisioners/#jwk/index.html) provisioner called Admin JWK to the database.
- Create an initial Super Admin user, with default username `step`, and link it to the Admin JWK provisioner.

#### On an existing CA

To migrate your `ca.json` provisioners to the database, and to enable remote provisioner management on an existing CA:

1. Stop `step-ca` if it is running.
2. Update your `"authority"` block in `ca.json` to include the following:

`"authority": {
"enableAdmin": true,
"provisioners": [\
    ...\
]
},

`

3. Start `step-ca` from the command line.

When `step-ca` starts up, it will:
   - Migrate the provisioners from your `ca.json` to the database
   - Repurpose the first JWK provisioner in your `ca.json` as an administrative provisioner. If no JWK provisioner exists, it will add a [JWK](/content/docs/step-ca/provisioners/#jwk/index.html) provisioner called Admin JWK to the database. You will be prompted for a password that will encrypt the new provisioner key.
   - Create an initial Super Admin user, with username `step`, and link it to the administrative provisioner.
4. Remove old provisioner configurations from `ca.json`.
Once your provisioners are migrated to the database, the provisioners in `ca.json` are ignored and you can remove them from that file:
`"authority": {
   		"enableAdmin": true,
           "provisioners": []
},

`

### Managing admin users

With remote provisioner management,

"Admins" can remotely manage provisioners.

"Super Admins" are Admins that can also manage the list of Admins for the CA using [`step ca admin`](/content/docs/step-cli/reference/ca/admin/index.html).

#### Create an admin user

To perform CA administrative operations, you sign into that provisioner as an Admin.

As a Super Admin, lets create an Admin user linked to the Admin JWK provisioner:

`step ca admin add carl "Admin JWK"

`

Output:

`SUBJECT    PROVISIONER        TYPE
carl       Admin JWK (JWK)    ADMIN

`

#### Authenticating as an admin

An Admin (or a Super Admin) is a combination of a username (a subject name) and a provisioner.
No passwords are associated with administrators.
An administrator is just a subject name and a provisioner name.

**The default Super Admin username is `step`, and the default admin provisioner is called `Admin JWK`.**

You can authenticate as an administrator via the authentication scheme of the provisioner.
For example, for the default JWK provisioner, running administrative commands in `step` will prompt for the provisioner password.

**Tip: single sign-on can be used for Admin users.**
To enable SSO CA administration, first add an [OIDC provisioner](/content/docs/step-ca/provisioners/#oauthoidc-single-sign-on/index.html) linked to your identity provider.
Then, add an Admin user associated with that provisioner, using your email address as the Admin's subject name.

The Admin and Super Admin privileges **are not scoped to a provisioner**:
admins can modify any provisioner configurations.
Super Admins are Admins that can also modify Admins, regardless of provisioner.

### Use remote provisioner management

You're all set. 🎉

You can use the [`step ca provisioner`](/content/docs/step-cli/reference/ca/provisioner/index.html) commands, from any client, to modify your CA's provisioner configuration.

#### Unattended remote provisioner management

If you want to manage provisioners remotely using a script or an Infrastructure as Code (IaC) tool,
you will need an _administrative certificate_ and key.

An administrative certificate must meet the following criteria:

- The Subject (or any SAN) must match the name of an Admin or Super Admin.
- The certificate must be issued by the provisioner of the Admin or Super Admin.
- The certificate must be valid and unexpired.
- A passively revoked certificate is valid until it expires; for immediate revocation, remove the admin instead of revoking the certificate.

To create an admin certificate, run:

`step ca certificate step admin.crt admin.key --provisioner "Admin JWK"

`

Output:

`✔ Provisioner: Admin JWK (JWK) [kid: 5UasaZcgkI_PxQeZqssfq5mzFnGHOWL5g5kDt07Vc1k]
Please enter the password to decrypt the provisioner key:
✔ CA: https://localhost
✔ Certificate: admin.crt
✔ Private Key: admin.key

`

With that certificate, you can use it as follows:

`step ca provisioner add ... --admin-cert=admin.crt --admin-key=admin.key

`

If the `admin.crt` represents a Super Admin, the same flags can also be used to manage Admins:

`step ca admin add ... --admin-cert=admin.crt --admin-key=admin_key

`

## Provisioner types

### JWK

JSON Web Key (JWK) is the default CA provisioner type,
and the [`step ca certificate`](/content/docs/step-cli/reference/ca/certificate/index.html) client tries to use it by default.
With a JWK provisioner,
a Certificate Signing Request (CSR) is sent to the CA
along with a short-lived JSON Web Token (JWT) which authenticates the request.

The JWK provisioner can be useful for custom integrations.
JWTs are easy to [generate programmatically](https://jwt.io/libraries),
without using `step`.
We have written a few [example clients](https://github.com/smallstep/clients/tree/main) for demonstration purposes.

Here's an example JWT used by `step-ca`:

`$ step ca token foo.internal | step crypto jwt inspect --insecure
{
"header": {
    "alg": "ES256",
    "kid": "kXLZ2xHQEXAMPLEq4j38N5QzQzNBmOPp0NCLzKAI0yA",
    "typ": "JWT"
},
"payload": {
    "aud": "https://ca.internal/1.0/sign",
    "exp": 1711479459,
    "iat": 1711479159,
    "iss": "carl@tashian.com",
    "jti": "8211a180b6EXAMPLEed81da54132e9...",
    "nbf": 1711479159,
    "sans": [\
      "foo.internal"\
    ],
    "sha": "c8de28e620ecEXAMPLE4a0c405d92d7350dbec351cec3e4f6a6d1fc9512387aa",
    "sub": "foo.internal"
},
"signature": "MEcSHfmIEXAMPLElNiLoDcHz90..."
}

`

The JWT subject (`sub`) specifies a subject Common Name for the issued certificate.
The `sha` and `sans` claims are non-standard:
they specify the root CA certificate fingerprint in SHA256
and any subject alternative names
that are authorized for inclusion in the issued certificate.

The JWT is designed to be generated in one context, then passed into the context where it will be used (eg. a container or pod).
Meanwhile, sensitive private key material can remain in the context where it is generated.
Therefore, by default, the JWT is not bound to the CSR, which may not yet exist when the token is created.
The JWT is instead bound to the expected SANs, subject common name, and the CA's root fingerprint.
See [Issue a Certificate Using A Single-Use CA Token](/content/docs/step-ca/basic-certificate-authority-operations/#issue-a-certificate-using-a-single-use-ca-token/index.html) for an example.

Optionally, a confirmation claim (`cnf`) can be added (as defined in [RFC 7800 § 3.4](https://datatracker.ietf.org/doc/html/rfc7800#section-3.4) to bind the JWT to a CSR. See [smallstep/certificates#1637](https://github.com/smallstep/certificates/issues/1637#issuecomment-1871620791) for details.

#### Example

Add a JWK provisioner:

`step ca provisioner add you@smallstep.com --create

`

In the ca.json configuration file, a complete JWK provisioner example looks like:

`{
    "type": "JWK",
    "name": "you@smallstep.com",
    "key": {
        "use": "sig",
        "kty": "EC",
        "kid": "NPM_9Gz_omTqchS6Xx9Yfvs-EuxkYo6VAk4sL7gyyM4",
        "crv": "P-256",
        "alg": "ES256",
        "x": "bBI5AkO9lwvDuWGfOr0F6ttXC-ZRzJo8kKn5wTzRJXI",
        "y": "rcfaqE-EEZgs34Q9SSH3f9Ua5a8dKopXNfEzDD8KRlU"
    },
    "encryptedKey": "eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjEwMDAwMCwicDJzIjoiTlV6MjlEb3hKMVdOaFI3dUNjaGdYZyJ9.YN7xhz6RAbz_9bcuXoymBOj8bOg23ETAdmSCRyHpxGekkV0q3STYYg.vo1oBnZsZjgRu5Ln.Xop8AvZ74h_im2jxeaq-hYYWnaK_eF7MGr4xcZGodMUxp-hGPqS85oWkyprkQLYt1-jXTURfpejtmPeB4-sxgj7OFxMYYus84BdkG9BZgSBmMN9SqZItOv4pqg_NwQA0bv9g9A_e-N6QUFanxuYQsEPX_-IwWBDbNKyN9bXbpEQa0FKNVsTvFahGzOxQngXipi265VADkh8MJLjYerplKIbNeOJJbLd9CbS9fceLvQUNr3ACGgAejSaWmeNUVqbho1lY4882iS8QVx1VzjluTXlAMdSUUDHArHEihz008kCyF0YfvNdGebyEDLvTmF6KkhqMpsWn3zASYBidc9k._ch9BtvRRhcLD838itIQlw",
    "claims": {
        "minTLSCertDuration": "5m",
        "maxTLSCertDuration": "24h",
        "defaultTLSCertDuration": "24h",
        "disableRenewal": false,
        "minHostSSHCertDuration": "5m",
        "maxHostSSHCertDuration": "1680h",
        "minUserSSHCertDuration": "5m",
        "maxUserSSHCertDuration": "24h",
        "enableSSHCA": true
    },
    "options": {
        "x509": {
            "templateFile": "templates/certs/x509/default.tpl"
        },
        "ssh": {
            "templateFile": "templates/certs/ssh/default.tpl"
        }
    }
}

`

- **type**: for a JWK provisioner it must be `JWK`, this field is case insensitive.

- **name**: identifies the provisioner, a good practice is to use an email address or a descriptive string that allows the identification of the owner, but it can be any non-empty string.

- **key**: is the JWK (JSON Web Key) representation of a public key
used to validate a signed token.

- **encryptedKey** [\*](/content/docs/step-ca/provisioners/#star1/index.html): is the encrypted private key used to sign a token.
It's a JWE compact string containing the JWK representation of the private key.
This value is not necessary for CA operation, but is provided for the convenience of clients.
Without the `encryptedKey` attribute, the private key must be provided by the client, using the `--key` flag.

- **claims** [\*\*](/content/docs/step-ca/provisioners/#star2/index.html): overwrites the default claims set in the authority.
See [claims](/content/docs/step-ca/configuration/#claims/index.html) for details.

- **options** [\*](/content/docs/step-ca/provisioners/#star2/index.html): see [template configuration](/content/docs/step-ca/templates/#configuring-step-ca-to-use-templates/index.html) for more details.

\*

Recommended

\*\*

Optional

#### Decrypting the private key

We can use [`step crypto jwe decrypt`](/content/docs/step-cli/reference/crypto/jwe/decrypt/index.html) to see the private key encrypted with the password `asdf`:

`$ step ca provisioner list \
| jq -r '.[] | select(.name == "you@smallstep.com") | .encryptedKey' \
| step crypto jwe decrypt \
| jq
Please enter the password to decrypt the content encryption key:
{
"use": "sig",
"kty": "EC",
"kid": "NPM_9Gz_omTqchS6Xx9Yfvs-EuxkYo6VAk4sL7gyyM4",
"crv": "P-256",
"alg": "ES256",
"x": "bBI5AkO9lwvDuWGfOr0F6ttXC-ZRzJo8kKn5wTzRJXI",
"y": "rcfaqE-EEZgs34Q9SSH3f9Ua5a8dKopXNfEzDD8KRlU",
"d": "rsjCCM_2FQ-uk7nywBEQHl84oaPo4mTpYDgXAu63igE"
}
`

#### Changing a JWK provisioner password

1. Retrieve the current encrypted key.

Run the following, changing the provisioner name in the `jq` command to match your configuration:
`OLD_ENCRYPTED_KEY=$(step ca provisioner list \
      | jq -r '.[] | select(.name == "you@smallstep.com").encryptedKey')

`
2. Update the encrypted key password.

Run:
`ENCRYPTED_KEY=$(echo $OLD_ENCRYPTED_KEY | \
     step crypto jwe decrypt | \
     step crypto jwe encrypt --alg PBES2-HS256+A128KW | \
     step crypto jose format)

`
You'll be asked for the old and new passwords.

3. Update the provisioner.

Run the following, changing the provisioner name in the command to match your configuration:
`step ca provisioner update you@smallstep.com \
     --private-key=<(echo -n "$ENCRYPTED_KEY")

`
4. Send a `SIGHUP` to `step-ca` to reload the configuration file.

(Skip this step if you have enabled remote provisioner administration.)
`killall -i -s SIGHUP step-ca

`

#### Rekeying a JWK provisioner

1. Update the provisioner.

Run the following, changing the provisioner name in the command to match your configuration:
`step ca provisioner update you@smallstep.com --create

`
2. Send a `SIGHUP` to `step-ca` to reload the configuration file.

(Skip this step if you have enabled remote provisioner administration.)
`killall -i -s SIGHUP step-ca

`

#### Removing the encrypted private key from a JWK provisioner

The encrypted private key stored in the JWK provisioner configuration and published to the public `/provisioners` endpoint is provided for client convenience.
It is not required for `step-ca` to operate.
To remove this key:

1. Update the provisioner.

Run the following, changing the provisioner name in the command to match your configuration:
`step ca provisioner update you@smallstep.com --private-key ""

`
2. Send a `SIGHUP` to `step-ca` to reload the configuration file.

(Skip this step if you have enabled remote provisioner administration.)
`killall -i -s SIGHUP step-ca

`

### OAuth/OIDC single sign-on

Sometimes it's useful to issue certificates to people.
So `step-ca` supports single sign-on with identity providers (IdPs) like Google, Okta, Microsoft Entra ID, Keycloak,
or any other provider that supports OAuth's [OpenID Connect extension](https://openid.net/connect/).

OpenID Connect is an extension to OAuth 2.0 that adds an identity layer.
Providers that support OIDC can issue identity tokens ("ID tokens") to OAuth clients.
These are JSON Web Tokens (JWTs) containing user identity information (eg. full name, username, email address).
Like certificates, OIDC tokens have a validity period and are cryptographically signed by a trust authority (the OAuth provider).

Here's an example OIDC identity token issued by Google:

`{
"alg": "RS256",
"kid": "cd49b2ab16e1e9a496c8239dac0dadd09d443012",
"typ": "JWT"
}.{
"iss": "https://accounts.google.com",
"azp": "1087160488420-8qt7bavg3qesdhs6it824mhnfgcfe8il.apps.googleusercontent.com",
"aud": "1087160488420-8qt7bavg3qesdhs6it824mhnfgcfe8il.apps.googleusercontent.com",
"sub": "115449349109627210866",
"hd": "smallstep.com",
"email": "mike@smallstep.com",
"email_verified": true,
"at_hash": "lE6o-GdMpurFQ0WrJ9-H7g",
"nonce": "5f5820880a43c3f50d55ce79af15430b14b4059bdf4efbe717da6af8bfc53122",
"iat": 1621877714,
"exp": 1621881314
}.[Signature]

`

The OIDC provisioner in `step-ca` can be configured to trust and accept an OAuth provider's ID tokens for authentication.
By default, the issued certificate will use the _subject_ (sub) claim from the identity token as its subject.
The value of the token's _email_ claim is also included as an email _SAN_ in the certificate.

_Fig. 3: diagram of how step works with individuals using a single sign-on provisioner_

From the user's perspective, when requesting a certificate, `step` detects the OIDC provisioner and initiates the OAuth login flow automatically:

`$ step ca certificate mike@smallstep.com mike.crt mike.key

✔ Key ID: 650445034027-jsjdrkiskeq9ke99ud2rqkst82ft8uch.apps.googleusercontent.com (Google)
✔ CA: https://ca.internal
✔ Certificate: mike.crt
✔ Private Key: mike.key
``$ step certificate inspect --short mike.crt
X.509v3 TLS Certificate (ECDSA P-256) [Serial: 2581...6739]
Subject:     115449349109627210866
          mike@smallstep.com
Issuer:      Smallstep Intermediate CA
Provisioner: Google [ID: 6504....com]
Valid from:  2019-06-20T18:21:52Z
      to:  2019-06-21T18:21:52Z
`

#### Configuring your identity provider (IdP)

When creating an OAuth app, there isn't much to configure on the IdP.
Most providers will ask you to specify a Redirect URI, where the ID token will be delivered at the end of the OAuth flow.
Since `step` starts its own local web server to receive the token, use `http://127.0.0.1` as the Redirect URI.

#### Example: Google identity

One of the most common providers, and the one used in the following example, is [Google Identity](https://developers.google.com/identity/protocols/oauth2/openid-connect).

Add a Google provisioner:

`$ step ca provisioner add Google --type oidc \
  --client-id 650445034027-jsjdrkiskeq9ke99ud2rqkst82ft8uch.apps.googleusercontent.com \
  --client-secret 6Q7lGMua_Oox4nA92QBXYypT \
  --configuration-endpoint https://accounts.google.com/.well-known/openid-configuration \
  --domain smallstep.com --domain gmail.com

`

Example `ca.json` provisioner configuration for a Google provisioner:

`{
"type": "OIDC",
"name": "Google",
"clientID": "1087160488420-8qt7bavg3qesdhs6it824mhnfgcfe8il.apps.googleusercontent.com",
"clientSecret": "udTrOT3gzrO7W9fDPgZQLfYJ",
"configurationEndpoint": "https://accounts.google.com/.well-known/openid-configuration",
"admins": ["you@smallstep.com"],
"domains": ["smallstep.com"],
"scopes": ["openid", "email"],
"listenAddress": ":10000",
"claims": {
    "maxTLSCertDuration": "8h",
    "defaultTLSCertDuration": "2h",
    "disableRenewal": true
},
"options": {
      "x509": {
          "templateFile": "templates/certs/x509/default.tpl"
      },
      "ssh": {
          "templateFile": "templates/certs/ssh/default.tpl"
      }
}
}

`

- **type**: indicates the provisioner type and must be OIDC.

- **name**: a string used to identify the provider when the CLI is used.

- **clientID**: the client id provided by the identity provider used to initialize the authentication flow.

- **clientSecret**: the shared secret provided by the identity provider; used to get the id token during the OAuth flow. Some identity providers may use an empty string as a secret. In the context of `step-ca`, the client "secret" is not actually a secret and is available via the CA's `/provisioners` configuration endpoint, because every `step` client needs to use it locally.

- **configurationEndpoint**: is the HTTP address used by the CA to get the OpenID Connect configuration and public keys used to validate the tokens.

- **admins** [\*](/content/docs/step-ca/provisioners/#star3/index.html): These privileged users may request certificates with arbitrary subject names (custom SANs). Non-privileged users may only request certificates for their email address.

- **domains** [\*](/content/docs/step-ca/provisioners/#star3/index.html): is the list of domains valid. If provided only the emails with the provided domains will be able to authenticate.

- **scopes**: a list of scopes OAuth clients should request. This is used by the `step` CLI. The default value is `["openid","email"]`.

- **listenAddress** [\*](/content/docs/step-ca/provisioners/#star3/index.html): is the address (`:port` or `host:port`) where the authorization server will redirect the client's web browser at the end of the authorization flow. By default, the `step` client will bind to 127.0.0.1 on a random port. This parameter is only required if the authorization server demands a specific port for loopback IP redirect URIs.

- **claims** [\*](/content/docs/step-ca/provisioners/#star3/index.html): overwrites the default claims set in the authority,
see the [claims](/content/docs/step-ca/configuration/#claims/index.html) section for all the options.

\*

Optional

#### Browserless console mode

For OpenID Connect, by default, `step` opens a web browser to run the Authorization Code flow with PKCE.

Sometimes it's helpful to use OAuth in an input-constrained environment where no web browser is available.
The Device Authorization Grant flow (aka "Device Flow") is an OAuth 2.0 extension designed for this scenario.
The `step` client supports the Device Authorization Grant flow.

To use the Device Authorization Grant flow for input-constrained devices, run:

`$ step ca certificate foo foo.crt foo.key --console

`

or

`$ STEP_CONSOLE=true step ssh certificate carl carl.crt

`

#### Notes

**Why is the OAuth client secret unprotected?**

When using the OIDC provisioner, you may notice that your OAuth client secret is visible to anyone via the CA's `/provisioners` API endpoint.
Counterintuitively, this is a secure implementation of OAuth that conforms to the OAuth Best Current Practices for Native Apps ( [RFC8252 / IETF BCP212](https://www.rfc-editor.org/rfc/rfc8252.html)).
And it is the same approach that Google's `gcloud` CLI tool uses for Google Cloud Platform authentication: An OAuth client secret is hardcoded into its source code.

So, what makes it secure?
The Authorization Code flow for native OAuth apps requires the redirect URI hostname be hardcoded as `127.0.0.1` (or `localhost`) in the client configuration.
This constraint obviates the need for a client secret, because the loopback address is inherently resistant to network attacks that the client secret is designed to mitigate in other, non-native app flows.

An attacker in posession of the client secret would need local access to your device in order to compromise the flow.
OAuth in general is not very resistant to local attacks, so the threat model for the native app flow with an exposed client secret is the same as with any other OAuth flow:
It assumes that if you have a local attacker on your device, it's unlikely that this kind of attack is going to be your biggest threat.

The client secret is superfluous in the Authorization Code flow for native apps.
In fact, BCP212 has recommended that OAuth identity providers offer a special OAuth client type that has no client secret.
In practice, very few OAuth providers have implemented this "secretless" approach, so we don't yet support it.
Functionally, however, it is equivalent to having a public secret.

Bottom line, the OAuth flow implemented in `step` and `step-ca` is widely vetted and considered secure.
