In a distributed system, every service interaction requires establishing trust between the communicating parties. Whether it’s applications talking to each other, or an application using infrastructure services like a database or message broker, it’s all built on trust. Trust that the other service is who they are claiming to be - trust in their identity.
This is why applications need a secure, verifiable, efficient, and portable way to express their identity to each other.
Application Identity
An application identity is a digital representation of an application that encapsulates attributes and context about the expected use and behaviour of the application. You can use the application identity to grant access to certain data and services whilst aligning with the principal of least privileged access. The application identity is also a unique identifier that can be used to reliably associate contextual and operational data during the application’s lifecycle.
Traditionally, we’ve relied on secrets, such as API keys, passwords, or static tokens in the absence of a native application identity. Possession of the secret itself was treated as proof of identity: if the application could present the secret, it was assumed to be the rightful identity holder.
The problem is that secrets are fragile and risky:
- They must be stored, distributed, and rotated safely.
- If a secret is leaked, stolen, or misconfigured, an attacker can impersonate the application without detection.
- Secrets are often shared so don’t uniquely identify each application.
Because of these weaknesses, secrets alone are an unreliable foundation for identity in modern distributed systems.
In contrast, a verifiable identity is a cryptographically provable claim about an application’s identity. Unlike secrets, it does not rely on parties simply sharing the secret value itself. Instead, identity is demonstrated through proof. The proof can only be issued by the holder of the secret and can be independently verified. This separation of proof from the underlying secret ensures that trust can be established without using the secret value directly, reducing the attack surface and enabling short-lived, easily rotated credentials.
Credentials
Proofs still need a way to be transported and interpreted between systems. That’s where credentials come in. A credential is a standardized, portable container for identity proofs. It represents who the application is in a format that other services can understand and validate.
Two widely used credential containers are:
- X.509 certificates: A structured digital document that represents an application’s identity by including its public key along with information, such as the issuer, subject, and validity period. The certificate is signed by an issuer to prove its authenticity.
- JWT (JSON Web Tokens): A compact, self-contained token representing an application’s identity and associated claims in a standardized JSON format. It can include metadata such as permissions, roles, or other contextual attributes. The token includes a signature by an issuer to prove its authenticity.
Credential Verification
When a service needs to verify a credential, it relies on cryptography. There are two main approaches:
- Symmetric verification: Both the Issuer and verifier share a private key (AES/HMAC-SHA256), sometimes known as a symmetric key or shared secret. The verifier uses the same private key as the issuer to check the authenticity of the proof (e.g. HMAC-signed JWT). Anyone with possession of the private key can issue as well as verify signatures. This means it’s very important to distribute the private key securely.

- Asymmetric verification: The issuer signs the proof with a private key (RSA/ECDSA), but the verifier uses a derived public key to check the proof's authenticity. The private key remains private, and the public key can be distributed in a scalable and secure manner. This approach distinguishes clearly between those who can issue and those who can only verify.

