By extending zero-trust principles with continuous access management to your Azure AD authentication flows, you can protect your organization against a variety of risks that arise from attackers unauthorized requests against your protected Azure AD applications.
What is Azure AD
Azure Active Directory (Azure AD), and now renamed in 2023 Microsoft Entra ID, is a cloud-based identity and access management service. Azure AD enables organizations to manage identities and protect sensitive resources such as applications, infrastructure, and IT systems such as Microsoft 365, the Azure portal, and many more custom and SaaS applications. For more information visit this page.
Continuous Access Management
Continuous access management is the combination of methods, technologies, and business processes used to manage access to applications, infrastructure, or data. Continuous Access Management uses a dynamic and real-time access check for every request made by a user, device, or application to a resource provider (e.g., application, microservice, database).
Continuous Access Management for Azure AD
Azure AD supports coarse-grained authorization (i.e. RBAC), attributed based access control (ABAC) , and conditional access, which provide options for controlling access to resources. With this said, these approaches are limited to the signals being evaluated and the limitations of their integration with Azure AD.
For instance, conditional access is dependent on a variety of environment signals being evaluated by the conditional access rules defined in Azure AD. Some of that environment information and signals come from business systems and data stored and managed outside of Azure AD. These different authorization data sources are important to make a fine grained authorization decision based on the current state of the user’s relationship to the organization’s protected assets. Business requirements may require advanced authorization logic that requires dynamic data and request context information that is found outside of the Azure AD authentication and beyond conditional access evaluation flows.
With SGNL, access administrators and developers can externalize contextual and real-time access management decisions to a central policy engine. With SGNL, administrators set policies that take effect across all assets.
Here are some reasons why implementing continuous access management for Azure AD protected applications make sense:
- Enhance conditional access with external real-time signals - Using business context signals in policy with SGNL (no pun intended), identity and security teams can ensure access to protected assets takes into account their user’s entire identity profile and associated relationships to IT assets using graph-based relationship modeling. By leveraging the SGNL policy engine to externalize access decisions, you can ensure authorization decisions are taking into account a complete view of your business, using the most up-to-date business context data.
- Easily extend the Azure AD login flow - Halt the Azure AD login flow based on authorization decisions made using business context. This post will show you how to implement a custom authentication extension for managing access to protected applications, and optionally insert claims into the ID token sent to the final application. You can also combine this capability with the continuous access evaluation profile (CAEP) for processing event signals such as session revocation and credential changes implementing a real-time layered security approach.
- Simplification of policy management - SGNL simplifies the creation, management, and auditability of enterprise authorization policies. By using the SGNL policy builder, an access administrator can pick and choose reusable policy snippets that can be used across applications and systems. See the sample human readable policy in the How Does SGNL Work section.
Using SGNL For Azure AD
With SGNL, access control is enforced consistently and easily across all Azure AD protected services using Azure AD custom authentication extensions and SGNL human-readable policies. By integrating SGNL with the Azure AD authentication flow, you can enhance existing Azure AD / Entra ID authentication, authorization, and conditional access decisions with authorization decisions made with a complete view of business context and policy. Azure AD and SGNL together, help significantly reduce security risks and exposure, while promoting easy to understand and maintain access policy.
- Business Data Driven Continuous Access Management - Any changes recorded in an organization’s business systems of record are automatically and rapidly reflected in the Azure AD authentication flow.
- Real-time Audit and Comprehensive Reporting - With SGNL, all access decisions are logged centrally with the policies that contributed to the decision to grant or deny access.
- Centralized Human-Readable Policies - Policies using reusable snippets enable policies to scale with manageability and consistency across the application ecosystem. SGNL‘s reusable snippets can be reused in multiple authorization policies across apps and systems. This allows for easier maintenance, time savings, and broader coverage for an authorization policy.
- Consistent Authorization Decisions Across all applications - SGNL provides the same access decisions consistently across frontend and backend application frameworks because they are based on centrally managed policies.
- Contextual Authorization Decisions - Any access decision is determined considering the context of the request coming from Azure AD custom authentication extension, which keeps the original request context intact.
With SGNL, you can enhance your Azure AD / Microsoft Entra ID access management for your protected applications and provide consistent, fine-grained decisions that are based on easy to understand and implement human readable policies.
Solution Approach
The solution consists of a sample Microsoft (single page application), Azure AD custom authentication extension, the SGNL access service API, graph directory, data ingestion adapters, and human-readable policy used for making authorization decisions. A custom authentication extension is configured to send authorization requests to the SGNL access service via the SGNL REST API as part of an Azure AD IDP authentication login flow. The SGNL access service responds to the authorization query sent by the custom authentication extension with an allow or deny decision considering the context of the authorization request sent by Azure AD. For example, context may consist of the principal making the request, IP Address, the action (e.g. access, update, create, custom action, etc.) and protected asset. If the request is denied, the authentication extension returns a ObjectResult(“Unauthorized to access resource, by SGNL.”) { StatusCode = 403} to Azure AD which stops the OAuth 2 / OIDC authentication request flow (Azure AD will not generate an id token for the user) and redirects to the sample application with an error message.
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 CMDB, ITSM cases, tickets from JIRA, or customers from a CRM (e.g., Salesforce). Applications or protected systems (i.e. API gateways, application servers, web servers) make authorization calls via control points (a.k.a policy enforcement points), SDK, or REST API to the SGNL policy engine. The policy engine calculates an authorization decision (allow or deny) and returns the decision to the control point or application.
In this post, we use Azure AD as the identity provider and user system of record. Salesforce is the CRM sales management system of record. The user’s real-time location (e.g. State, City), SFDC account , and opportunity assignments are used to make the allow or deny decisions.
This post uses a simple single page application provided by Microsoft as an example for inspecting the id token returned to the application after a successful authorization decision made by SGNL in conjunction with the Azure AD authentication extension.
An example of a real human-readable policy for demonstrating the custom authentication extension
This policy checks if the Azure AD principal is an authenticated Azure AD principal, is in the correct location based on IP Address and has valid assigned accounts in Salesforce. If this policy matches, then the SGNL access service returns allow, otherwise the response will be denied and the custom authentication extension returns a ObjectResult(“Unauthorized to access resource, by SGNL.”) { StatusCode = 403} and no id token is generated.
Sample Request Flow
When a user authenticates with Azure AD, a custom authentication extension (HTTP Trigger) is triggered. The HTTP trigger calls the SGNL access service API with an authorization query (see sample code on how to formulate the query objects). If the extension receives an allow, it returns an OkObjectResult with the contents of some optional claims. The Azure IDP then creates the id token for the user and redirects to the jwt.ms application for decoding. If the SGNL authorization decision is denied, then the custom extension HTTP Trigger returns a ObjectResult(“Unauthorized to access resource, by SGNL.”) { StatusCode = 403};
- The user initiates an authentication request via a browser.
- Azure AD IDP authenticates the user.
- Once the user is authenticated, the custom authentication is triggered and the HTTP trigger sends an SGNL authorization query to the SGNL access service.
- (A) If the SGNL policy matches, the access service returns an “Allow” decision to the HTTP trigger. (B) If the SGNL policy does not match, the access service returns a “Deny” to the HTTP Trigger.
- (A) If the decision from the SGNL access service is “Allow”, then the HTTP trigger sets an “OKObjectResult” and allows the authentication extension to continue normally. The Azure IDP then generates an id token and sends it to the sample jwt.ms application. (B) If the decision from the SGNL access service is “Deny”, the HTTP trigger sets an ObjectResult(“Unauthorized to access resource, by SGNL.”) { StatusCode = 403}. The Azure IDP then sends an error back to the jwt.ms application.
Authentication Extension Sample Code
The following code snippet is an example implementation of the Azure AD custom authentication extension for calling the SGNL access service API.
You can download the full C# custom authentication extension example from the SGNL examples repository.
Code snippet from the custom authentication extension HTTP Trigger
#r "Newtonsoft.Json"
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Text;
public static async Task < IActionResult > Run(HttpRequest req, ILogger log) {
log.LogInformation("SGNL custom authentication extension HTTP trigger. Calling SGNL API...");
// Get request body.
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
// Deserialize request body into JSON.
dynamic data = JsonConvert.DeserializeObject(requestBody);
// Extract the relevant query fields to construct SGNL query from the request body.
string principalId = data?.data.authenticationContext.user.userPrincipalName;
string ipAddress = data?.data.authenticationContext.client.ip;
string assetId = data?.data.authenticationContext.clientServicePrincipal.appDisplayName;
// Read the correlation ID from the Azure AD request. This ID is sent back as part of the custom claims.
string correlationId = data?.data.authenticationContext.correlationId;
// Instantiate new query class with action and protected assetid. Note: You can instantiate mutliple query objects to be serialized into JSON.
var query = new Query {
action = "access",
assetId = assetId,
};
// Instantiate new AzurePrincipal class with the principal.
var azurePrincipal = new AzurePrincipal {
id = principalId
};
// Initialize query array, and add queries to be send to the SGNL access service.
var queryArray = new Query[] {
query
};
// Build final request object to be serialized into JSON before sending to the // SGNL access service.
var sgnlRequest = new SGNLRequest {
principal = azurePrincipal,
ipAddress = ipAddress,
queries = queryArray
};
// Serialize sgnlRequest into JSON.
string postData = JsonConvert.SerializeObject(sgnlRequest);
// Uncomment the line below to print the postData to the Azure function log.
// log.LogInformation(postData);
// Create a request for the SGNL Access API
WebRequest request = WebRequest.Create("https://access.sgnlapis.cloud/access/v2/evaluations");
request.Method = "POST";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Set the ContentType property of the WebRequest.
request.ContentType = "application/json";
request.Headers["Authorization"] = "Bearer {SGNL protected system token}";
// Get the request stream.
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
// Get the response.
WebResponse response = request.GetResponse();
dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
// Read the content
string responseFromServer = reader.ReadToEnd();
dynamic responseData = JsonConvert.DeserializeObject(responseFromServer);
// Get the authorization decision from decision array.
string decision = responseData?.decisions[0].decision;
// Uncomment line below to print out the SGNL API decision to the Azure function log.
// log.LogInformation(decision);
// Close reader, data stream, and response.
reader.Close();
dataStream.Close();
response.Close();
// Determine whether to stop the login flow or continue based on authorization decision.
if (decision == "Allow") {
// Allow the login flow to continue.
// Optionally setup claims to return to Azure AD and application.
ResponseContent r = new ResponseContent();
r.data.actions[0].claims.CorrelationId = correlationId;
r.data.actions[0].claims.ApiVersion = "1.0.0";
r.data.actions[0].claims.DateOfBirth = "01/01/2000";
r.data.actions[0].claims.CustomRoles.Add("Customer Service");
r.data.actions[0].claims.CustomRoles.Add("Support Agent");
return new OkObjectResult(r);
} else {
// return forbidden with custom message
log.LogInformation("Access denied, returning ObjectResult with { StatusCode = 403}");
return new ObjectResult("Unauthorized to access resource, by SGNL.") {
StatusCode = 403
};
}
}
Responses
Access Allowed
If the custom authentication extension allows the login process to continue, Azure AD continues with IDP authentication request flow to the sample jwt.ms application with the id token. The sample application then decodes the id token and displays it’s contents.
Access Denied
The jwt.ms application will display an error message when the authorization decision is denied. You can view the sample HTTP Trigger invocation, and you will see a success message but with a 403 forbidden result code sent back to Azure AD from the custom authentication extension / HTTP Trigger.
Configuration
For steps to install, test, and configure the custom authentication extension visit the SGNL examples Git repo’s readme file.
Conclusion
Using SGNL for managing access to your Azure AD / Entra ID applications, especially high-risk APIs and data - organizations can reduce risk, security administrators can minimize 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.