Featured image for 3scale API Management.

 Applying fine-grained access control to APIs is a common enterprise requirement that can be challenging to implement. Encapsulating authorization decisions into the API gateway can quickly become difficult to manage in complex APIs with many resources and access control rules. However, you can externalize API authorization decisions from the API gateway and from your microservices by leveraging Keycloak Authorization Services as a centralized authorization component. Keycloak Authorization Services acts as a policy decision point integrated with 3scale API gateway, which is the central enforcement place to access your APIs.

Integrating Keycloak Authorization Services into your API architecture has many benefits:

  • Centralized control with simplified administration: Organizations have a single point of control for managing access policies with simplified operations, where the administrator can efficiently manage authorization decisions and permissions from a central Keycloak web console gives them the power to define exactly the policies they need without the need for changes in the API gateway.
  • Separation of concerns: Externalizing authorization decisions to a specialized authorization service allows API gateways and API services to remain lightweight and focused on their primary responsibilities.
  • Fine-grained access control: Keycloak Authorization Services supports policy-based access control , allowing for very granular and fine-grained access control policies. This enables precise control over who /when can access what within your APIs.
  • Fast security review: It becomes easier to perform security checks for permissions without knowledge in the API gateway.

This article introduces the Keycloak authorizer custom policy and details how to integrate Red Hat 3scale API Management with Red Hat build of Keycloak Authorization Services to decouple your API authorization policies.

3scale API Management provides a feature that allows users to define custom policies. These policies enable you to enhance the default behavior of the APIcast/gateway.

Keycloak Authorization Services

Red Hat build of Keycloak is based on the Keycloak open source identity and access management solution, which provides features like single sign-on (SSO), user management, OAuth 2.0/OpenID Connect support, and authorization services.

Keycloak Authorization Services provide fine-grained authorization policies that give businesses the ability to control authorizations for all of their services from the Administration Console, enabling them to set the policies they need accurately with the ability to combine different access control patterns such as:

  • Attribute-based access control (ABAC)
  • Role-based access control (RBAC)
  • User-based access control (UBAC)
  • Context-based access control (CBAC)
  • Rule-based access control
  • Time-based access control
Figure 1:Keycloak Authorization Services
Figure 1: Keycloak Authorization Services
Figure 1: Keycloak Authorization Services.

By leveraging Keycloak Authorization Services, organizations can ensure that they have a consistent, powerful, and flexible solution to manage access to their APIs and resources, thereby increasing security while also providing a better experience for developers and end users.

Furthermore developers and administrators can implement complex access control scenarios, from basic role-based access control to detailed, attribute-based access control, and even context-aware policy enforcement. This empowers organizations to enhance their security posture and ensure that users only access the resources they are authorized to use.

Scenario

Imagine we have a course management microservice that exposes REST APIs through 3scale for viewing and deleting course resources that can serve users with two types of roles:

  • Instructor
  • Student

Only instructors are allowed to delete a course; both student and instructor are allowed to view the course resource. In this demo, we are going to implement a basic RBAC access control pattern.

Architecture

The flow is shown in Figure 2 and described below.

High level architecture for the example uses Keycloak for centralized authentication and authorization with 3scale API gateway.
Figure 2: High level architecture for the example uses Keycloak for centralized authentication and authorization with 3scale API gateway.
Figure 2: High-level architecture for the example uses Keycloak for centralized authentication and authorization with 3scale API gateway.
  1. API consumer application hits request to 3scale API product secured by OpenID Connect authentication method with Keycloak.
  2. The gateway redirects the user to the Keycloak authentication page to authenticate and issue a token using OAuth 2.0 authorization code flow.
  3. Keycloak Authorizer Policy extracts resource name and scope from policy configuration based on matching mapping rule of the incoming HTTP request in order to send an authorization request to Keycloak Authorization Services for decision making.
  4. Keycloak Authorization Services replies with an authorization decision.
  5. The gateway will allow or deny the request based on the authorization decision; if the decision is allowed, then the request will be proxied to the upstream service.