The enhanced security model of asymmetric verification makes it the most suitable approach to building a modern distributed identity system. In this model, we have an identity provider (IDP) or issuer that signs credentials for applications. We then distribute the trust anchors (public keys) to any external parties who need to independently verify those signed credentials.
Cloud Managed Identities Limitations
Cloud platforms provide various forms of Managed Identities via their IAM services:
These identities allow applications running in the cloud to transparently acquire credentials to authenticate to services without using secrets. This makes it straightforward to write, deploy, and run applications in the cloud that securely access cloud services.
However, they come with limitations:
- They are tied to a specific cloud provider and runtime environment. You cannot directly move these identities across clouds (without federation), on-premises environments, or use them for local development setups.
- In many cases, the identity is actually assumed by the host of your application (e.g. virtual machine) and not the application itself. This means access to the credential may not be scoped specifically to your application and can mean you are writing policy in terms of infrastructure and not applications.
- The identity is not natively part of your inter-service communication. For instance, when your apps are calling each other, they are not presenting and using each other's AWS identity.
Universal Application Identity
Wouldn’t it be better if applications could obtain a secure, verifiable identity that is based on a standard, interoperable structure, universally accessible, and independent of where it is running?
A single identity that is unique to your application and can be securely verified from anywhere.
In other words, a universal application identity.
Secure Production Identity Framework for Everyone (SPIFFE)
SPIFFE is a CNCF graduated project that defines a standard framework for assigning strong, portable identities to software workloads (applications). Each workload is issued a SPIFFE ID, which looks like a URI:
spiffe://trust-domain/workload-identifier
That SPIFFE ID is the identity. It is stable, portable, and belongs to the application, not the infrastructure it runs on. The trust domain is used to establish the scope of the root of trust which could represent an individual, organization, environment or department.
To make that identity useful, SPIFFE defines Verifiable Identity Documents (SVIDs) — short-lived cryptographic credentials that represent the identity.
For more information on SPIFFE, please refer to the project’s documentation.
SPIFFE in Practice with Dapr
Dapr’s identity model is built on SPIFFE. When running an application with Dapr:
- The Dapr Sentry control plane service acts as a Certificate Authority, issuing signed credentials with an embedded SPIFFE ID to Dapr sidecars and other control plane services.
- Dapr sidecars use their credentials when establishing mutual TLS for secure Dapr-to-Dapr calls.
- Dapr sidecars can also use their credentials when authenticating with external services and cloud providers via Dapr components.
In Dapr, the SPIFFE IDs include both a namespace and the app id name.
spiffe://trust-domain/ns/<namespace>/<app-id>
Prior to Dapr 1.16, the only supported credential format was X.509 certificates. As of Dapr 1.16, you can opt-in to allowing Dapr Sentry to issue JWTs to Dapr sidecars in addition to the X.509 certificates. Both of these credentials represent the same underlying SPIFFE ID, but have specific use cases:
- The X.509 certificate is the most secure representation and is used for mTLS between Dapr sidecars. It can also be presented to external resource providers that support certificate-based authentication, such as AWS IAM Roles Anywhere.
- The JWT is a more interoperable and portable credential for integrating with external resource providers and OIDC systems. It is still secure but can be susceptible to replay attacks if the token is stolen - although steps to mitigate this risk can be taken. In Dapr, JWTs can currently be used with Azure components for federated credential flows.
Trust Distribution
When using asymmetric cryptography, trust anchors must be distributed to all the parties that need to verify identities. This is the mechanism by which the public key material is shared to the verifiers.
Dapr supports two trust distribution mechanisms:
- X.509 trust bundle – The X.509 trust bundle is a set of CA certificates that can be trusted in order to verify the authenticity of any application certificates. The trust bundle is made available within a Dapr installation so that sidecars and control plane services can easily verify each other's certificates. The trust bundle can also be distributed manually to other parties outside of Dapr should they need to verify the certificates.
- JWKS – The JWKS (JSON Web Key Set) is a set of keys that can be trusted in order to verify the authenticity of any application JWTs. The JWKS is made available within a Dapr installation as a configuration file and can be exposed via an OIDC discovery endpoint on Dapr Sentry to allow easy OIDC federation.
Together, these mechanisms provide standard, portable trust anchors for both certificate and token-based credentials. Services don’t need to share secrets; they simply verify against a root of trust using the trust anchors distributed by Dapr.
Using Identity with Dapr
With Dapr, every application gets a verifiable identity out of the box. Dapr makes it easy to then use that identity for application-to-application and application-to-infrastructure authentication and authorization.
Application to Application
Applications can use Dapr’s service invocation API to call methods on each other. Dapr will automatically establish mTLS between the Dapr instances to ensure that only the intended sender and receiver can read the communication. Dapr can also enforce access policies to restrict which applications can call specific methods. These access policies use the app’s SPIFFE ID to guarantee that the identity cannot be spoofed.
Application to Infrastructure
Dapr provides APIs that abstract the application from infrastructure. Dapr is configured to access the infrastructure using Dapr components. Each component will support one or more authentication methods, depending on what is supported by the infrastructure provider.
Dapr supports identity federation for some Dapr components that allow external identity providers to directly trust your Dapr application identity. This enables you to connect to infrastructure without using secrets or tightly coupling to a vendor's identity service.
Identity Federation with AWS
AWS Dapr components can use various authentication profiles to access AWS services. The AWS IAM Roles Anywhere profile enables you to establish a trust relationship between AWS and your Dapr Sentry installation. When the AWS Dapr components are loaded in a Dapr sidecar, they can use its X.509 certificate to authenticate to AWS IAM Roles Anywhere and get an AWS issued credential, typically in the form of a short lived token that will be automatically rotated. This token can then be used to directly access the underlying AWS service.

