The second important process in a secure system architecture is authorization, aka AuthZ. In the digital world not just the end users have an identity but the services also do. With the introduction of the OAuth 2.0 standards we have defined ways of implementing authorization in our systems. As always, my story is going to be a little different from then normal!. You will get to see a flow which involves 3 flavors of AuthZ.
1. User-Access Delegated Authorization
The most common version is the one that involves the end-user authenticating with an Identity System, completing the authorization by providing consent or rights to the client that he/she uses to reach the resource server. Common clients used in this flow are the apps that run in your browsers and smart phones. With the advancements in the cyber security to battle all the latest attacks, the implicit-grant flow has been marked as a “Do-Not Use” variation in OAuth and is said to be obsolete(at least according to the latest RFCs).
One misnomer of this flow is the practice of storing the application credentials (the client Id) in the application configuration files and the access tokens in the browser’s local or session storage. The configuration settings are viewable in plain text form (coz they are stored in js files that are downloaded by the browser) and the access tokens become accessible if you have accepted malicious cookies or malware programs that can mine your system for sensitive information. I am guilty of implementing this solution myself. Wouldn’t do this again :) . The suggested best practice is to use Auth Code +PKCE (Proof key for code exchange). However one beautiful thing that I learned to address issues in this flow is to adopt and implement the “Backend for FrontEnd” pattern. This involves having a service that runs in a web server that acts as the Auth proxy for the application that serves the end-users but have the security risks stated above.
To understand this pattern and how the BFF/Auth microservice works, read from Scott Brady’s articles or posts on OAuth 2.0. This clip is from his course in Pluralsight. https://app.pluralsight.com/course-player?clipId=cb2f8a3e-ed46-4869-88c8-ce4c691b6a06
The Auth service now becomes a proxy and interacts with the Identity system (Azure Active Directory is an example of IAM system in azure cloud) to help the user complete the AuthN, receive the Auth Code, exchange the code for ID and Access Tokens and handle the token renewal. A few key things to notice are
- use of same-site cookie to protect the Auth service and have it accessible only from the apps in the same domain
- the token issued by the identity system is for the Auth service. In an usual case the token would be for the user’s app and the AUD would directly be the resource(s) that the user is entitled to access. This is done so that the Auth Service can now act on the user’s behalf.
- The user’s application client-Id and the tokens would now be stored in the Auth service’s memory or a light-weight cache service. This ensures that the client-Id and the tokens are not accessible to the end-users and attacks that involve mining data in browser’s memory
2. Token for Token — An Exchange mechanism
If you had spent some solid time examining and self-introspecting a JWT token, you would know that the “aud (audience)” field would be the service that hosts the resource, a resource server in common terms. In the flow discussed in the previous section, the token was issued for the Auth Service so that the auth service can now handle the user requests for the downstream services too ( a common design called a gateway pattern). How does that work though??
When a user requests data from a downstream microservice ( say product-catalog) and the microservice is protected i.e. accessible only from a selected set of services and not open to the internet, a token that is presented to the service now needs to its Id as the targeted audience and should have come from the BFF. Also the token should carry information that the Gateway/BFF is acting on the user’s behalf. To accomplish these requirements, the BFF exchanges the user’s access token for a new access token that provides the bearer of the token rights to reach the downstream service.
To understand this in detail read the amazing article by Scott Brady on the OAuth delegation patterns — OAuth 2.0 Token Exchange . One important thing to notice in this flow is the use of a new grant-type,
3. Managed Identity — Service Identity
In an end to end flow not all services accept tokens from an user delegated application. Sometimes the communication is between 2 downstream microservices or between a microservice and a message bus. In either of these cases, the “caller” needs to present its own identity and should have been provided access permissions to access the “called” service/message bus.
A managed identity is actually an Azure IAM term. AWS and GCP should have similar concepts though. A service will be provided its own identity and also access rights (RBAC- Role Based Access Control) to selected services. If you want to read more about managed identities, read my post
Azure Managed Identities- the How
Some of the Microsoft-Azure developers might have used Azure Managed Identities and the rest might not have. Do you…
The scenario depicted in this picture, has a service enabled with managed identity sends a message to a service bus queue. The receiver of the messages is another service that also has its managed identity enabled. The RBAC provides the sender with the privileges to only SEND to the bus and the receiver with privileges to only RECEIVE from the bus. The Bus validates the sender’s and receiver’s tokens to establish the trusted connection (Authorization and not the mTLS :))
This flow has 3 parts
- User completes AuthN and AuthZ to get into the system
- The BFF/Gateway performs a token exchange when the user requests data from a downstream service (e.g. a REST call that can synchronously return a response in the same context)
- User initiates a request that involves a service (after passing through the gateway) accessing another service/storage that has been protected and the caller uses its managed identity
That’s all in this story folks. Happy Learning!
For further reading
OAuth Delegation Patters — by Scott Brady
Microservices Security (an exhaustive coverage)