Featured image for secure coding.

Authorino solves a persistent problem that arises when upgrading applications for secure internet use: the need to add authentication or authorization to APIs that were built without these security concepts in mind. Authorino provides an easy, cloud-native way to expose these APIs. You don’t have to modify or rebuild your API. A thin reverse-proxy layer with an external authorization filter, completely configurable via the Kubernetes API, allows you to add the right authentication and authorization model to suit your needs.

This article introduces Authorino with an overview of its uses and benefits, a look at its underlying mechanics, and a brief demonstration based on an example use case.

A use case for Authorino

Let's imagine a frequent scenario for using Authorino. As an API developer, suppose you have identified a need or gotten an exciting new request for enhancement (RFE) to work on. So you go to the whiteboard and come up with a nice software solution based on services and APIs. You pick your favorite stack and dive into coding the key aspects of your project. In a matter of hours or days, you have a beta version ready to be shown and to play with. Your solution is thin, focused, and efficient. Everything goes well ... until certain real-life requirements loom up, notably the requirement for access control.

Now you need to address subtle security questions. Who should access the API? How will you verify the user’s identity? Should you store a database of users? What about permissions? How often will the authorization rules change? Should you implement role-based access control (RBAC)? Should you allow read-only access?

With so many different, dynamic, and possibly complex usage policies to enforce, authentication and authorization standards and protocols to comply with, authorization systems to connect, and legacy code to integrate, securing your APIs can quickly become quite overwhelming.

Shoving all the access control rules into your API’s code is a clear violation of the key design principle of separation of concerns. Doing so would weaken the specialization, performance, maintainability, and scalability of your API. Apart from the infamous if's and else's polluting your code, using embedded access controls can couple your implementation to peripheral packages and technologies, and it definitely limits the reusability of your code.

On the other hand, a separate, domain-specific solution from the market may not sound very appealing. Setting up another server, dealing with complicated config files … not cool.

Developers these days want good, specialized solutions that perform well, and that let us focus on the core aspects of our applications; solutions that are also easy to learn, deploy, and maintain while leveraging the infrastructure we already have and the languages and technologies we have mastered and enjoy using.

What is Authorino?

Authorino is an open source, cloud-native authentication and authorization enforcer that protects APIs. It builds on the gateway pattern of API design to support Zero Trust security for your APIs. Authorino works at the edge of the network as well as for your back-end services, and for intra-cluster communication between containers as well as for ingressing outcoming traffic.

Authorino builds on top of the Envoy proxy and implements the gRPC protocol for external authorization. On top of the proxy, Authorino adds a fast, bullet-proof layer that verifies user identity and enforces authorization policies when requests come in to your API, thus preventing any traffic from reaching your service unless it's been properly authenticated and authorized.

With Authorino, you can expose your API and validate authentication tokens and credentials based on API keys, OpenID Connect (signed JSON Web Tokens), OAuth 2.0 introspection, and Kubernetes authentication, among others. Authorino allows tailor-made access control with authorization policies represented as simple JSON pattern-matching rules or Open Policy Agent (OPA) Rego policies. You pick the industry standard or protocol that best works for you, or any combination of those. You can connect with external auth servers and resource data registries, make use of caching, and deploy for the topology you want—such as a centralized gateway, sidecars, and so on.

The benefits of using Authorino