In this architecture, the gateway acts as a policy enforcement point (PEP), while Keycloak acts as a policy decision point (PDP) and OpenID Connect identity provider.

Prerequisites

The following resources are necessary to run this demonstration:

  • Red Hat 3scale API Management 2.13 on-premises deployment.
  • Red Hat Build of Keycloak 22.0.

Step 1: Configure Keycloak

  1. In the Red Hat build of Keycloak console, create a realm named 3scale-course-mgmt for a 3scale client, as shown in Figure 3.

    Create a realm named 3scale-course-mgmt
    Figure 3 : Create a realm named 3scale-course-mgmt
    Figure 3 : Create a realm named 3scale-course-mgmt.
  2. Create a client in the realm 3scale-course-mgmt with the configurations of the integration as an identity provider for 3scale.

  3. Next, we'll set up a client within the 3scale-course-mgmt realm, configured to serve as the identity provider for 3scale (see Figure 4).

    Create a client named course-mgmt
    Figure 4: Create a client named course-mgmt
    Figure 4: Create a client named course-mgmt.

    In the Capability config section, make the following adjustments (Figure 5):

    • Turn ON the client authentication. 
    • Turn ON Authorization to enable Authorization Services.
    • Disable the Standard Flow and Direct access grands by unchecking it.
    • After making these changes, click Next and Save.
    configure the client for OIDC identity provider with 3scale
    Figure 5: configure the client for OIDC identity provider with 3scale
    Figure 5: Configure the client for OIDC identity provider with 3scale.
  4. Next, assign roles to the service account for the client using these steps, illustrated in Figure 6:

    • Head to the Service Account Roles section for the client.
    • Click the Assign role button.
    • Choose Filter by client and search by manage-clients.
    • Within the search result section, choose manage-clients and then click on Assign to allocate the role.
    configure Service Account roles for 3scale integration
    Figure 6: configure Service Account roles for 3scale integration
    Figure 6: Configure Service Account roles for 3scale integration.

    Note the client credentials shown in Figure 7:

    • Make a note of the client ID (<client_id>).
    • Navigate to the Credentials tab of the client and make a note of the Secret field (<client_secret>).
    shows the Client ID and Client secret
    Figure 7: shows the Client ID and Client secret.
    Figure 7: The Client ID and Client secret.
  5. Now move to the Roles section. Create realm roles for students and instructors, as shown in Figure 8.

    Create realm roles for student and instructor
    Figure 8: Create realm roles for student and instructor
    Figure 8: Create realm roles for student and instructor.

Configure Keycloak Authorization Services

  1. Create scopes: In Keycloak's Authorization Services, a scope represents a specific action, access level, or privilege that can be applied to a resource. Essentially, scopes help define in more granular detail what a user can do with a given resource. In our example, we have view and delete scopes that belong to Course Resource (Figure 9).
    Create authorization scopes for delete and view scopes
    Figure 9: Create authorization scopes for delete and view scopes.
  2. Create the Course resource: In the context of Keycloak's Authorization Services, a resource represents any asset or entity that you want to protect and control access to. Essentially, it's something for which you wish to enforce certain access constraints based on user roles, attributes, or other criteria. In our example, the target REST resource is the course resource (Figure 10).
    create Course resource attaching view and delete scopes.
    Figure 10: create Course resource attaching view and delete scopes.
    Figure 10: Create a course resource attaching view and delete scopes.
  3. Create a role policy: A role policy is a type of policy that grants access based on the roles assigned to a user. It allows you to specify that users with a particular role (or set of roles) will either be granted or denied access to a resource or a specific scope within that resource. In our example, we will create two role policies:
    • Student role policy with attaching student realm role (Figure 11).
    • Instructor role policy with attaching instructor realm role (Figure 12).
      Create student role policy
      Figure 11: Create student role policy.
      Create instructor role policy.
      Figure 12: Create instructor role policy.
  4. Create scope-based permissions: In Keycloak's Authorization Services, a permission represents the association between resources and policies, and it defines who can access what and under which conditions. In our example, we need to create two scope permissions:
    • Course view permission that associates course resource, view scope, student role policy, and instructor role policy (Figure 13).
    • Course delete permission that associates course resource,delete scope and instructor role policy (Figure 14).
    Create scope based permission for viewing the course.
    Figure 13: Create scope based permission for viewing the course
    Figure 13: Create scope based permission for viewing the course.
    Create scope based permission for deleting the course
    Figure 14: Create scope based permission for deleting the course
    Figure 14: Create scope-based permission for deleting the course.

