Key Takeaways
- Fine-Grained Access Control: Learn how to apply permissions to specific users via capability-based tokens, which are crucial when trying to implement least privilege in microservice contexts.
- Multi-Layer Security Model: Understand how shared resources are secured through JWT, OAuth2, and service accounts in a robust multi-level security model that prevents unauthorized access and token misuse.
- Token-Based Authentication: Learn how to issue and verify tokens using effective approaches that will ensure services only see data they should have.
- Risk Mitigation for Shared Databases: Learn some of the best practices that will help you secure databases shared between services and look at some real-world challenges in multiservice data environments of CRM and Trading platforms.
In his article, Mikhail Baranov, Team Lead of Cybersecurity, covered some of the pragmatic ways of implementing fine-grained access control using the multi-layered security approach principles. This article discusses how capability-based tokens, along with other mechanisms, are crucial for least-privilege access to resources, token abuse minimization, and robust user-specific protection of data.
Introduction: The Need for Secure Data Sharing in Microservices
Microservice architectures are very widely adopted, as they allow systems to scale and be designed in a modular fashion; yet, they pose security challenges for data access, particularly for shared databases. In multi-service ecosystems, such as CRM and trading applications, which require access to the same data source, unauthorized access, leakage, and other security risks can easily occur without proper access control.
The article considers a practical solution to such problems using JWTs, OAuth2, and service accounts. It follows the security model on multiple layers. Every system component runs with the least-privilege principle to protect the data from intrusion. In other words, only those services and users that are granted permission should access only the data they should.
Implementing Fine-Grained Access Control in Shared Database Environments
Fine-grained access is necessary in any scenario where several services operate on the same resource but have different and restricted access to it. In this case, capability-based tokens might be granted specific permissions for each service in order to keep a system secure. As such, let’s consider the setup of a CRM and trading service operating on the same database, while each should handle this database with strictly limited access to the data inside.
Step 1: User Authenticates with the Customer Portal
The process starts with the Customer Portal, which handles a request for user authentication. After that, it logs the user into the system and communicates with an Authentication Provider for verification of the user. Upon successful authentication, an OAuth2 session token representing the authenticated subject is returned to the Customer Portal, whereby secure communication of services can take place.
Customer → Customer Portal: “Login with username/password”
Customer Portal → Authentication Provider: “Authenticate the user”
Authentication Provider → Customer Portal: “User authenticated, here’s an OAuth token”
Here, the OAuth2 session token is a temporary credential that verifies the user has authenticated, and is allowed to thereby use the system’s capabilities. This is used in order to acquire a capability token that gives the correct permissions for using the Trading service.
Step 2: Customer Portal Requests a Capability Token from Token Issuer
Once the user has been authenticated, Customer Portal requests from Token Issuer a capability token. In this case this is a fine-grained access token stating precisely what this user shall be able to do with Trading service’s data – e.g., just fetch the user trade history but not give access to other information like order management.
Capability Token Request Example:
It consists of the user ID with a unique identifier, and the access scope (trades:read), which grants authorization to read trading data only. This will be used by the Token Issuer, the entity responsible for generating secure tokens, to construct a capability token appropriate for that user.
Step 3: Generating the Capability Token
To implement least-privilege access, the Token Issuer will create a JWT–the capability token–encoding in it the actual permissions that the user has on the data. Here is an example of how one can develop the capability token in Python using Flask and JWT:
Token Generation Code:
This snippet creates a capability token, which embeds user-specific data access permissions. The capabilities field includes only the functions the user can perform (read access to order_history and trade_execution). The token expires after one hour.
Token Issuer Response:
The capability token is then returned to the Customer Portal, from where it can securely access the Trading service.
Step 4: Customer Portal Sends Request to Trading Service
The Customer Portal uses the capability token to make a request to the Trading Service for the data associated with the authenticated user.
Example Data Request to Trading Service:
The capability token is included in the Authorization header so that the Trading Service can verify the requesting user has appropriate permission against the requested data.
Step 5: Trading Service Verifies Token and Requests Data from Database
Trading Service will verify the capability token to ensure that the request is aligned with permissions set inside the token. Below is a sample Python code to perform verification on this token:
Token Verification Code:
This code makes sure the token is valid and not expired, with all permissions included. If the user ID does not match or the permissions are not as required, it denies access in order to block unauthorized data access.
Step 6: Database Access and Data Return
Upon verification, the Trading Service uses this authenticated capability token to access the shared database and fetch data only for those resources that are allowed by the token.
Example of Final Data Return to Customer Portal:
The result is then sent back to the Customer Portal, which displays this information to the authenticated user. Such grace in managing permissions secures the guarantee that only user-specific data has been made available while the security of the data and privacy of the user are preserved.
Multi-Layered Security Model: Strengthening Security Across Components
This multi-layered security model leverages the strengths of JWTs, OAuth2, and service accounts, combining them into a robust framework:
- JWTs provide a secure stateless way to transmit user authentication data and service authentication data
- OAuth2 allows for secure access delegation, where one service-the Customer Portal-can act on behalf of the user without divulging sensitive credentials
- Service Accounts implement an additional layer of authentication for the microservices to ensure that they act with controlled permissions.
Each layer forms another protection layer such that even when one is breached, the rest protect the integrity of the system.
Summary
This approach provides a way to securely manage fine-grained and user-specific access in a multi-service architecture with a shared resource base. Only authorized users can access their data while mitigating risks of unauthorized access. This kind of architecture ensures least-privilege access across microservices in an effective manner. It therefore guarantees that data access shall be secure and compliant.
About the Author
Mikhail Baranov
With over a decade of cybersecurity experience, Mikhail has designed and implemented several global security infrastructures protecting in excess of $500 million in financial transactions every year. His work in custom solutions, such as bot mitigation and secure code reviews, has reduced cybersecurity risks by as much as 45%, enhancing operational efficiency across international organizations.