Authorino covers the requirements of modern web authorization. Here are some of its benefits:

  • Codeless: With Authorino, you can focus on the core aspects of your API solution and leave it up to a strong security agent to perform all the overhead of handling authentication and authorization, such as integrating with authorization servers and identity providers, managing user profiles, and all the if's and else's of complex access control systems. By leveraging the gateway pattern for API access with Envoy filters, Authorino adds security to your APIs, requiring zero changes to your API’s code for most use cases.
  • Agnostic: Authorino offers tailor-made interoperability of API security. Authorino is not strongly opinionated and avoids pushing for a single way of doing things. Thus, it supports different authentication models and protocols, such as API keys, OAuth 2.0, OIDC, native Kubernetes authentication tokens, Red Hat OpenShift user authentication, and mTLS, among others. You can choose the one mode that best suits your API protection needs or combine them to integrate alternative sources of identity, while enforcing assertive and effective authorization policies to each group of users. Authorino provides powerful built-in policy evaluators based on Open Policy Agent (OPA) and JSON pattern matching, allowing you to write authorization rules to implement all kinds of access control models: RBAC, UBAC, or ABAC based on user information stored in the edge, JWTs, context, or attribute data fetched on the fly and cached.
  • Cloud-native: Authorino was built to run on Kubernetes. Instead of unfriendly configuration files or unstandardized administrative APIs, you add protection to services with Authorino through Kubernetes custom resources. Authorino’s custom controller watches for the state of the resources in the Kubernetes server and ensures a single source of truth, thus delivering a real cloud-native user experience. You can, of course, scale, automate, monitor, and audit as you would expect in any truly container-based orchestrated environment. You can lean on Kubernetes's RBAC to manage permissions concerning who can or cannot modify the state of security of your running APIs, either by delegating responsibility to API developers directly or by handling more elaborate DevOps and site reliability engineering (SRE) workflows.
  • Flexible: Authorino is not opinionated regarding the architecture of your API network, either. On the contrary, Authorino can enable a typical single-gateway topology, with one proxy configuration serving multiple APIs, or allow for dedicated proxies contacting either a centralized or completely distributed set of one-to-one Authorino sidecars. As a flexible, fully stateless application, Authorino empowers DevOps to activate scaling for either north/south or east/west API access, without architectural stiffness or intrinsic bottlenecks.
  • Efficient: Layers of caching are automatically added to your API security stack. Options include discovered OpenID Connect and User-Managed Access (UMA) configurations, as well as JSON Web Key Sets (JWKS) and precompiled OPA policies. We will soon add revoked access token information, and even caching of requested resource data.
  • Seamless: You can use Authorino standalone, and soon will be able to use Red Hat 3scale API Management Kuadrant integration. Kuadrant will deliver full cloud-native API management, including authentication and authorization with Authorino, as well as rate limiting, OAS support, custom developer portals, and more. Kuadrant’s data plane will add a layer of abstraction for cohesive, simple and automated orchestration of your API management resources, and translation of high-level API specifications into lower-level resources deployed to scale, including Authorino API protection custom resources.
  • Open source: Authorino is based on reliable, widely-adopted, open source technologies such as Kubernetes, OpenShift, OAuth, OIDC, OPA, and UMA. Authorino is written in Golang and backed by Red Hat.

How does Authorino work?

Authorino implements the Envoy proxy’s external authorization gRPC protocol. It all starts with a developer building and deploying an API and serving it through an Envoy proxy endpoint. The proxy must be configured to point the external authorization filter to a running Authorino service. The developer can do this configuration manually, according to the desired topology to expose the API, or by leveraging the automation provided by Kuadrant. To effectively add protection to the API and start accepting requests, the developer writes a Kubernetes custom resource that represents the identity verification and authorization rules for the API, and then applies this resource to the cluster.

The API protection custom resource states a list of identity sources and authentication methods for authenticating users. Authorino validates access on every request to the API. Authentication methods can be built-in, intrinsic methods based on API keys, mTLS, or HMAC, or based on access tokens issued by auth servers and identity providers (examples include OAuth 2.0 tokens, OIDC JWTs, Kubernetes access tokens, or OpenShift auth server tokens).

The custom resource also lets you define forms of authorization. Authorino supports authorization policies expressed either as simple JSON pattern-matching rules or using the Rego language inline.

Users of the protected API obtain a valid token or credential to access it, and then send requests carrying those credentials in the specified authentication field (such as an HTTP authorization header, custom header, query string parameter, or cookie). The requests are intercepted by the Envoy proxy, which establishes a fast gRPC connection with Authorino. Authorino looks up a valid custom resource to enforce its policies and triggers an auth pipeline. Throughout the auth pipeline, Authorino verifies whether the supplied token or credential is accepted by at least one of the known trusted identity sources, and whether all authorization policies agree on granting access to the user for the requested resource of the API. Figure 1 shows the basic flow.

How Authorino works, from building and deploying the API to protecting access with Envoy reverse-proxy and Authorino external authorization filter.
Figure 1: A sequence diagram showing the role of Authorino in authorization through a proxy.

