--- page_title: Authenticate a Stack description: Learn how to set up OIDC authentication or use the store block to authenticate Stacks with their providers. --- ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ > [!IMPORTANT] > **Documentation Update:** Product documentation previously located in `/website` has moved to the [`hashicorp/web-unified-docs`](https://github.com/hashicorp/web-unified-docs) repository, where all product documentation is now centralized. Please make contributions directly to `web-unified-docs`, since changes to `/website` in this repository will not appear on developer.hashicorp.com. ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ # Authenticate a Stack You can authenticate a Stack in two ways: by using OIDC to dynamically authenticate with the built-in `identity_token` block or by accessing existing authentication credentials with the `store` block. We recommend authenticating your Stack with OIDC because using static credentials to authenticate providers presents a security risk, even if you rotate your credentials regularly. ## Authenticate with OIDC [OpenID Connect](https://openid.net/connect/) (OIDC) is an identity layer on top of the OAuth 2.0 protocol. You can use HCP Terraform’s [Workload identity](/terraform/cloud-docs/workspaces/dynamic-provider-credentials/workload-identity-tokens) tokens, built on the OpenID Connect protocol, to securely connect and authenticate your Stacks with cloud providers. -> **Hands on**: Walk through setting up OIDC for a Stack in the [Deploy a Stack with HCP Terraform](/terraform/tutorials/cloud/stacks-deploy) tutorial. Stacks have a built-in `identity_token` block that creates workload identity tokens, also known as JWT tokens. You can use these tokens to authenticate Stacks with Terraform providers securely. This guide covers how to set up OIDC for Stacks using the `identity_token` block. ### Overview The details of Stack authentication differ based on which cloud provider you are setting up, but the basic steps remain the same: 1. Set up the trust configuration between your cloud provider and HCP Terraform, which usually includes creating roles and policies for your cloud provider. 1. Add an `identity_token` block to your Stack’s deployment file using the audience and roles you created in the previous step. Your deployments can reference the value of the `identity_token` block to pass the trust relationship role to your Stack’s operations. ### Configure trust configuration In this example, you will set up an example trust policy with AWS. For examples of setting up trust policies with other providers, refer to our [repository of example configurations](https://github.com/hashicorp-guides/terraform-stacks-identity-tokens/tree/main). We recommend using Terraform to create and configure the trust relationship and permissions for the cloud provider you want to authenticate with. Using the following Terraform configuration, [create a new workspace](/terraform/cloud-docs/workspaces/create) and configure the `aws_region`, `tf_organization`, `tf_project,` and `tf_stack` variables for your specific set up. ```hcl # main.tf variable "aws_region" { type = string description = "The AWS region to create the role in." } variable "tf_organization" { type = string description = "The name of the organization that this workspace and Stack live in." } variable "tf_project" { type = string description = "The name of the project that this workspace and Stack live in." } variable "tf_stack" { type = string description = "The name of the Stack you will you use this token in." } provider "aws" { region = var.aws_region } resource "aws_iam_openid_connect_provider" "stacks_openid_provider" { url = "https://app.terraform.io" client_id_list = ["aws.workload.identity"] # This is the thumbprint of https://app.terraform.io as of 2024/08/07 # Refer to "Adjust access of trust" to learn how to update this thumbprint thumbprint_list = ["9e99a48a9960b14926bb7f3b02e22da2b0ab7280"] } resource "aws_iam_role" "stacks_role" { name = "stacks-${var.tf_organization}-${var.tf_project}-${var.tf_stack}" assume_role_policy = data.aws_iam_policy_document.stacks_role_policy.json } data "aws_iam_policy_document" "stacks_role_policy" { statement { effect = "Allow" principals { type = "Federated" identifiers = [aws_iam_openid_connect_provider.stacks_openid_provider.arn] } actions = ["sts:AssumeRoleWithWebIdentity"] condition { test = "StringEquals" variable = "app.terraform.io:aud" values = ["aws.workload.identity"] } condition { test = "StringLike" variable = "app.terraform.io:sub" # This value dictates which HCP Terraform organizations, projects, # and stacks can assume the new role you are creating. # # You can widen access to an entire organization or project by # tweaking the value below. You can also restrict access to specific # deployments or operations. Refer to Configure trust for more information. values = ["organization:${var.tf_organization}:project:${var.tf_project}:stack:${var.tf_stack}:*"] } } } # Now, you give the new role access to things you want to manage in your Stack. # # The policies below are too broad for a production use case, but you set them # broadly for now to ensure this Stacks can do anything during development and # testing. In practice, only give your Stack access to what it needs to manage. resource "aws_iam_role_policy_attachment" "iam" { role = aws_iam_role.stacks_role.name policy_arn = "arn:aws:iam::aws:policy/IAMFullAccess" } resource "aws_iam_role_policy_attachment" "sudo" { role = aws_iam_role.stacks_role.name policy_arn = "arn:aws:iam::aws:policy/PowerUserAccess" } # Your workspace returns this output role, which you use to configure your # deployments. output "role_arn" { value = aws_iam_role.stacks_role.arn } ``` After setting up your workspace in HCP Terraform, perform a plan and apply operation. HCP Terraform will create your OpenID provider, policy, and role before outputting your new role’s ARN with the `role_arn` output. Copy your new AWS ARN role because this is the value you use to configure your cloud provider with your Stack and HCP Terraform. #### Adjust access of trust Workload identity tokens contain useful metadata in their payloads, known as claims. Once a cloud platform verifies a token using HCP Terraform’s public key, it can look at the identity token's claims to match it to the correct permissions or reject it. You do not need to understand the full token specification or what every claim means, but you can use the claims to adjust your trust relationship. Workload identity tokens commonly reference the following claims. | Claim | Explanation | | :---- | :---- | | `jti` (JWT ID) | A unique identifier for each token, which is a UUID. | | `iss` (issuer) | Full URL of the HCP Terraform instance that signed the token. For example, “https://app.terraform.io”. | | `iat` (issued at) | Unix timestamp when the token was issued. May be required by certain relying parties. | | `nbf` (not before) | Unix Timestamp when the token can start being used. Should be the same as `iat` for your purposes and may be required by certain relying parties. | | `aud` (audience) | Intended audience for the token. For example, “api://AzureADTokenExchange” for Azure. | | `exp` (expiration) | Unix timestamp based on the timeout of the operation phase that it was issued for. | | `sub` (subject) | Fully qualified path to a Stack deployment, followed by the operation type:
`organization::project::stack::deployment:my-deployment-name:operation:`

For example:
`organization:My_Org:project:My_Project:stack:My_Stack:deployment:staging:operation:apply` | You can further customize your token’s permissions using the following custom claims. | Claim | Explanation | | :---- | :---- | | `terraform_operation` ("run phase") | The Terraform operation this token was issued for. For example, “plan” or “apply”. | | `terraform_stack_deployment_name` | Name of the deployment that the operation is for. | | `terraform_stack_id` (stack ID) | External ID of the Stack that the operation is for. | | `terraform_stack_name` (stack name) | Name of the Stack that the operation is for. | | `terraform_project_id` (project ID) | External ID of the project that the operation is taking place in. Useful if you want to use the same role across Stacks in a given project. | | `terraform_project_name` (project name) | Name of the project that the operation is taking place in. | | `terraform_organization_id` (organization ID) | External ID of the HCP Terraform organization that the operation is taking place in. Useful if you are in a large company that may have more than one organization or if you want to use the same role across your entire organization. | | `terraform_organization_name` (organization name) | Name of the HCP Terraform organization that the operation is taking place in. | | `terraform_plan_id` (plan ID) | External ID of the plan that this token is being used for creating or applying. This might be used to track down where a token has been leaked from or to block a specific token if it has been leaked. | You can also update your configuration to use the current thumbprint for HCP Terraform by running the following command and removing the colons from the value it returns. ```shell-session $ echo | openssl s_client -showcerts -servername app.terraform.io -connect app.terraform.io:443 2>/dev/null | openssl x509 -fingerprint -noout -sha1 sha1 Fingerprint=FD:88:23:AE:FB:96:13:28:A1:34:70:6D:C8:57:5A:17:0F:0B:B3:7C ``` ### Configure HCP Terraform Stacks use the [`identity_token` block](/terraform/language/stacks/reference/tfdeploy#identity_token-block-configuration) to define a JSON Web Token (JWT) for a specific deployment. This token enables OIDC-based authentication, allowing your Stack deployments to securely connect to cloud providers like AWS, Azure, and GCP. When you define the `identity_token` block, you specify its audience. For example, the example Stack deployment configuration defines an `identity_token` block specifying the AWS audience. ```hcl identity_token "aws" { audience = ["aws.workload.identity"] } ``` Once defined, you can reference an identity token in a deployment's input variables and reference that token in a provider’s configuration. You also need to add your trust relationship, your role ARN, to configure your token with the trust relationship to authenticate AWS resources. ```hcl # deployments.tfdeploy.hcl identity_token "aws" { audience = ["aws.workload.identity"] } deployment "development" { inputs = { role_arn = "" identity_token = identity_token.aws.jwt } } ``` Now, the deployments are authenticated with AWS and can pass the trust configuration to your Stack’s providers for authentication. ```hcl # variables.tfstack.hcl variable "role_arn" { type = string } variable "identity_token" { type = string ephemeral = true } # providers.tfstack.hcl required_providers { aws = { source = "hashicorp/aws" version = "~> 5.7.0" } } provider "aws" "this" { config { region = var.region assume_role_with_web_identity { role_arn = var.aws_role web_identity_token = var.aws_token } } } ``` With this setup, each of your deployments pass the ARN of your trust relationship role and a JWT token generated by AWS each time you plan or apply your Stack. Each of your deployments uses their own role, configured with the specific permissions you require. For more examples of setting up OIDC with different providers, refer to our [repository of example configurations](https://github.com/hashicorp-guides/terraform-stacks-identity-tokens/tree/main). ## Authenticate with existing credentials You can use the `store` block to define key-value secrets in your deployment configuration and then access those values in your deployments. You can use the `store` block to access credentials stored in an [HCP Terraform variable set](/terraform/cloud-docs/workspaces/variables/managing-variables#variable-sets). This example uses a `store` block with a variable set to access credentials stored in HCP Terraform. For more information about using `store` blocks, refer to the [Deployment configuration reference](/terraform/language/stacks/reference/tfdeploy). Before writing any configuration, ensure your Stack can access the variable set you are targeting by allowing your project to access the set or making the set globally available. Next, add a `store` block to your deployment configuration file to access your variable set. Once defined, your deployments can access your variable set’s values. ```hcl # deployments.tfdeploy.hcl # Source environment secrets from your HCP Terraform variable set store "varset" "tokens" { id = "varset-" category = "env" } # Access your variable set's value using your store and pass them into your # deployment's inputs. deployment "test" { inputs = { access_key = store.varset.tokens.AWS_ACCESS_KEY_ID secret_key = store.varset.tokens.AWS_SECRET_ACCESS_KEY session_token = store.varset.tokens.AWS_SESSION_TOKEN } } ``` For example, if your `test` deployment can use your `store` to access your variable set’s keys, and therefore, your variable set’s AWS provider credentials. Your `test` deployment can define your AWS credentials as `inputs`, allowing your `providers` to access those credentials. ```hcl # providers.tfstack.hcl variable "access_key" { description = "AWS access key" type = string ephemeral = true } variable "secret_key" { description = "AWS sensitive secret key." type = string sensitive = true ephemeral = true } variable "session_token" { description = "AWS session token." type = string sensitive = true ephemeral = true } required_providers { aws = { source = "hashicorp/aws" version = "~> 5.7.0" } } provider "aws" "this" { config { access_key = var.access_key secret_key = var.secret_key token = var.session_token } } ``` This example allows your `aws.this` provider to authenticate to AWS using the credentials from a variable set stored in HCP Terraform. For more information about using `store` blocks, refer to the [Deployment configuration reference](/terraform/language/stacks/reference/tfdeploy).