Identity Federation with Azure
Azure Dapr components can also use various authentication profiles to access Azure services. By using an Azure Federated Identity, you can establish a trust relationship between Azure and your Dapr Sentry installation. When the Azure Dapr components are loaded in a Dapr sidecar, they can use its JWT to authenticate to Azure Entra ID and get an Azure-issued credential, typically in the form of a short-lived token that will be automatically rotated. This token can then be used to directly access the underlying Azure service.

Example using AWS and Azure Identity Federation
Let’s consider how this applies to an example distributed application.
Imagine an Order service that saves orders to an AWS DynamoDB, then makes a remote call to a Payments service, which writes a payment instruction to an Azure Storage Account.
In this very simple example, we need to establish trust between:
- Order service and Payments service
- Order service and AWS
- Payments service and Azure
Fortunately, with Dapr’s universal application identity, this is simple.
Below is a high-level illustration of how this works.
- Dapr is deployed with JWT issuing and OIDC serving enabled.
- Trust is set up from AWS to the Dapr Sentry Trust Bundle and policy is configured to grant access to the Order service’s SPIFFE ID.
- Trust is set up from Azure Entra ID to Dapr Sentry’s JWKS via the OIDC server and policy is configured to grant access to the Payment service’s SPIFFE ID.
- On startup, the Dapr sidecars fetch both an X.509 certificate and JWT from Dapr Sentry.
- The Order service’s Dapr sidecar uses an AWS Dapr component to authenticate to AWS IAM Roles Anywhere and obtain an AWS credential.
- When the Order service receives an order, it uses the Dapr state store API to save it to AWS Dynamo DB, authenticating with its AWS credential.
- The Order service then uses the Dapr service invocation API to remotely call a method on the Payment service. Dapr will use both sidecars' X.509 certificates to establish a mutual TLS connection over which to send the request.
- The Payment service’s Dapr sidecar uses an Azure Dapr component to authenticate to Azure Entra ID and obtain an Azure credential.
- When the Payment service receives the method invocation, it uses the Dapr bindings API to save it to Azure Storage, authenticating with its Azure credential.

For every interaction in this system, it’s the same SPIFFE identity being used, but leveraging different credentials depending on the situation.
To learn more about how to use Dapr’s application identity to access your cloud resources, please refer to the following documentation:
Dapr’s application identity model delivers the following practical benefits:
- Zero-trust by default: Every request is authenticated and authorized.
- No secrets to manage: Short-lived, rotated credentials replace static secrets.
- Fine-grained ACLs: Define access policies in terms of app identities and operations.
- Multi-cloud readiness: Identities travel with the app across environments.
- Unified model: Consistent interoperable identity, available in multiple credential formats.
Distributed systems can no longer rely on static secrets or implicit trust. To build secure, portable, and scalable applications, proof of identity must be verifiable, short-lived, and independent of infrastructure.
With Dapr’s SPIFFE-based model, every workload automatically receives a universal identity that can be used consistently for both application-to-application and application-to-infrastructure trust. By combining X.509 certificates for strong mutual TLS with JWTs for federation and interoperability, Dapr delivers a practical implementation of zero-trust principles without burdening developers with secret management.
The result is an application identity system that is cloud-agnostic, standards-based, and production-ready—helping teams simplify security, reduce risk, and move faster across multi-cloud and hybrid environments.
Stay tuned to find out how Diagrid Catalyst builds on Dapr’s identity model to offer managed universal identity for your applications.
Further reading on application security from the Diagrid team: “Zero Trust Security for Distributed Applications with Dapr” by Alice Gibbons
More information on configuring Dapr’s security stance can be found in the configuration section of the Dapr docs.