Skip to main content

Command Palette

Search for a command to run...

Optimizing Authentication Strategies for Distributed Applications

Updated
3 min read
Optimizing Authentication Strategies for Distributed Applications
V

Hello! I'm a student passionate about becoming a Cloud and DevOps Engineer. I have a solid foundation in AWS Cloud, Linux, Docker, and Kubernetes.

What started as a simple Kubernetes deployment for a Spring Boot app turned into a deep dive into authentication methods when the login suddenly broke after setting up Ingress.

During the deployment of a Spring Boot-based Bank application to a Kubernetes cluster, I encountered an issue.

I deployed the app in a Kubernetes cluster, and I faced a problem.

Problem: Unable to log in after setting up Ingress.

Cause: The Server used cookies for session state.

I was curious about API authentication ways, and a few days back, I started to learn about these:

  • HTTP basic authentication, where credentials (username, password) are base64 encoded and sent with the HTTP header with every request.

  • API key authentication, where the key has limited control and API keys need to be sent with every request as either a Query String, a Request Header, or a Cookie.

  • JWT

  • OAuth and OpenID

This article is about what I learned about JWT (JSON Web Token).

If we take the example of the bank application, for maintaining the state it uses session tokens which were sent to the user via a cookie. With every new request, the client browser would send the session ID stored in the cookie. The server validates the session ID, and if it is valid, the user gets the response.

Our Bank application was deployed in the K8s cluster and was exposed via Ingress. When a user sends a Login request to Ingress, the load balancer forwards the request to a random pod, the user enters the username and password, the server validates the credentials and creates a session, and sends back the session id to the user via cookie.

Sessions are sticky, meaning the server that issues the session id can only be used to validate the user.

Solution: Enabling session affinity can solve the problem, it ensures that all requests from a specific client go to the same pod.

Introduction to JWT

Session token/ID can be verified only with the issuing server, but a JWT token can be used on multiple servers.

It uses a public-private key signing method (private key to sign JWT and public key to verify JWT).

It is very useful in distributed systems and microservice architecture.

Now, consider how the bank app would work if we used JWT instead:

The user sends a login request to one pod (server) and enters the username & password.

The server validates the user, issues a JWT token signed with the private key, and sends it to the user's browser.

When the user requests a different page, the user sends a request to the load balancer, and it forwards the request to any other server (pod).

The server validates the JWT token and serves the content (because all the servers were using the same pair of keys, a token issued by one server can be validated in another).

JWT consists of:

Header: contains info about the type of token, hashing algorithm used, etc.

{

  "alg": "HS256",

  "typ": "JWT"

}

Claim (Payload): contains claims — identity & permissions of the user, token issue time, expiry time, etc.

{

  "sub": "1234567890",

  "name": "John Doe",

  "iat": 1516239022

}

Signature: created from encoded header, encoded payload, and secret (private key).

Signature is unique and reproducible.

HMACSHA256(

  base64UrlEncode(header) + "." +

  base64UrlEncode(payload),

  secret

)