Configure Certificate Provisioners in step-ca | Smallstep
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
- Authorization Scope by Provisioner
- Provisioner Management
- Remote Provisioner Management
- Provisioner Types
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 messenger application identities.
The configuration for this is described in ACME for Wire messenger clients.
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 | ssh-host-cert-renew | ssh-revoke | ssh-rekey |
|---|---|---|---|---|---|---|---|---|---|
| JWK | โ๏ธ | โ๏ธ | โ๏ธ | โ๏ธ | โ๏ธ | ๐ซ | ๐ซ | โ๏ธ | ๐ซ |
| OIDC | โ๏ธ | โ๏ธ | โ๏ธ | โ๏ธ | โ๏ธ 2 | ๐ซ | ๐ซ | โ๏ธ | ๐ซ |
| 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.
2
Privileged OIDC subject names can generate Host SSH Certificates. These can be configured in the OIDC provisioner.
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 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 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 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-balancedstep-ca instances,
or if you want to manage your provisioners remotely (eg. with Infrastructure as Code (IaC) tools; see below).
See Remote Provisioner Management for more.
Common provisioner operations
Common provisioner operations include:
- Adding a provisioner
- Removing a provisioner
- Listing all provisioner
- Modifying the configuration of an existing provisioner
Unless you are using remote provisioner management, 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 to add a provisioner:
`step ca provisioner add acme --type ACME
`
See the command reference for complete documentation and examples.
Remove a provisioner
Use step ca provisioner remove 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 or the /provisioners endpoint on your CA.
Modify a provisioner
Use step ca provisioner update 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 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 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:
- Stop
step-caif it is running. - Update your
"authority"block inca.jsonto include the following:
`"authority": {
"enableAdmin": true,
"provisioners": [
...
]
},
`
- Start
step-cafrom the command line.
When step-ca starts up, it will:
- Migrate the provisioners from your
ca.jsonto the database - Repurpose the first JWK provisioner in your
ca.jsonas an administrative provisioner. If no JWK provisioner exists, it will add a JWK 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.
- Remove old provisioner configurations from
ca.json. Once your provisioners are migrated to the database, the provisioners inca.jsonare 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.
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 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 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 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,
without using step.
We have written a few example clients 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 for an example.
Optionally, a confirmation claim (cnf) can be added (as defined in RFC 7800 ยง 3.4 to bind the JWT to a CSR. See smallstep/certificates#1637 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 *: 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
encryptedKeyattribute, the private key must be provided by the client, using the--keyflag.claims **: overwrites the default claims set in the authority. See claims for details.
options *: see template configuration for more details.
*
Recommended
**
Optional
Decrypting the private key
We can use step crypto jwe decrypt 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
- 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.
- 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 aSIGHUPtostep-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
- 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 aSIGHUPtostep-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:
- 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 aSIGHUPtostep-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.
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.
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/provisionersconfiguration endpoint, because everystepclient 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 *: These privileged users may request certificates with arbitrary subject names (custom SANs). Non-privileged users may only request certificates for their email address.
domains *: 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
stepCLI. The default value is["openid","email"].listenAddress *: is the address (
:portorhost:port) where the authorization server will redirect the client's web browser at the end of the authorization flow. By default, thestepclient 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 *: overwrites the default claims set in the authority, see the claims 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).
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.