Step 2: Add keycloak-authorizer-policy to 3scale API Management

Next, you need to deploy keycloak-Authorization-policy to APIcast 3scale managed in OpenShift.

  1. Start by cloning the custom policy from the GitHub repository:
    $ git clone https://github.com/3scale-demos/keycloak-Authorization-policy
    $ cd keycloak-Authorization-policy/policies/keycloak_Authorize
  2. Create an OpenShift secret with the custom policy content in 3scale API manager namespace:

    oc create secret generic keycloak-authorizer-policy   --from-file=keycloak_Authorizer.lua   --from-file=init.lua --from-file=apicast-policy.json  --from-file=http_headers.lua --from-file=http_connect.lua  -n <<3scale-api-manager>>
  3. Configure and deploy APIManager CR with the custom policy.

  4. Next, you need to add custom policy definition to your APIManager custom resource in the section of 3scale managed apiCast staging and production definition as shown below:

    apiVersion: apps.3scale.net/v1alpha1
    kind: APIManager
    metadata:
      name: example-3scale
    spec:
      apicast:
        stagingSpec:
           customPolicies:
     - name: keycloak_authorizer
       secretRef:
          name: keycloak-authorizer-policy
        version: 1.0.0
        productionSpec:
           customPolicies:
     - name: keycloak_authorizer
       secretRef:
          name: keycloak-authorizer-policy
        version: 1.0.0
  5. Next, you need to create 3scale CustomPolicyDefinition Custom Resource in order to view the policy configuration in the API Manager policy editor UI, the custom policy should be registered using customPolicyDefinition custom resource as shown below.

    apiVersion: capabilities.3scale.net/v1beta1
    kind: CustomPolicyDefinition
    metadata:
     name: custompolicydefinition-kca
    spec:
     name: "keycloak_authorizer"
     version: "1.0.0"
     schema:
        $schema: 'http://json-schema.org/draft-07/schema#'
        configuration:
          properties:
            error_message:
              description: Error message to show to user when traffic is blocked
              title: Error message
              type: string
            rules:
              description: 'List of rules '
              items:
                properties:
                  Keycloak_resource_name:
                    description: Keycloak resource name
                    type: string
                  Keycloak_scope:
                    description: Keycloak scope name
                    type: string
                  methods:
                    default:
                      - ANY
                    description: Allowed methods
                    items:
                      enum:
                        - ANY
                        - GET
                        - HEAD
                        - POST
                        - PUT
                        - DELETE
                        - PATCH
                        - OPTIONS
                        - TRACE
                        - CONNECT
                      type: string
                    type: array
                  resource:
                    description: >-
                      Resource controlled by the rule. This is the same format as
                      Mapping Rules. This matches from the beginning of the string
                      and to make an exact match you need to use '$' at the end.
                    type: string
                  resource_type:
                    description: How to evaluate 'resource' field
                    oneOf:
                      - enum:
                          - plain
                        title: Evaluate as plain text.
                      - enum:
                          - liquid
                        title: Evaluate as liquid.
                    type: string
                required:
                  - Keycloak_resource_name
                  - resource
                  - Keycloak_scope
                type: object
              type: array
          type: object
        name: keycloak_authorizer
        summary: 'The policy integrates APICast with Keycloak Authorization services '
        version: 1.0.0

