What Are Custom Applications
Custom applications, also known as “home grown” applications, are designed, developed, and deployed for specific organizational needs. These applications are not provided by a generally available product or service which are from a third party provider, but rather are written from scratch using traditional programming languages (e.g. Java, Go, Node.js, C#,C) and user interface frameworks (e.g. REACT, Angular).
Teams frequently build home grown applications for transacting with sensitive data like billing, customer data, and employee information. With the high-value and high-risk nature of this data, compounded with the lack of pre-built and cost of custom-built security for these applications, identity teams find home grown applications a critical piece of a company’s landscape for managing access.
Externalizing Access Management
Continuous access management must be considered as a part of an overall zero trust security strategy for custom application development. Here are some points to consider when attempting to externalize access management for a custom application:
- Access is more than just a one time authorization decision - Review your security requirements and strategy for your custom applications. In many cases custom applications are directly tied to specific business processes and requirements that need a dynamic way of allowing access. Identify the areas of the application’s authorization model that can be delegated to an external authorization platform. For example, moving from an RBAC approach to a relationship based authorization model. It may make sense to externalize the new authorization model to be able to reuse the policy across multiple application targets.
- Authorization also applies to the authenticated session in real time - In most highly transactional custom applications, the application should check the state of the user’s session on each access request. This session may be augmented with events driven by identity providers such as a change of credential, session revocation, token claim change, assurance level change, and device compliance change. See the Continuous Access Evaluation Profile (CAEP) draft for more considerations on continuous evaluation details.
- RBAC is not sufficient for custom applications - RBAC works great for static coarse-grained authorization and a small set of protected resources, but in most cases, custom enterprise applications need dynamic, fine-grained permissions to prevent unauthorized access. See what the Open Worldwide Application Security Project (OWASP) authorization cheat sheet says about adopting other models to help solve fine- grained authorization, robustness of policy, and speed.
- Authorization is way beyond authentication - When designing a custom application, it is important to keep a distinction between authentication and authorization. Authentication is the process of identifying a user, device, or application (a.k.a principal) using a credential. Just because a principal is authenticated, does not mean that principal should access all of the available data in a system. This is where authorization comes into play. Authorization allows a security developer to enforce access decisions based on principal and additional context related to the resource request.
- It’s about least privilege not convenience - It is common to see audit findings regarding over-provisioned users or users with permissions accumulated over time. Roles are commonly used to manage access in homegrown applications, but the burden of building and maintaining roles tends to compromise on the granularity of control with overarching permissions to applications and data. While this is convenient from a permissions management perspective, it introduces massive security risk to the organization.
- Simplify authorization logic - A small authorization logic error or misconfiguration can lead to serious vulnerabilities and breaches. It is always better to look towards simplifying your custom authorization logic by centralizing access management in a controlled policy engine that handles the authorization logic for your team across all your homegrown applications.
For more considerations and best practices for including security in your application development process visit the OWASP authorization cheat sheet.
Continuous Access Management
Continuous access management is the combination of methods, technologies, and business processes used to manage access to applications, infrastructure, or data using a dynamic and real-time authorization check for every request made by a user, device, or application to a resource provider (e.g., Application, Microservice, Database).
This high level diagram depicts relationships between the request client, resource provider, and continuous access management services. This example shows a resource provider protected by a continuous access management enforcer or control point.
In cases where a control point or enforcer is not available, the resource provider may call the continuous access management policy engine directly for a real-time authorization decision.
Using SGNL For Custom Applications
SGNL provides continuous access management by building a dynamic graph of sanctioned enterprise activity through continuous data ingestion from systems of record. With SGNL, access control is enforced consistently and easily across all protected services, applications, and data using human-readable policies. By using SGNL for custom applications, you can externalize access management to a scalable and modern platform, minimize security exposure, and implement a truly least-privileged approach to securing your custom applications. Here are five benefits of using SGNL:
- Business Data Driven Continuous Access Management. Any changes recorded in an organization’s business systems (e.gServiceNow, Salesforce, HRIS) of record are automatically and rapidly reflected in the custom application access decisions without changing proxy policy or configuration.
- Real-time Audit and Comprehensive Reporting. With SGNL, all custom application access decisions are logged centrally with the policies that contributed to the decision to grant or deny access.
- Centralized Human-Readable Policies. Human-readable policies using reusable snippets enable organizations to scale policies without losing manageability and consistency. SGNL allows you to create reusable snippets, and reuse them in multiple authorization policies. This allows for easier maintenance, time savings, and broader coverage for an authorization policy.
- Consistent Authorization Decisions Across All Services. Custom applications using SGNL, provide the same access decisions consistently because they are based on the centrally managed policies.
- Contextual Authorization Decisions. Any access decision is determined considering the context of the request coming from the custom application at runtime. The request context received from the custom application is kept intact through the SGNL access service and back to the custom application.
Using SGNL for your custom applications, you can externalize authorization to a continuous and centralized authorization solution, minimize security exposure, and implement a fine-grained least-privileged approach to securing your applications.
Solution Approach
The solution consists of a SGNL policy engine (integration via the access service API), graph directory, data ingest adapters, and human-readable policy used for making authorization decisions. A custom application is configured to send authorization requests to the SGNL access service via the SGNL SDK or REST API. The SGNL access service responds to the custom application with allow or deny decisions considering the context of the authorization request. For example, context may consist of principal data, asset identifier, or network IP address. If the request is denied, the application sends the appropriate response to the caller.
Logical Diagram Of Solution
How Does SGNL Work
SGNL continuously ingests data from systems of record to a central graph directory via resilient and performant data ingest adapters. This data includes identity data, such as users and groups, and any relevant data required to define access policies, such as ITSM cases, tickets from JIRA, or customers from a CRM.
In this post, we use ServiceNow and Azure Active Directory as the Systems of Record. Azure AD is our Identity Provider system of record, and ServiceNow provides the assigned and active case for the user.
Once the system of record data sources are set up, administrators can quickly author and manage human-readable policies based on the ingested data for granting or denying access to applications, APIs, and sensitive data. By implementing a centralized approach, SGNL provides consistency in centralized policy management, audit logging, and reporting across all assets an organization desires to protect (including APIs).
Instead of implementing complex custom logic in your custom application to evaluate access, you use SGNL to select policy snippets from the user interface and graphically build a human-readable policy. This ensures that any request to the custom application is evaluated against the latest data ingested from systems of record and the policies defined in SGNL.
An example of a real human-readable policy for protecting a custom application
This policy checks if the principal is a valid Azure AD user, belongs to the engineering organization, and is currently on call. SGNL applies this policy to an incoming access request from the custom application. The application sends the employee identifier, the action (e.g. Modify) they want to take on a case and the case identifier. SGNL will return an “Allow” decision if the employee belongs to the engineering organization and is on-call or a “Deny” decision if either of those conditions fail to match.
Sample Request Flow
A developer may simplify authorization logic for a custom application by delegating complex authorization logic to the SGNL policy engine. The authorization decisions are made by the SGNL policy engine which is calculating policy against continuously ingested data from various systems of record (e.g. Azure AD, ServiceNow). In addition, SGNL automatically creates the appropriate relationships for that ingested data, and it calculates multiple human-readable policies in milliseconds. Below is an example sequence diagram for a custom application authorization request.
- A principal (e.g. user, device, service) makes a request to the custom application for a resource.
- Custom application gathers request context information (e.g. Azure AD principal id), IP Address, asset identifiers (e.g. case identifier), action (e.g. Modify) and sends an authorization query request to the SGNL access service API.
- The SGNL policy engine calculates the human-readable policies associated with the custom application in milliseconds and determines a final decision (allow/deny). There is no extra configuration or modification for the policy engine for benefiting from the performant policy calculations and response.
- (A) If the decision made by the access service is allowed, the access service responds with an allow response. (B) If the decision is denied, the access service responds with a denied response.
- (A) If the custom application receives an allow decision, it then responds back to the caller with the requested resource. (B) If the custom application received an denied decision, it then responds back with a 403 forbidden.
Sample Code
In the following Node.js sample code, the application implements a customAppEvaluateAccess() function that is passed an instance of a SGNL client (returned by the getClient() function), the principalId, the case id and the action (e.g. Modify) being performed by the employee. These are passed to the accessEvaluation() function which constructs the queries using helper functions in the SGNL SDK, and calls SGNL’s Access API using the instance of the SGNL client.
Based on the example policy in this post, the API either returns an allow if the user can modify a case or deny if the user does not meet the policy conditions. The custom application can process the response appropriately - either log and allow the access to go through, or log and deny the request.
Sample Node.js
const sgnl = require("sgnl");
// Build the SGNL Client
sgnlClient = getClient("<<Insert your Protected System Access Token here>>");
// Call SGNL Access API with principal, asset and action to get access decision
result = await customAppEvaluateAccess(
sgnlClient,
"alejandro.bacong@wholesalechips.co",
"Case-4321",
"Modify"
);
// Async function to access evaluation using the client
async function accessEvaluation(client, principal, assetId = "", action = "") {
const p = new sgnl.Principal(principal);
const queries = [];
if (assetId && action) {
queries.push({ assetId, action });
}
const accessRequest = new sgnl.AccessEvaluationRequest(p, queries);
const opts = { accessEvaluationRequest: accessRequest };
return client.accessEvaluation(opts);
}
// Function to get the client instance with the provided access token
function getClient(accessToken) {
const defaultClient = sgnl.ApiClient.instance;
defaultClient.basePath = "<<Insert your Access API URL>>";
defaultClient.authentications["bearerAuth"].accessToken = accessToken;
return new sgnl.AccessEvaluationClient(defaultClient);
}
// Example usage: Call customAppEvaluateAccess() from your custom app code
async function customAppEvaluateAccess(client, employeeId, caseId, action) {
try {
const result = await accessEvaluation(client, employeeId, caseId, action);
console.log(result);
return result;
} catch (error) {
console.error("Error:", error);
}
}
Sample JSON Request
The SGNL SDK sends the following JSON request to the SGNL Access API Service.
{
"principal": {
"id": "alejandro.bacong@wholesalechips.co"
},
"queries": [
{
"assetId": "Case-4321",
"action": "Modify"
}
]
}
Sample JSON Responses
SGNL’s Access Service responds with a decision in a JSON format to the SDK. The Allow and Deny decision samples are for illustration purposes.
Allow
{
"decisions": [
{
"assetId": "Case-4321",
"action": "Modify",
"decision": "Allow"
}
],
"evaluationDuration": 13,
"issuedAt": "2023-07-20T23:47:06.644306908Z",
"principalId": "alejandro.bacong@wholesalechips.co"
}
Deny
{
"decisions": [
{
"assetId": "Case-1234",
"action": "Modify",
"decision": "Deny"
}
],
"evaluationDuration": 23,
"issuedAt": "2023-07-20T23:44:23.912490563Z",
"principalId": "alejandro.bacong@wholesalechips.co"
}
Batch Access Evaluations
SGNL Access Service supports multiple asset and action queries for a principal. The following JSON response is an example of the response sent for two queries for the principal in the same authorization request.
{
"decisions": [
{
"action": "Modify",
"assetId": "Case-4321",
"decision": "Allow"
},
{
"action": "Modify",
"assetId": "Case-1234",
"decision": "Deny"
}
],
"evaluationDuration": 16,
"issuedAt": "2023-07-20T23:50:14.324374185Z",
"principalId": "alejandro.bacong@wholesalechips.co"
}
For more information on protecting your custom applications and view a step by step guide, visit our SGNL SDK help page.
Conclusion
Using SGNL for custom applications - especially those homegrown applications that contain high-value or high-risk data - organizations can reduce risk, developers can reduce authorization logic complexity, and teams can centralize access management policy in a single platform for making complex, consistent, and continuous authorization decisions.
Schedule time with a SGNLer to see how all this can work in your context.