User Identity vs Service Account in GCP: Differences, Use Cases, and Best Practices
In GCP, every identity is either a user identity (a human) or a service account (a workload or application). User identities sign in interactively with a password. Service accounts authenticate automatically using short-lived tokens. The practical rule is straightforward: humans use user identities, automated code uses service accounts.
By the end of this page you will understand the difference between these two identity types, how to pick the right one for each situation, and how Application Default Credentials and Workload Identity Federation fit into the picture.
The simple explanation
Think of a user identity as an employee badge for a person and a service account as an access badge for a piece of software.
Two kinds of badge, two kinds of access
An employee badge works because it is linked to a person who can swipe it, enter a PIN, and take responsibility for using it. But a door that opens automatically when a server sends a command at 3am does not need a person’s badge. It needs a badge for the system. That is a service account: an identity that belongs to the system, not to any individual. When the person leaves, their badge gets deactivated. The system’s badge keeps working.
Here is the fundamental split:
- User identity: a human who signs in through a browser with a password and MFA.
- Service account: a workload or application that authenticates automatically using short-lived tokens, with no human present.
- Humans should not use service accounts for their own access. Service accounts cannot use interactive login flows.
- The default rule: if something runs automatically, give it a service account. If a person is doing it, they use their own identity.
User identity vs service account at a glance
| User identity | Service account | |
|---|---|---|
| Represents | A human | An application or workload |
| Used by | Engineers, admins, developers | Apps, VMs, pipelines, automated jobs |
| Login style | Interactive (browser + password + MFA) | Non-interactive (short-lived tokens) |
| Typical use case | Cloud Console, running gcloud locally | Cloud Run calling Storage, CI/CD deploying infrastructure |
| Tied to a person | Yes | No (belongs to a project) |
| Safe for automation | No | Yes |
| Best place to use it | Interactive human sessions | Any workload that runs without a human present |
| Common risk | Used in automation, breaks when person leaves | Over-permissioned, key file committed to git |
If a human is clicking or typing, it is a user identity. If code is running without anyone present, it is a service account. That single distinction resolves almost every identity decision you will face in GCP.
How it works
User identities
A user identity is a Google Account (Gmail) or a
Cloud Identity or Google
Workspace account managed by your organisation. When you access the Cloud Console,
run gcloud on your machine, or grant access to a colleague, you are
working with user identities.
Authentication is interactive. You enter a password, complete MFA if required, and Google issues a short-lived OAuth token. The IAM roles bound to your account determine what you are allowed to do.
# Grant a user IAM access to a project
gcloud projects add-iam-policy-binding my-project \
--member="user:alice@example.com" \
--role="roles/viewer"Service accounts
A service account is a special GCP identity for non-human workloads. It has an email-style identifier and is managed as a resource within a GCP project. It belongs to the project, not to any individual. When a VM, Cloud Run service, or GKE pod runs with an attached service account, GCP automatically issues short-lived credentials through the metadata server. Your code does not need to manage credentials at all.
IAM roles work the same way for service accounts as for users. You grant the service account the roles it needs, and GCP enforces those permissions on every API call.
# Create a service account
gcloud iam service-accounts create backend-api \
--display-name="Backend API" \
--project=my-project
# Grant it a narrowly scoped role
gcloud projects add-iam-policy-binding my-project \
--member="serviceAccount:backend-api@my-project.iam.gserviceaccount.com" \
--role="roles/storage.objectViewer"User credentials are tied to an individual. When that person changes roles or leaves your organisation, their access is revoked and any automation using their credentials breaks. It is a reliability problem on top of a security problem. Service accounts belong to the project. Team changes do not affect them.
When to use a user identity
Use a user identity when a human is directly taking the action:
- An engineer opens the Cloud Console to create a VM, inspect logs, or review IAM bindings
- A developer runs
gcloudcommands on their local machine - An admin grants or revokes IAM access for a colleague
- A team member reviews resources in the Console during an incident
- You are granting access to a new contractor or team member
For local development, developers also authenticate as their user identity through Application Default Credentials so that local code can call GCP APIs. This is covered in the Application Default Credentials section below.
Never pass your personal credentials to a script, pipeline, or application. Credentials tied to your account give that automation your full permissions across GCP. When your access is eventually revoked, the automation breaks silently. Use a service account instead.
When to use a service account
Use a service account any time automated code needs to interact with GCP:
A Cloud Run service calling Cloud Storage. Attach a service account with
roles/storage.objectViewerto the Cloud Run service. No key file. No environment variable. Application Default Credentials finds the attached account automatically.A Compute Engine VM reading from Firestore. Attach a dedicated service account at VM creation time instead of accepting the broad default Compute Engine service account.
A CI/CD pipeline deploying infrastructure. A GitHub Actions workflow or Cloud Build job should run as a service account with only the deployment roles it needs. Use Workload Identity Federation to avoid creating a key file.
A GKE pod accessing a GCP API. Workload Identity binds a Kubernetes service account to a GCP service account so each pod has its own narrowly scoped identity.
A Cloud Function triggered by Pub/Sub. The function runs as a service account and can be granted only the permissions that specific function requires.
Any scheduled or automated job. Cloud Scheduler, Cloud Tasks, and Cloud Workflows all support running as a service account.
If a resource runs on GCP, attach a service account to it. The platform handles credentials through the metadata server automatically. No key file. No stored credential. No environment variable pointing to a JSON file. For a deeper guide to creating and managing service accounts, see GCP Service Accounts.
Common mistakes
Using a personal account in automation. The script works today. Six months later, that person moves teams, their access is revoked, and the pipeline breaks at 2am. Service accounts are not tied to individuals. Use them for all automated tasks.
Sharing one service account across multiple workloads. Revoking or adjusting access for one workload then affects all of them. A compromised application exposes every other application sharing that identity. Create one service account per distinct workload.
Granting Editor or Owner to a service account. A service account reading from Cloud Storage needs
roles/storage.objectViewer, notroles/editor. Broad roles mean a compromised service account causes broad damage. Follow the principle of least privilege.Committing a key file to git. A
key.jsonfile in a repository, even a private one, is a leaked credential. Automated scanners find them within minutes. Use attached service accounts for GCP workloads and Workload Identity Federation for external ones. If a key file is unavoidable, store it in Secret Manager, not in source control. See Why Service Account Keys Are Dangerous for the full picture.Confusing
gcloud auth loginwithgcloud auth application-default login. These serve different purposes. The first authenticates thegcloudCLI. The second sets the credentials that GCP client libraries use in your application code. For local development, you typically need both.
User identity vs service account: key differences
The distinction between a user identity and a service account is not just semantic. It affects how authentication works, how credentials are managed, and what happens when people join or leave your organisation.
Ownership and lifecycle
An employee leaves. The server stays.
When an employee leaves a company, their ID card is deactivated. Any system that relied on that card stops working. But the building’s HVAC system, the security cameras, the automated locks — those keep running because they have their own credentials that belong to the building, not the employee. Service accounts work the same way. They belong to the project. When a team member leaves, the service account keeps running until you deliberately delete it.
Authentication mechanism
User identities use interactive authentication: a browser-based OAuth flow with a password and MFA. Service accounts use non-interactive authentication: short-lived access tokens issued by the metadata server (for attached accounts) or via an external token exchange through Workload Identity Federation. No password, no MFA prompt, no browser required.
What happens in IAM
Both types are principals in IAM. You bind
IAM roles to them using the same
add-iam-policy-binding command. The member prefix differs:
user: for user identities, serviceAccount: for service
accounts. Apart from that, IAM treats them identically.
Safe for automation
User identities are not safe for automation because they are tied to an individual and require interactive re-authentication when tokens expire. Service accounts are designed for automation: credentials refresh automatically, there is no interactive login requirement, and they can be granted the minimum permissions a workload needs.
Putting user credentials in automation is both a reliability and a security risk. Service accounts cannot perform interactive browser logins. Keep the two identity types completely separate. If you hit permission errors after setting up an identity, see IAM Access Denied Errors for the most common causes.
Local development vs production
The identity your code uses changes depending on where it runs. Here is how each environment should be set up.
Local development
When a developer runs code on their own machine, they typically authenticate using their user identity through Application Default Credentials:
# Authenticate the gcloud CLI (for running gcloud commands)
gcloud auth login
# Set credentials for GCP client libraries in your application code
gcloud auth application-default loginAfter gcloud auth application-default login, your local application
code has whatever GCP permissions your personal account holds. If your account has
broad project access, a bug in local code could affect real production resources.
To test with narrower permissions that match production, impersonate a service account
instead of using your user identity directly.
For more accurate local testing that mirrors what will happen in production, you can impersonate a service account without creating a key file:
# Run local code as if it were a specific service account
gcloud auth application-default login \
--impersonate-service-account=backend-api@my-project.iam.gserviceaccount.comThis requires the Service Account Token Creator role on the target account. No long-lived key file is created.
Production on GCP
In production, attach a service account to every GCP resource that needs to call GCP APIs. The platform provides credentials automatically via the metadata server. Your application code changes nothing. Application Default Credentials finds the attached service account without any additional configuration.
# Attach a service account to a Cloud Run deployment
gcloud run deploy my-service \
--region=us-central1 \
--service-account=backend-api@my-project.iam.gserviceaccount.com \
--image=gcr.io/my-project/my-service
# Attach a service account to a VM at creation time
gcloud compute instances create my-vm \
--zone=us-central1-a \
--service-account=backend-api@my-project.iam.gserviceaccount.com \
--scopes=cloud-platformNo key files. No GOOGLE_APPLICATION_CREDENTIALS environment variables.
No credentials in your application code. Just an attached service account and
Application Default Credentials doing the work invisibly.
Application Default Credentials
Application Default Credentials (ADC) is the mechanism GCP client libraries use to find the right identity to authenticate as. Your code does not specify credentials directly. The library calls ADC, and ADC works through a lookup chain to find what is available.
ADC is like a key ring
When your code needs to authenticate, ADC tries each key on the ring in order.
First it checks for a key file path in the environment. Then it checks if you
ran gcloud auth application-default login. Then it checks whether
the compute resource it is running on has an attached service account. In
production with a properly attached service account, the right key is always
right there on the ring and no other configuration is needed.
The lookup order:
- The
GOOGLE_APPLICATION_CREDENTIALSenvironment variable: if set, ADC uses the key file it points to - Credentials from
gcloud auth application-default login: used for local development with your user identity - The service account attached to the running GCP resource: the metadata server provides the token automatically
- The default service account of the GCP environment, if present
On a VM or Cloud Run service with an attached service account, ADC skips the first two steps and resolves the attached account through the metadata server. No environment variables, no key files, no credential configuration in your application code.
# For local development: set your user identity as the ADC source
gcloud auth application-default login
# Check which identity ADC is currently using
gcloud auth application-default print-access-token
# For local testing that mirrors production: impersonate a service account
gcloud auth application-default login \
--impersonate-service-account=backend-api@my-project.iam.gserviceaccount.comgcloud auth login authenticates the gcloud CLI so you
can run gcloud commands. gcloud auth application-default login
sets the credentials GCP client libraries use inside your application code. For local
development, run both. On GCP infrastructure with an attached service account, neither
is needed.
In production, always prefer an attached service account over setting
GOOGLE_APPLICATION_CREDENTIALS to a key file. The attached account approach
means there is no credential to store, rotate, or accidentally expose. If you hit
authentication errors, see
Troubleshooting Authentication Errors
for the most common causes and fixes.
External workloads and Workload Identity Federation
When code runs outside GCP (in GitHub Actions, on AWS, on Azure, or on-premises) it cannot use an attached service account because there is no GCP infrastructure to attach to. The traditional workaround was to create a service account key file and store it as a secret in the external system.
Workload Identity Federation eliminates the need for key files by mapping an external identity to a GCP service account:
- The external workload presents its own credential (a GitHub Actions OIDC token, an AWS IAM role, a Kubernetes service account token)
- GCP verifies the external credential against a configured identity pool
- GCP issues a short-lived GCP access token for the mapped service account
- The workload uses that token to call GCP APIs. No key file was created or stored.
# Create a Workload Identity Pool for GitHub Actions
gcloud iam workload-identity-pools create "github-pool" \
--project=my-project \
--location="global" \
--display-name="GitHub Actions Pool"
# Allow a specific repository's workflow to impersonate a service account
gcloud iam service-accounts add-iam-policy-binding \
deploy-bot@my-project.iam.gserviceaccount.com \
--project=my-project \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github-pool/attribute.repository/my-org/my-repo"A key file stored in GitHub Actions secrets is a long-lived credential that does not expire automatically. A Workload Identity Federation token is short-lived, scoped to a single workflow run, and leaves no permanent credential anywhere. If your CI/CD runs outside GCP, set up federation before reaching for a key file. See Service Account Keys Explained for a comparison of all credential options.
Best practices
Humans use user identities. Workloads use service accounts. Keep the two identity types completely separate. Never use a personal account for automation, and do not grant service accounts interactive Console access.
One service account per workload. A Cloud Run service and the CI/CD pipeline that deploys it should have separate service accounts. This limits the blast radius of any compromise and keeps access auditing straightforward.
Apply least privilege. Grant each service account only the IAM roles it needs to function. A workload that reads from Cloud Storage should have
roles/storage.objectViewer, notroles/editor. See Principle of Least Privilege for a practical guide.Prefer attached identities over key files. If your code runs on GCP, attach a service account to the compute resource. This removes the entire class of credential-file vulnerability.
Use Workload Identity Federation for external workloads. GitHub Actions, AWS workloads, and on-premises pipelines should use federation rather than storing a service account key file as a secret.
Use impersonation instead of key files for testing. To test what a service account can do, use
gcloud —impersonate-service-accountrather than downloading a key. See Service Account Impersonation for setup instructions.Audit access regularly. Service account roles accumulate. Review what each service account can access quarterly and check for key files that are no longer in use with
gcloud iam service-accounts keys list.Separate human and workload access patterns. Do not grant a service account the same broad project-level role you might grant a human admin. Service accounts should have narrower, resource-specific permissions matched to exactly what the workload does.
Summary
- User identities are for humans; service accounts are for applications and automation
- User identities authenticate interactively with a password; service accounts use short-lived tokens with no human involvement
- Service accounts belong to a project, not a person. They keep running when team members leave.
- On GCP infrastructure, attach a service account to the resource. Application Default Credentials finds it automatically via the metadata server.
- For local development, run
gcloud auth application-default loginto give client libraries your user identity - For external workloads (GitHub Actions, AWS), use Workload Identity Federation instead of a key file
- One service account per workload; grant only the minimum permissions it requires
Frequently asked questions
What is the difference between a user identity and a service account in GCP?
A user identity (Google Account or Cloud Identity account) represents a human. It authenticates with a password and MFA and is managed outside GCP. A service account represents a non-human workload: an application, a VM, a pipeline. It has no password and authenticates automatically via short-lived tokens. The rule is simple: humans get user identities, automation gets service accounts.
Should a CI/CD pipeline use a user account or a service account?
Always a service account. A user account is tied to an individual. If that person changes teams or leaves, the pipeline breaks. A service account belongs to the project, can be granted only the permissions the pipeline needs, and keeps working regardless of team changes. Use Workload Identity Federation to avoid creating a key file.
Can a human use a service account?
Not interactively. Service accounts have no password and cannot use browser-based OAuth login flows. However, a human with the roles/iam.serviceAccountTokenCreator role can impersonate a service account using gcloud --impersonate-service-account to generate a short-lived token. This is the correct way to test what a service account can do without creating a key file.
What is the safest way for code outside GCP to authenticate to Google Cloud?
Workload Identity Federation. It lets an external identity (a GitHub Actions OIDC token, an AWS IAM role, a Kubernetes service account) exchange for a short-lived GCP access token. No key file is created or stored. This is significantly safer than downloading a service account key file and storing it in CI environment variables.
Do I need both gcloud auth login and gcloud auth application-default login?
For local development, yes. They serve different purposes. gcloud auth login authenticates the gcloud CLI itself, so you can run gcloud commands. gcloud auth application-default login sets the credentials that GCP client libraries (Python, Go, Node.js) use in your application code. On GCP infrastructure with an attached service account, neither is needed: Application Default Credentials finds the service account automatically via the metadata server.