This sample shows a simple Dotnet service invocation between a Client and a Server using Dapr, with the Server authorizing requests from the Dapr sidecar using an API authentication.
You can generate any token you want. For this example, we'll use an openssl generated token. Set the token as an environment variable:
On Linux:
export APP_API_TOKEN=tZL3XdZQoLLWfLHn0UPWEg==
On Windows:
set APP_API_TOKEN=tZL3XdZQoLLWfLHn0UPWEg==
Take the token you generated for Dapr and give it to your app. In your code, you will compare the token that Dapr sends you with the one your app has.
On Linux:
export MY_APP_TOKEN=tZL3XdZQoLLWfLHn0UPWEg==
On Windows:
set MY_APP_TOKEN=tZL3XdZQoLLWfLHn0UPWEg==
cd Server
dapr run --app-id routing --app-port 5000 -- dotnet run
cd Client
dapr run --app-id DaprClient -- dotnet run
When Dapr invoked the Server app, it sent the token to be validated via an HTTP header. The check is done in the following code:
async Task Deposit(HttpContext context)
{
// We try to get the token sent by the caller. If Dapr sent it, it will be populated
context.Request.Headers.TryGetValue("dapr-api-token", out var token);
// Get the token that we will authorize against from an environment variable. You'll want to put this in your program startup.
// On Kubernetes, you will mount the token as an environment variable from a secret.
var apiToken = System.Environment.GetEnvironmentVariable("MY_APP_TOKEN");
// Validate the token we got from Dapr against the one we gave our app
if (token != apiToken)
{
logger.LogInformation("Unauthorized call rejected");
// Return unauthorized
context.Response.StatusCode = 401;
return;
}
logger.LogInformation("Enter Deposit");
Now you can try to call the app directly and see the call fail with 401 unauthorized.
curl -X POST http://127.0.0.1:5000/deposit -H 'Content-Type: application/json' -d '{"amount": 81.00}' -verbose
You can see the curl response returns with 401 unauthorized
and the logs of the Server app shows == APP == Unauthorized call rejected
.
When running on Kubernetes, there are no code changes in the application required. The only thing that changes is how we mount the token.First, create a Kubernetes secret containing the token:
Note: the value of token
needs to be a base64 encoded string
kubectl create secret generic app-api-token --from-literal=token=tZL3XdZQoLLWfLHn0UPWEg==
Next, set the following annotation to configure Dapr to send the token from this secret on every request to your app:
annotations:
dapr.io/enabled: "true"
dapr.io/app-id: "myapp"
dapr.io/app-token-secret: "app-api-token" # name of the Kubernetes secret
You're done!
You can mount the secret you created as an environment variable to your app pod:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
selector:
matchLabels:
app: myapp
replicas: 1
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:1.15.0
envFrom:
- secretRef:
name: app-api-token
ports:
- containerPort: 5000