OpenID Connect is a protocol that can be used to authenticate with your compatible third-party service. OIDC allows your deployments to exchange short-lived tokens directly from your cloud provider or third-party service. env0 provides an OIDC token as an environment variable, which is also a short-lived token. A deployment can use it to access a compatible cloud service without the need for a long-lived credential stored and managed by env0, adding an extra layer of security to your deployments.
OpenID Connect (OIDC) is a simple identity layer on top of the OAuth 2.0 protocol. It allows third-party applications to verify the end user's identity and obtain basic user profile information. OIDC uses JSON web tokens (JWTs), which you can obtain using flows conforming to the OAuth 2.0 specifications.
JWT is actually a pretty simple format: a base64-encoded JSON string. Its goal is representing claims securely between two parties. Of course, decoding a base64 is a straightforward method and anyone could decode it as it’s not encrypted. Security kicks in when validating its signature. JWT contains a header, payload, and signature. A signature is the result of a function that uses the header, the payload, a secret key, and hash function. If the payload/claim is modified, the signature will not be the same, rendering the JWT invalid.
OIDC is an identity authentication protocol and may be used to verify the identity of a user to client service or between services. This widespread protocol is implemented by many third-party service providers, and is a safe and relatively easy way to authenticate with those services. For instance, you could use it to authenticate your favorite Secrets Manager, fetching values securely and verifying the permissions to this service. For example, your GitHub Action could fetch secrets from your AWS/GCP/Azure cloud and use them during its processing.
In order to deploy your Infrastructure as Code (IaC) successfully while integrating your cloud service, env0 deployments have access to your cloud credentials or sensitive variables. Although env0 encrypts and securely saves your sensitive cloud credentials or secrets, you may want to manually manage the access to those values. Using the OIDC protocol can add an extra layer of security to your deployments: instead of letting env0 manage those values, you can grant the env0 IdP (Identity Provider) to securely access your Secret Manager at deployment runtime.
env0 provides an OIDC token (JWT) as an environment variable called [.code]ENV0_OIDC_TOKEN[.code]. This variable can be made available at deployment time, which can then be used to access compatible cloud services with no long-lived credential stored in env0. With our Custom Flows mechanism, you can access this JWT value and use it to authenticate your third-party service and fetch data securely.
Let’s set up a simple OIDC flow in env0 together to see how it works :)
Organization admins can enable the OIDC integration by toggling the related checkbox in the Organization Policies tab. Afterwards, any deployment will have access to an [.code]ENV0_OIDC_TOKEN[.code] environment variable.
In this blog post, we’ll cover how to integrate Vault by OIDC. For other services consult the service’s documentation for how to add an identity provider (e.g. GCP, AWS). Generally, the process involves two phases. Phase one adds an OIDC/JWT authentication method to your service. This phase will require adding a JWT Verification method. The second phase will probably include Bounding Claims.
JWT signatures will be verified against public keys from the issuer (env0). A JSON Web Key Set (JWKS) URL should be configured on your third-party service’s side. Keys will be fetched from this endpoint during authentication. This way your third-party service can decrypt and verify env0’s JWT ([.code]ENV0_OIDC_TOKEN[.code]).
Our JWKS URL is: https://login.app.env0.com/.well-known/jwks.json
Once a JWT has been validated as being properly signed and unexpired, the authorization flow should validate that any configured "bound" parameters match. This is a very important step which ensures that only a specific JWT can access your third-party service. In our case, we need to make sure that the JWT:
The OpenID Connect ID token contains the following standard claims. The following table shows the main claims you will probably want to bind and validate on your third-party service’s side.
Our JWT also contains some additional custom claims that you need to validate:
The OIDC token is unique to your organization. The custom claims attached to the token contain your organization ID. You can find your env0 organization ID by navigating to the Organization Settings page in our web app and copying the UUID from the URL.
Prepare your Vault cluster
Let’s create a new dummy KV store in Vault in order to save and fetch secrets from it.
If you already have your own secrets store up and running, you can skip this step. Just note that in this guide we named our store as [.code]secrets-for-env0[.code]. The new ACL policy named [.code]env0-access[.code] will be used in the following steps for allowing access to this KV store through our OIDC token login.
As we saw earlier, we should add a JWT authentication method in our Vault then configure env0 JWKS URL to ensure Vault can verify and decrypt env0’s JWTs.
You could use Vault’s Terraform provider, but here we’ll make it simpler by using the following CLI commands:
If you like, you can view the results on Vault’s UI by navigating to Access -> Auth Methods.
In the following example, we add a new custom role that binds [.code]sub, aud[.code] and env0’s custom claims via the Vault CLI. For more info see the tables above.
Now your Vault cluster is ready to receive env0’s JWTs—meaning your deployments can authenticate with Vault!
After you successfully enable and configure OIDC on both sides of the bridge, the final step is to deploy your env0 environment and log into Vault. The following YAML file is our [.code]env0.yml[.code] which controls our Custom Flows mechanism. Here we add a custom script, hooked after the “Load Variables” deployment step. This script downloads Vault CLI directly to the deployment docker’s runtime. Then it executes the JWT’s login CLI command which uses both the role we created earlier and the special [.code]ENV0_OIDC_TOKEN[.code] environment variable. Finally, we successfully put a new secret in Vault and fetch it right after.
Note that to execute that Custom Flow successfully, you should either create an [.code]env0.yml[.code] file or append that hook to your existing file. In addition, you should add the following Environment Variables with their proper values: [.code]ROLE_NAME, VAULT_ADDR, VAULT_NAMESPACE[.code].