When using GitHub as the version control system (VCS) provider for Terraform, it’s hard to decide which authentication methods the organization should adopt: GitHub App or GitHub OAuth?
In this blog, we’ll explore the differences between these two methods, their advantages, drawbacks, and best practices. This will help you choose the right approach based on your team’s security and operational requirements. Whether you’re managing a small project or an enterprise Terraform setup, understanding these options will help you optimize your workflow and security posture.
About GitHub App vs. OAuth
If you have already know how GitHub App and GitHub OAuth work in the Terraform integration, you can skip this section.
About GitHub App
A GitHub App is a type of integration designed to interact with GitHub repositories and organizations independently of any individual user. It uses fine-grained permissions, gives the user more control over which repositories the app can access, can be installed in multiple repositories, and remains active even if a user who installed the app on an organization leaves the organization.
Set up the GitHub.com (GitHub App) VCS provider for HCP Terraform.
About GitHub OAuth
GitHub OAuth apps use personal user authentication to access repositories. You can create and register an OAuth app under your personal account or under any organization you have administrative access to. If the user who created the GitHub Oauth app leaves the organization, access may be lost.
Set up the GitHub.com OAuth VCS provider for HCP Terraform.
Categories to consider
When an organization uses GitHub as the VCS provider for Terraform to create workspaces, it must choose an authentication method: GitHub App, OAuth, or both. Each method has its own advantages and limitations. Several factors should be considered when making this decision. Key considerations include:
GitHub repository setup
In this blog, we will focus on repository setup and access control for GitHub repositories.
Repository structure: Repositories can be structured either by projects or teams:
By IT projects: Each project is independent, with minimal cross-team collaboration.
By organization teams: Teams often need to share resources across multiple projects they own.
Repository permissions: Setting the right permissions is essential for Terraform workspaces. Organizations must follow the least-privilege principle when granting access rights.
Read access: Required for Terraform to pull the latest configuration from GitHub.
Write/admin access: Only required for the admin managing the repositories.
Organizational authentication and permission standards
Authentication and permission determine how an organization manages connections between GitHub and Terraform, ensuring secure and controlled access.
Management and maintenance of GitHub connections:
Here are common concerns from customers regarding GitHub-Terraform integration…
Who can set up the connection? How do you define the roles and permissions for configuring GitHub-Terraform connections?
What happens if the person who set the connection leaves the company? What are the options for ensuring continuity?
Who or which team can see those connections? How do you control visibility and access to Terraform’s VCS integrations?
Permissions when creating workspaces:
Who can use the connection? How do you define which teams or individuals are allowed to use the GitHub-Terraform connection?
How do you restrict access and where can you set the restrictions?
Webhooks and communication
Different authentication methods handle webhooks and repository updates differently. Understanding their impact on Terraform workspaces is key to maintaining efficiency and scalability.
How do webhooks affect Terraform workspaces? When there are updates in a GitHub repository, Terraform workspaces may be triggered based on the webhook configuration. The impact depends on:
Authentication method: GitHub App vs OAuth.
Repository changes: Commits, pull requests, or branch merges can trigger Terraform runs.
Workspace configuration: Workspaces linked to specific branches may trigger runs automatically, while others require manual confirmation. And you can also define automatic speculative plans in the Terraform workspace.
Impact on workload and performance: The organization needs to consider the current and future sizes of Terraform deployments.
Size of the Terraform deployment: Small-scale deployment vs large-scale deployment.
Terraform concurrency limits: HCP Terraform and Enterprise enforce concurrent run limits based on the chosen plan.
Free and Standard plans: Lower concurrency, potential queuing delays.
Plus, Premium, and Enterprise plans: Higher concurrency but still requires monitoring to prevent performance issues.
Number of GitHub repositories per connection: A single GitHub connection can manage multiple repositories, but excessive repositories on one connection may impact webhook performance.
In the next sections, I will dive deeper into these considerations, compare different methods, and discuss their pros and cons.
GitHub repository setup
Repository structure and permissions are the first things you will look at as you decide whether to use GitHub App, OAuth, or both.
Repository structure
There are many factors to consider when designing a GitHub repository structure for an organization. When GitHub is used as the VCS provider for Terraform, one of the key decisions is whether to secure repositories by project or by team. Below is a comparison table outlining the pros, cons, and common use cases for structuring IT projects vs organization teams. The GitHub repository structure can impact your choice between GitHub App and GitHub OAuth.
Factor
By IT projects
By organization teams
Pros
Easier integration with Terraform workspaces when workspaces are separated by IT projects.
Avoids unintended cross-project dependencies.
Granular repository access, ensuring only project members have access.
Easier integration with Terraform workspaces when workspaces are separated by the organization teams.
Fewer repositories to manage, reducing repo sprawl.
Cons
As the number of IT projects grows, the organization must manage more repositories, potentially increasing Terraform traffic when updates occur.
Harder to enforce access control when team members need to manage resources across different projects.
Terraform files for multiple projects are stored in a single repository, which may lead to access control issues.
Common use case
Recommended for most Terraform setups, especially when the company’s cost structure is IT project-based and requires strict access control by user.
Can be used when resources aren’t tied to specific IT projects. Some orgs track costs by department or team instead of project-based cost centers, so provisioning outside project scope is acceptable.
Repository permissions
Based on the repository structure, the organization needs to determine how to grant and maintain repository access permissions for its members. More information about the access permissions on GitHub can be found here.
Deep dive: Authentication and permission
GitHub provides an article on the differences between GitHub Apps and OAuth Apps, comparing several factors. However, when it comes to Terraform VCS connections, there is limited information on how these two approaches differ in practice and where to configure access restrictions. This section will present a visualized comparison to help you better understand these differences and make an informed decision.
GitHub App authentication
This method uses a preconfigured GitHub App for HCP Terraform.This VCS provider is only available on HCP Terraform. If you are using Terraform Enterprise, you can follow the instructions for creating a GitHub App for Terraform Enterprise or connecting to GitHub.com via OAuth.
Key data point overview:
Terraform user account: Created within Terraform.
Repo access list: Defined per GitHub organization, linked to the corresponding Terraform user account (which matches the GitHub user account).
GitHub:
Organization: Each GitHub organization manages a set of repositories.
GitHub personal account
Authentication set up
Set up requirements:
The HCP Terraform App needs to be installed to each GitHub Organization / Personal account. This can be done through a service account/user account in GitHub for the GitHub Organization.
The admin (the service account/user account) who manages the GitHub App configuration needs to add the Terraform user accounts with the repositories that they could access.
Each HCP Terraform user authenticates individually, and can use GitHub resources within HCP Terraform according to their own GitHub organization memberships and access permissions.
Installation:
GitHub: Each GitHub organization needs to install the HCP Terraform app.
HCP Terraform/Terraform Enterprise:
Each Terraform user must install the GitHub App initially, but only once. After installation, the user can leverage the GitHub App across multiple organizations within the HCP Terraform platform or Terraform Enterprise tenant.
Each user in HCP Terraform will need to authorize the App once, before being able to see available installations and selecting a repository to connect a workspace.
HCP Terraform can only have one GitHub App installed.
Terraform user account and the corresponding repo access list
Terraform user account name
Repo access list (GitHub Org A)
Repo access list (GitHub Org B)
Repo access list (GitHub personal account)
TF_User1
A_Dev1
A_Test2
B_Dev4
User1_test1
TF_User2
A_Prod 2
None
None
TF_User3
None
B_Prod1
None
GitHub App authentication flow
Access permissions:
Each Terraform user account is linked to a GitHub user account.
A Terraform user’s repository list remains the same across the HCP Terraform platform or Terraform Enterprise tenant. For example, TF_User1 will see the same repository list in Terraform Org1 and Terraform Org2.
Repository access is managed at the GitHub organization level, where admins define access per user. In the example diagram above, the access is defined in the table “Terraform user account and the corresponding repo access list”. For example, in GitHub Organization A, TF_User1 may have access to repositories A_Dev1 and A_Test2. When TF_User1 creates a workspace using the GitHub App, they will see Organization A: ADev1, ATest2 in the repository list.
The same is applicable to the GitHub personal account.
With GitHub App, customers can limit which repositories the app has access to. This control is managed within GitHub (under Personal Account/Organization App settings).
There is currently no way to limit access within HCP Terraform, and repositories cannot be added except by administering changes directly in GitHub.
Users cannot restrict which repositories are available for specific projects or workspaces, unlike in OAuth.
A workaround would be to create the workspace programmatically using the TFE provider, specifying which repository will be used in the VCS section. Alternatively, you can block access at plan or apply time using Sentinel for the VCS source.
GitHub App installation remains active even after the user who installed it leaves the GitHub organization. As long as the user has access in GitHub to the installation and authorizes the GitHub App within Terraform Enterprise, workspaces can continue to connect to it.
GitHub OAuth authentication
This method uses a per-organization OAuth connection.
Key data point overview:
Terraform user account: In Terraform, user accounts can be created and managed within Terraform itself. When using the GitHub OAuth authentication model, there are two key roles in this approach:
Owner: This role is responsible for establishing the GitHub OAuth connection between Terraform and GitHub using personal credentials. The owner can be either an individual user account or a dedicated service account. This role requires permission to manage VCS settings for the organization.
User: This role utilizes the existing GitHub OAuth authentication connections within the Terraform project, without needing to establish a new connection.
Repo access list: Defined per GitHub organization, linked to the corresponding Terraform user account (which matches the GitHub user account).
GitHub:
Organization: Each GitHub organization manages a set of repositories.
Authentication set up
Below are the steps between GitHub and HCP Terraform to set up the connection:
In your GitHub organization
In HCP Terraform (Owner role)
1. Create a new connection in HCP Terraform. Get a callback URL.
2. Register your HCP Terraform organization as a new app. Provide callback URL.
3. Provide HCP Terraform with ID and key. Request VCS access.
4. Approve access request.
(optional) Configure advanced settings. For example, use the “Scope of VCS Provider” to limit which projects can use this connection.
Below are the settings on the Terraform side to limit which projects can use which connection to access repositories in the GitHub organization.
GitHub OAuth connection name
Terraform projects in the allow list
GitHub organization
A_Dev
Org1_Dev
Org1_Test
Organization A / all repositories that the owner has access to.
A_Test
Org1_Dev
Org1_Prod
Organization A / all repositories that the owner has access to.
A_Prod
Org2_Prod
Org2_Dev
Organization A / all repositories that the owner has access to.
B_Prod
Org2_Stage
Org2_Dev
Organization B / all repositories that the owner has access to.
Each Terraform organization can have multiple GitHub OAuth connections. For example, Org1 has two GitHub OAuth connections: ADev and ATest.
Terraform user account and the corresponding repo access list
Owner role:
TF_Owner could create VCS connections in both Terraform organizations: Org1 and Org2.
TF_Owner has access to the repos in GitHub organization A and GitHub organization B.
User role:
TF_User can access Terraform organizations: Org1 and Org2.
GitHub OAuth authentication flow
Access permission
The owner (TF_Owner) needs to have the permission to manage VCS settings for the organization.
The Terraform user ( TFUser 1, TFUser 2…) needs to have access to the Terraform organization and projects to create workspaces. For example, TF_User 1 could create workspaces in all projects in Org1, it means:
If the user is in project Org1_Dev, then the user would see two GitHub OAuth connections are available to use when creating workspaces:
A_Dev to create workspaces from all repositories in Organization A.
A_Test to create workspaces from all repositories in Organization A.
If the user is in project Org2_Dev, then the user would see two GitHub OAuth connections are available to use when creating workspaces in Organization A and Organization B:
A_Prod to create workspaces from all repositories in Organization A.
B_Prod to create workspaces from all repositories in Organization B.
With GitHub OAuth, providers can have different scopes to define which workspaces can use repositories from the VCS provider.
If the user account is removed (e.g. when an employee leaves the company), the rest of the team loses access to the connection.
A workaround is to create an OAuth connection from GitHub using an organization account.
Comparison between GitHub App and GitHub OAuth: Authentication and permissions
GitHub App
GitHub OAuth
Setup complexity
Requires installation of the GitHub App in the organization
Simpler setup using personal OAuth tokens
Permission: Install / uninstall
Organization owner or users with admin permissions
Individual users who have access to the Github repositories.
Connections per Terraform organization
One
Multiple
Access control
Supports organization-level and repository-level permissions
Grants access at the user level, affecting all repositories the user has access to
Access control setup
Setup repository access in GitHub
Setup Terraform project access in Terraform
Token expiry & rotation
Tokens are managed by GitHub and do not expire unless revoked.
The GitHub App remains available for other Terraform users even if the user who installed it on GitHub leaves.
OAuth tokens can expire and may require re-authentication
The OAuth connection becomes unusable if the user who set it up for the organization leaves.
End-user access to GitHub repository list
The list of repositories is linked to the Terraform user’s personal GitHub account, regardless of which project the user is creating the workspace for.
The list of repositories is linked to the Terraform project, regardless of which Terraform user creates the workspace.
Webhooks and communication
HCP Terraform uses webhooks to monitor new commits and pull requests. This section explains how webhooks function differently in a GitHub App connection versus a GitHub OAuth connection. This will help you understand the communication between GitHub and Terraform, as well as the workload triggered when changes occur in the GitHub repository.
GitHub App authentication
The chart below illustrates how webhooks work with Terraform and the GitHub App.
GitHub:
The organization admin adds the user (TF_User1) to GitHub Organization A.
TFUser1 is granted access to the repositories: ADev1, ATest2, and ADev2.
The GitHub App has a callback URL, for example: callbackuser1url, to manage webhook communications.
Terraform:
User account: TF_User1
The user creates two workspaces from the GitHub App connection:
Workspace TFATest2 from GitHub repository A_Test2
Workspace TFADev1 from GitHub repository A_Dev1
The yellow tunnel represents the global webhook for the GitHub App.
All installation events are transmitted through this bridge.
The volume of messages received is controlled by:
The repositories the GitHub App has access to.
The events the GitHub App is subscribed to.
GitHub App does not require manual webhook registration; it automatically sends requests for all or selected repositories to a single webhook callback URL. If only 10 out of 1,000 repositories are selected, the GitHub App will not receive webhook events from the other 990 repositories.
Communication between GitHub and Terraform is based on the number of users × the number of repositories assigned to each user. A single pull request (PR) in Repo1 could trigger communication with multiple HCP Terraform/Terraform Enterprise instances.
GitHub OAuth authentication
The chart below illustrates how webhooks work with Terraform and GitHub OAuth.
GitHub OAuth requires the application to register a webhook on each repository to receive webhook events.
When connecting a workspace to a repository, Terraform registers a webhook for that repository. For example:
In project Org1Test, the workspace WS1 is created using a GitHub OAuth connection with the repository ARepo1_dev, which triggers the registration of a webhook on that repository.
In project Org1Prod, the workspace WS2 is created using a GitHub OAuth connection with the repository ARepo1_dev, which triggers the registration of another webhook on that repository.
If a repository is not connected to any workspace, GitHub will not send webhook events for it. For example, the repository ARepo1test does not have a webhook registered because it is not connected to any workspace in Terraform.
Customers may encounter duplicate webhook registrations if they create multiple OAuth clients. For example, the repository ARepo1dev has two webhook registrations.
Communication between GitHub and Terraform is based on the sum of all workspace connections for each repository. For example:
If repository ARepo1dev has a PR, it will send webhook events to the two workspaces (WS1 and WS2) but will not send webhook events to WS3.
If repository ARepo2prod has a PR, it will send webhook events to WS3 only.
If another repo, e.g. ARepo1test has a PR, it won’t send a webhook event to any workspaces.
Comparison between GitHub App and GitHub OAuth: Webhook and communication
GitHub App
GitHub OAuth
Webhook registration
Automatically managed by the GitHub App
Requires manual webhook registration.
Webhook scope
Webhooks apply only to the selected repositories.
Webhooks are registered only for repositories connected to workspaces.
Event filtering
Receives events only for the repositories selected in the GitHub App installation.
GitHub only sends events for repositories linked to a Terraform workspace.
Duplicate webhooks
No risk of duplicate webhook registration
Possible duplicate webhooks if multiple OAuth clients are created.
Communication model
Based on (# of users × # of assigned repositories)
Based on the sum of all workspace connections for each repository
Triggering workloads
A single PR in a repository can trigger multiple workspaces
A PR triggers webhook events only for linked workspaces
Webhook URL management
Uses a single callback URL for all selected repositories
Each repository requires its own webhook registration
Example scenario
There is no right or wrong approach when choosing between GitHub App and OAuth, and both can coexist in certain scenarios.
For example, in this case, the customer has the following requirements:
Restrict workspace creation to a specific project. For example, in project A, the user can only choose certain repositories, while the same user in project B, can choose a different set of repositories.
Limit repository selection when creating a workspace via the VCS provider.
Ensure connection continuity when the person who created the VCS connection leaves the team.
Recommended Solution – GitHub OAuth, with the following considerations:
Manage repositories through a separate GitHub organization since GitHub OAuth does not allow limiting which repositories are listed.
Use a system/service account in Terraform (or an account that won’t expire) when creating the connections to ensure long-term stability.
Reduce duplicate webhooks by standardizing OAuth clients within the organization
Helpful links
Connect to VCS Providers
Integration with GitHub App: Describes how to integrate your Terraform Enterprise deployment with a GitHub App.
Differences between GitHub Apps and OAuth apps