Who Is Responsible for Auth in a Microservices Architecture

by Eric Hanson, Backend Developer at Clean Systems Consulting

The gap that produces security incidents

Your organization has eight services. Each team owns one. Each team has independently decided how to handle authentication and authorization. Team A validates JWTs using RS256. Team B validates them using HS256 with a secret that three developers know. Team C doesn't validate tokens on internal endpoints because "those are internal only." Team D added auth six months after launch and the implementation is inconsistent across endpoints.

This is not an extreme scenario. It's the default outcome when auth responsibility is not explicitly assigned in a microservices architecture. The result is inconsistent security posture, duplicated implementation work, and at least one team that's made a decision they don't realize is wrong.

Authentication versus authorization: different problems, different owners

These are frequently conflated but require separate ownership decisions.

Authentication answers: is this request from who it claims to be? It involves verifying credentials, issuing tokens, validating token signatures, and managing sessions. This is a cross-cutting concern that should be owned centrally.

Authorization answers: is this authenticated identity allowed to perform this operation on this resource? This is domain-specific. Whether a user can delete an order depends on business rules that the Order Service owns. Whether a service account can call a payment endpoint is a policy decision that needs to be enforced close to the resource.

These require different ownership models because they have different change rates, different stakeholders, and different risk profiles.

Who owns authentication

Authentication — token issuance, validation standards, key management, session lifetime — belongs to a central platform team or a dedicated auth service. This is not a microservice in the business domain sense; it's infrastructure. It should be treated with the same discipline as your API gateway or your Kubernetes cluster.

The deliverables from the auth infrastructure:

  • A token issuance endpoint (OAuth 2.0 authorization server: Keycloak, Auth0, or a custom implementation)
  • A JWKS endpoint for public key distribution
  • A shared validation library consumed by all services
  • Documented token format: which claims are in every token, what they mean, what their expected values are
  • Key rotation policy and tooling

All services use the central validation library. No service implements its own JWT parsing. When the signing algorithm changes or new required claims are added, the library is updated once and services adopt it on their next deploy.

Who owns authorization

Authorization logic belongs to the service that owns the resource. The User Service decides what user data different callers can access. The Payment Service decides which operations require which roles. The Order Service decides whether a given user can modify a given order.

The mistake is centralizing authorization: building a permissions service that every other service calls to check "can user X do action Y on resource Z?" This sounds clean architecturally but creates a synchronous dependency on your authorization service for every permission check in the system. If the permissions service is slow or unavailable, the entire system degrades.

Authorization checks should be local. Each service evaluates claims from the JWT (roles, permissions, user attributes) against its own authorization rules:

@PreAuthorize("hasRole('ADMIN') or #userId == authentication.principal.userId")
public Order getOrder(String orderId, String userId) {
    return orderRepository.findById(orderId)
        .orElseThrow(() -> new OrderNotFoundException(orderId));
}

For more complex policies, Open Policy Agent (OPA) can be deployed as a sidecar, providing local policy evaluation without a network call to a central service:

# OPA policy: can this user access this order?
allow {
    input.user.roles[_] == "admin"
}

allow {
    input.user.id == input.resource.owner_id
    input.action == "read"
}

OPA evaluates policies locally using data pushed to it — the policy evaluation itself is not a network call.

Service-to-service authorization

When services call each other, the authorization question is: is this service allowed to call this endpoint? This is different from user authorization.

The answer should be explicit, not implicit. Relying on "only internal services can reach this endpoint" (network isolation alone) is insufficient if a service is compromised. Use service identity claims in tokens:

// Service-to-service JWT claims
{
  "sub": "order-service",
  "aud": "payment-service",
  "scope": "payments:create",
  "iss": "https://auth.internal",
  "exp": 1714089600
}

The Payment Service validates that the caller is order-service and has payments:create scope. Scope grants are managed centrally (in the auth service configuration) but enforced locally (by Payment Service).

Making ownership explicit

Write it down. Your architecture documentation should specify:

  • Which team owns the authentication infrastructure
  • Which team is responsible for updating the shared validation library
  • How authorization decisions are made in each service
  • Who approves service-to-service permission grants
  • What the process is when a new service needs to call an existing protected endpoint

Unwritten ownership is no ownership. In practice, it means the first team to make a decision makes it for everyone — or the last team to be asked makes it inconsistently with what came before. Neither outcome is acceptable for security-critical infrastructure.

Scale Your Backend - Need an Experienced Backend Developer?

We provide backend engineers who join your team as contractors to help build, improve, and scale your backend systems.

We focus on clean backend design, clear documentation, and systems that remain reliable as products grow. Our goal is to strengthen your team and deliver backend systems that are easy to operate and maintain.

We work from our own development environments and support teams across US, EU, and APAC timezones. Our workflow emphasizes documentation and asynchronous collaboration to keep development efficient and focused.

  • Production Backend Experience. Experience building and maintaining backend systems, APIs, and databases used in production.
  • Scalable Architecture. Design backend systems that stay reliable as your product and traffic grow.
  • Contractor Friendly. Flexible engagement for short projects, long-term support, or extra help during releases.
  • Focus on Backend Reliability. Improve API performance, database stability, and overall backend reliability.
  • Documentation-Driven Development. Development guided by clear documentation so teams stay aligned and work efficiently.
  • Domain-Driven Design. Design backend systems around real business processes and product needs.

Tell us about your project

Our offices

  • Copenhagen
    1 Carlsberg Gate
    1260, København, Denmark
  • Magelang
    12 Jalan Bligo
    56485, Magelang, Indonesia

More articles

Why Backend Developers Often Inherit Everyone Else’s Problems

Backend developers often end up carrying the weight of the whole team. When roles are missing or absent, the backend becomes the glue holding everything together.

Read more

Employee vs Contractor: The Real Financial Difference

Why that “expensive” contractor rate isn’t as simple as it looks (and why employees aren’t as cheap as they seem)

Read more

The Performance Bug That Only Appears Under Real Traffic

Some performance problems are invisible in staging, invisible in load tests, and only surface under the specific combination of data, concurrency, and access patterns that real users produce. Here is how to find them before they become incidents, and how to diagnose them when they do.

Read more

Spring Boot Security Checklist — What to Verify Before Going to Production

Security gaps in Spring Boot applications follow predictable patterns. This checklist covers authentication, authorization, data protection, infrastructure configuration, and the vulnerabilities that survive code review. Work through it before every production deployment.

Read more