Step 3: Configure 3scale API management

  1. Now you need to create an API backend in 3scale, which is the actual API endpoint or service that 3scale manages. In this demo we are going to create the course-mgmt backend using 3scale's Echo API.

    The API backend can be created in 3scale using the admin portal or using 3scale operator application capabilities; the following YAML file uses the operator capabilities:

    apiVersion: capabilities.3scale.net/v1beta1
    kind: Backend
    metadata:
      name: course-mgmt
    spec:
      name: "Course-Mgmt"
      systemName: "course-mgmt"
      privateBaseURL: "https://echo-api.3scale.net"
  2. Next you need to create an API product CR in 3scale using operator with the following configurations:

    • Attach course-mgmt backend in the product.
    • Secure the API product by OpenID Connect authentication method and Keycloak. You will need to replace the CLIENT_SECRET that we created in step 1 and other variables, like the Keycloak host and port in the YAML CR below.
    • Create an application plan.
    • Create mapping rules for the view/delete course REST endpoints.
    • Add keycloak_authorizer policy to the product after APIcast policy with the configurations shown in Table 1 for mapping REST endpoint to the Keycloak resource and scope name.

    Table 1:  Configuration of keycloak_authorizer policy.

    Resource mapping rule HTTP method Keycloak resource name Keycloak scope name
    /course$ GET course view
    /course$ DELETE course delete
    apiVersion: capabilities.3scale.net/v1beta1
    kind: Product
    metadata:
      name: course-mgmt
    spec:
      name: "Course-Mgmt"
      backendUsages:
        course-mgmt:
          path: "/"
      deployment:
        apicastHosted:
          stagingPublicBaseURL: "<<stagingPublicBaseURL>>"
          productionPublicBaseURL: "<<productionPublicBaseURL>>"
          authentication:
            oidc:
              issuerType: "keycloak"
              issuerEndpoint: "https://course-mgmt:<CLIENT_SECRET>@<RHSSO-HOST>:<PORT>/realms/3scale-course-mgmt"
              authenticationFlow:
                standardFlowEnabled: true
                implicitFlowEnabled: false
                serviceAccountsEnabled: false
                directAccessGrantsEnabled: false
              jwtClaimWithClientID: "azp"
              jwtClaimWithClientIDType: "plain"
      metrics:
        hits:
          description: Number of API hits
          friendlyName: Hits
          unit: "hit"
      methods:
        view-course:
          friendlyName: view course
        delete-course:
          friendlyName: delete course
      mappingRules:
        - httpMethod: GET
          pattern: "/course"
          increment: 1
          metricMethodRef: view-course
        - httpMethod: DELETE
          pattern: "/course"
          increment: 1
          metricMethodRef: delete-course      
      applicationPlans:
          basic:
            name: "basic"
            published: true
            appsRequireApproval: false      
      policies:
        - name: apicast
          version: builtin  
          enabled: true
          configuration: {}
        - name: keycloak_authorizer
          version: 1.0.0
          enabled: true
          configuration:
            error_message: blocked because of keycloak Authorizer policy
            rules:
            - methods:
              - GET
              resource_type: plain
              Keycloak_resource_name: course
              resource: "/course$"
              Keycloak_scope: view
            - methods:
              - DELETE
              resource_type: plain
              Keycloak_scope: delete
              resource: "/course$"
              Keycloak_resource_name: course

Conclusion

This article showed how to integrate Keycloak authorization service with 3scale API Management to externalize your API protection for authentication and authorization.

Today's modern API architecture requires a centralized authentication and authorization component integrated with the API gateway. Red Hat build of Keycloak provides powerful fine-grained authorization services that can be integrated with 3scale API gateway using a custom policy to externalize authorization decisions for the incoming API requests.