How to fix Error: Unauthorized in Terraform

TerraformINTERMEDIATEHIGHUpdated Dec 30, 2025· 107 views

The 'Error: Unauthorized' in Terraform occurs when authentication credentials are missing, expired, or invalid when communicating with cloud APIs or Kubernetes clusters. This commonly happens with token-based authentication that expires between operations.

Quick fix

Fixes UNAUTHORIZED

provider "kubernetes" {
  host                   = var.cluster_host
  token                  = var.cluster_token
  cluster_ca_certificate = base64decode(var.cluster_ca)
}
  1. Verify your credentials are set correctly
  2. Run terraform refresh before destroy
  3. Verify RBAC permissions for Kubernetes
  4. Use load_config_file = false for Kubernetes provider
terraform — error
provider "kubernetes" {
host = var.cluster_host
token = var.cluster_token
cluster_ca_certificate = base64decode(var.cluster_ca)
}
Error: Unauthorized

What this error means

This error indicates that Terraform attempted to authenticate with a provider (such as Kubernetes, AWS, GCP, or Azure) but the credentials provided were either missing, malformed, expired, or didn't have the required permissions. The provider rejected the authentication attempt at the API level. This is different from a connection error—the server is responding, but it's refusing to grant access with the provided credentials.

Typical symptoms

  • terraform apply or terraform destroy fails midway through resource creation/destruction
  • Error message includes 'Unauthorized' or 'the server has asked for the client to provide credentials'
  • Works on first run but fails on subsequent runs with the same configuration
  • Specific resources fail (e.g., 'Failed to update deployment: Unauthorized')
  • Authentication works in curl or kubectl but fails in Terraform

Common causes

  1. Authentication token has expired between terraform apply and terraform destroy operations (common with Kubernetes, especially with 1-hour token TTL)
  2. Missing or incorrectly configured credentials (missing API token, missing KUBE_TOKEN environment variable)
  3. Insufficient permissions—the authenticated user/service account lacks RBAC permissions to perform the requested action
  4. Provider configuration mismatch (e.g., load_config_file true/false, wrong context in kubeconfig)
  5. Terraform provider version incompatibility with token-based authentication
  6. Invalid or revoked API credentials (expired AWS temporary credentials, revoked access tokens)
  7. Running create and destroy in same Terraform run before cluster finishes initialization

How to fix "Error: Unauthorized"

1Verify your credentials are set correctly

Check that your authentication credentials are properly configured in your Terraform provider block or environment variables.

For Kubernetes:

hcl
provider "kubernetes" {
  host                   = var.cluster_host
  token                  = var.cluster_token
  cluster_ca_certificate = base64decode(var.cluster_ca)
}

For AWS/Azure/GCP:
Ensure your AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, or equivalent credentials are set:

bash
export AWS_ACCESS_KEY_ID="your-key-id"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_DEFAULT_REGION="us-east-1"
2Run terraform refresh before destroy

Token expiration is common when tokens have short TTLs (e.g., 1 hour). Refresh before destroying to fetch new credentials:

bash
terraform refresh
terraform destroy

This forces Terraform to re-authenticate before attempting the destroy operation.

3Verify RBAC permissions for Kubernetes

If using Kubernetes, ensure the service account or user has the required permissions:

bash
kubectl auth can-i create deployments --as=system:serviceaccount:default:my-sa
kubectl auth can-i delete deployments --as=system:serviceaccount:default:my-sa

If permissions are missing, create a ClusterRole and ClusterRoleBinding:

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: terraform-admin
rules:
  - apiGroups: ["*"]
    resources: ["*"]
    verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: terraform-admin-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: terraform-admin
subjects:
  - kind: ServiceAccount
    name: terraform
    namespace: default
4Use load_config_file = false for Kubernetes provider

If using kubeconfig file, sometimes explicitly disabling auto-loading helps:

hcl
provider "kubernetes" {
  load_config_file       = false
  host                   = var.cluster_host
  token                  = var.cluster_token
  cluster_ca_certificate = base64decode(var.cluster_ca)
}

This forces Terraform to use only the explicitly provided credentials instead of trying to load ~/.kube/config.

5Check token expiration and regenerate if needed

If using temporary tokens (AWS STS, Kubernetes service account tokens), verify they haven't expired:

bash
# For AWS STS tokens
aws sts get-caller-identity

# For Kubernetes tokens
kubectl get secret my-secret -o jsonpath='{.data.token}' | base64 -d

RegenerateTokens if expired:
- AWS: Use aws sts get-session-token to get fresh credentials
- Kubernetes: Create a new service account token or use long-lived tokens
- Cloud providers: Regenerate API keys from console

6Separate cluster creation from resource application

Avoid creating the cluster and Kubernetes resources in the same Terraform apply:

bash
# First, apply only the cluster
terraform apply -target=aws_eks_cluster.main

# Then apply Kubernetes resources
terraform apply

This ensures the cluster exists and is fully initialized before Terraform tries to authenticate to it.

Advanced notes

Token Lifecycle in Terraform: Terraform does not automatically refresh authentication state during long-running operations. If your token expires during a multi-resource apply or destroy, Terraform will fail partway through. Solutions:

1. Use long-lived tokens when possible (at least as long as your Terraform operations take)
2. Use exec-based auth for dynamic credential refresh (recommended for Kubernetes on EKS/GKE/AKS):

hcl
provider "kubernetes" {
  exec {
    api_version = "client.authentication.k8s.io/v1beta1"
    command     = "aws"
    args        = ["eks", "get-token", "--cluster-name", var.cluster_name]
  }
}

3. Use HCP Terraform Dynamic Credentials if running in cloud:

hcl
provider "kubernetes" {
  dynamic "exec" {
    for_each = var.use_oidc ? [1] : []
    content {
      api_version = "client.authentication.k8s.io/v1beta1"
      command     = "terraform"
      args        = ["provider", "exec", "--", "kubernetes"]
    }
  }
}

Kubernetes-Specific: The system:anonymous user often appears in destroy errors. This happens because the provider's authentication context is lost. Explicitly setting the kubeconfig context avoids this:

hcl
provider "kubernetes" {
  config_context = var.kube_context  # e.g., "docker-desktop"
}

Azure AKS: If using Microsoft Entra ID (Azure AD) authentication, static token auth will always fail. Use the exec block with Azure CLI:

hcl
provider "kubernetes" {
  exec {
    api_version = "client.authentication.k8s.io/v1beta1"
    command     = "az"
    args        = ["aks", "get-credentials", "--resource-group", var.resource_group, "--name", var.cluster_name, "--file", "-"]
  }
}

Frequently asked questions

What does "UNAUTHORIZED" mean?
This error indicates that Terraform attempted to authenticate with a provider (such as Kubernetes, AWS, GCP, or Azure) but the credentials provided were either missing, malformed, expired, or didn't have the required permissions. The provider rejected the authentication attempt at the API level. This is different from a connection error—the server is responding, but it's refusing to grant access with the provided credentials.
How do I fix "UNAUTHORIZED"?
The 'Error: Unauthorized' in Terraform occurs when authentication credentials are missing, expired, or invalid when communicating with cloud APIs or Kubernetes clusters. This commonly happens with token-based authentication that expires between operations.
What causes "UNAUTHORIZED"?
Authentication token has expired between terraform apply and terraform destroy operations (common with Kubernetes, especially with 1-hour token TTL) Missing or incorrectly configured credentials (missing API token, missing KUBE_TOKEN environment variable) Insufficient permissions—the authenticated user/service account lacks RBAC permissions to perform the requested action
Is the "UNAUTHORIZED" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading