Azure API Management Policies and Custom Authentication Flows – Part 4: Advanced Scenarios & Best Practices

Azure API Management Policies and Custom Authentication Flows

Part 4: Advanced Scenarios & Production Best Practices

In this final part of our Azure API Management series, we’ll explore advanced enterprise scenarios, policy testing strategies, performance optimization techniques, and production-ready security best practices.

B2B Authentication Scenarios

<!-- B2B partner authentication with different trust levels -->
<inbound>
    <set-variable name="partnerType" value="@{
        var clientId = context.Request.Headers.GetValueOrDefault("X-Client-ID", "");
        var premiumPartners = new[] { "partner-A", "partner-B" };
        
        if (premiumPartners.Contains(clientId)) return "premium";
        return "standard";
    }" />
    
    <choose>
        <when condition="@((string)context.Variables["partnerType"] == "premium")">
            <!-- Premium partners: Certificate + JWT -->
            <choose>
                <when condition="@(context.Request.Certificate == null)">
                    <return-response>
                        <set-status code="401" reason="Unauthorized" />
                        <set-body>{"error": "certificate_required"}</set-body>
                    </return-response>
                </when>
            </choose>
            
            <validate-jwt header-name="Authorization" failed-validation-httpcode="401">
                <openid-config url="https://premium-partner.com/.well-known/openid_configuration" />
            </validate-jwt>
            
            <rate-limit-by-key calls="10000" renewal-period="3600" 
                counter-key="@("premium-" + context.Request.Headers["X-Client-ID"])" />
        </when>
        <otherwise>
            <!-- Standard partners: API Key -->
            <set-variable name="apiKey" value="@(context.Request.Headers.GetValueOrDefault("X-API-Key", ""))" />
            
            <choose>
                <when condition="@(string.IsNullOrEmpty((string)context.Variables["apiKey"]))">
                    <return-response>
                        <set-status code="401" reason="Unauthorized" />
                        <set-body>{"error": "api_key_required"}</set-body>
                    </return-response>
                </when>
            </choose>
            
            <rate-limit-by-key calls="1000" renewal-period="3600" 
                counter-key="@((string)context.Variables["apiKey"])" />
        </otherwise>
    </choose>
</inbound>

Performance Optimization

<!-- Optimized policy with caching -->
<inbound>
    <set-variable name="cacheKey" value="@("auth-" + context.Request.Headers.GetValueOrDefault("Authorization", "").GetHashCode())" />
    
    <cache-lookup-value key="@((string)context.Variables["cacheKey"])" variable-name="cachedAuth" />
    
    <choose>
        <when condition="@(!context.Variables.ContainsKey("cachedAuth"))">
            <validate-jwt header-name="Authorization" failed-validation-httpcode="401">
                <openid-config url="https://login.microsoftonline.com/{tenant}/.well-known/openid_configuration" />
            </validate-jwt>
            
            <cache-store-value key="@((string)context.Variables["cacheKey"])" 
                value="valid" duration="300" />
        </when>
    </choose>
</inbound>

Security Monitoring

<!-- Security event monitoring -->
<inbound>
    <set-variable name="suspiciousActivity" value="@{
        var userAgent = context.Request.Headers.GetValueOrDefault("User-Agent", "");
        var path = context.Request.Url.Path;
        
        if (userAgent.Contains("curl") || userAgent.Contains("python"))
            return true;
        if (path.Contains("..") || path.Contains("admin"))
            return true;
        
        return false;
    }" />
    
    <choose>
        <when condition="@((bool)context.Variables["suspiciousActivity"])">
            <send-request mode="new" response-variable-name="securityLog" timeout="2" ignore-error="true">
                <set-url>https://security.contoso.com/api/events</set-url>
                <set-method>POST</set-method>
                <set-body>@{
                    return new JObject(
                        new JProperty("eventType", "suspicious_activity"),
                        new JProperty("clientIp", context.Request.IpAddress),
                        new JProperty("timestamp", DateTime.UtcNow)
                    ).ToString();
                }</set-body>
            </send-request>
            
            <rate-limit-by-key calls="10" renewal-period="3600" 
                counter-key="@("suspicious-" + context.Request.IpAddress)" />
        </when>
    </choose>
</inbound>

Production Checklist

Security Configuration

  • ✅ Enable HTTPS only with proper TLS configuration
  • ✅ Implement proper CORS policies
  • ✅ Configure rate limiting for all endpoints
  • ✅ Set up comprehensive logging and monitoring
  • ✅ Configure proper error handling

Performance Optimization

  • ✅ Enable response caching where appropriate
  • ✅ Optimize policy expressions
  • ✅ Use caching for expensive operations
  • ✅ Configure proper timeouts

Final Recommendations

Start Simple: Begin with basic authentication patterns and gradually add complexity.

Security First: Always prioritize security over convenience.

Monitor Everything: Comprehensive monitoring is essential for production.


Azure API Management policies provide a powerful foundation for implementing sophisticated authentication and authorization schemes. The patterns covered in this series will help you build secure, scalable, and maintainable API gateways.

Azure API Management Policies and Custom Authentication Flows

Azure API Management Policies and Custom Authentication Flows – Part 3: Custom Authentication Implementation

Written by:

472 Posts

View All Posts
Follow Me :