The authorization policies can count on any information gathered throughout the auth pipeline, including context data of the request (such as attributes of the HTTP request), attributes of the identity resolved from the credentials (user info, JWT claims, etc.), and eventual metadata obtained from external services. On every request, Authorino builds an authorization JSON, which serves as the input for the evaluation of the authorization policies. The policies can be written in Rego and executed by the built-in OPA module, or be simple JSON pattern-matching rules with operators such as "is equal to," "matches a regex," "includes," and so on. Figure 2 shows the pipeline followed by Authorino when authorizing a request.

The Authorino auth pipeline: service lookup, identity verification, authorization JSON, additional metadata fetched from external services, policy enforcement, and a festival wristband.
Figure 2: The steps in a request authorization by Authorino.

If Authorino succeeds in verifying the user’s identity and if all policies grant access to the user, Envoy redirects the traffic to the requested protected API. Otherwise, the requested API will never be reached and the appropriate HTTP status code is returned to the user. Before that, however, Authorino can optionally also issue a "festival wristband," which is a configurable OIDC ID token, a signed JWT, that is sent back in the response to the user, and that can be used to implement token normalization and edge authentication.

Sample use case

Authorino is designed to build the custom API protection package that makes sense for your API. For instance, on requests to a given API, one could choose to accept access tokens from different identity sources, possibly obtained through different authentication protocols, while managing access through one single OPA-based authorization policy written in Rego to cover all cases. Other projects might prefer to allow access tokens issued always by a single, trusted source of identity, and split the authorization policies into multiple simple pattern matching rules. All of these use cases can be mixed and combined.

In the Authorino Service custom resource, this is what an API protection policy based on OIDC authentication, and enforcing RBAC and UBAC policy rules, looks like:

apiVersion: config.authorino.3scale.net/v1beta1
kind: Service
metadata:
  name: my-api-protection-1
spec:
  hosts:
    - my-api.io
identity:
  - name: users
    oidc:
      issuer: http://my-trusted-idp.example.com
authorization:
  - name: rbac
    json:
      conditions:
        - selector: auth.identity.roles
          operator: excl
          value: admin
      rules:
        - selector: auth.content.request.method
          operator: eq
          value: GET
  - name: ubac
    json:
      rules:
        - selector: auth.identity.email_verified
          operator: eq
          value: "true"

In this example, users authenticate with an OIDC server and present the JWT obtained in their requests to the protected API. Authorino discovers the OIDC configuration and JKWS, validates the JWTs, and enforces two authorization policies. The first authorization policy ensures that users without the admin role can send only GET HTTP requests to the API, while the second forbids requests from users with non-verified email addresses.

Another example follows of an API that accepts requests from users authenticated as clients of the Kubernetes server (i.e., holding a valid Kubernetes access token), or via an API key (where each API key is stored as a Kubernetes secret resource). For the authorization bit, one single policy written in Rego states that Kubernetes-authenticated users have full access to the API, whereas the API key-authenticated users can access the API only before 8 a.m. UTC.

apiVersion: config.authorino.3scale.net/v1beta1
kind: Service
metadata:
  name: my-api-protection-2
spec:
  hosts:
    - my-other-api.io
  identity:
    - name: k8s-users
      kubernetes: {}
    - name: api-key-users
      apiKey:
        labelSelectors:
          authorino.3scale.net/managed-by: authorino
          audience: api-user
      credentials:
        in: custom_header
        keySelector: X-APIKEY
  authorization:
    - name: my-policy
      opa:
        inlineRego: |
          k8s_user { input.auth.identity.iss == "kubernetes.default.svc" }
          api_key_user { input.auth.identity.kind == "Secret" }

          before_8am {
            beginning_of_day := floor(time.now_ns()/86400000000000)*86400
            (input.context.request.time.seconds - beginning_of_day) < (8*3600)
          }

          allow { k8s_user }
          allow { api_key_user; before_8am }

Where can I learn more about Authorino?

If you found this introduction interesting and want to know more about Authorino, check out the Authorino repository on GitHub. You will find several other examples in the repository, along with tutorials, deployment instructions, detailed information about how Authorino works, a list of features, and more.

Authorino is still in the alpha stage and has not yet been officially released. However, several teams at Red Hat have been exploring use cases and designing solutions around Authorino’s capabilities. It is an exciting moment to engage and contribute to the project.

Comments