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 might 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, Kubernetes-native external authorization service to protect APIs. It builds on the reverse-proxy 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 (attached to internal proxies) as well as for incoming traffic (attached to an Ingress gateway).
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, bulletproof 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 (e.g., JWT claim check, HTTP request attributes check), complex Open Policy Agent (OPA) Rego policies and Kubernetes SubjectAccessReview (Kubernetes RBAC). 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:
- 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. Authorino supports authorization based on Kubernetes SubjectAccessReview as well.
- Clean: 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 andelse
s of complex access control systems. By leveraging the reverse-proxy or 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. - Kubernetes-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 you will be able to use the Red Hat 3scale API Management Kuadrant integration. Kuadrant delivers 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 lets you attach simple and cohesive API management orchestration to your networking resources such as Kubernetes Services, Ingress gateways, OpenShift routes, and Istio Virtual Services and HTTPRoutes, translating from high-level API specifications into lower-level resources deployed to scale, including Authorino custom resources.
- Open source: Authorino is based on popular and reliable 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 applies to the cluster a Kubernetes AuthConfig
custom resource (CR).
The AuthConfig
CR states a recipe for identity verification and authorization rules to be enforced on requests to the API. It lists trusted sources of identity and authentication methods for validating user credentials and access tokens. Authentication can be performed by external auth servers and identity providers (IdP); Authorino validates access tokens issued by those providers at request time via protocols including OIDC JWTs, OAuth 2.0 opaque token introspection, and Kubernetes access tokens. Authentication can also be performed by built-in methods based on API keys, mTLS, and HMAC authentication.
The AuthConfig
CR also lets you define forms of authorization. Authorino supports authorization policies expressed as simple JSON pattern-matching rules (e.g., JWT claim checks), using the Open Policy Agent (OPA) Rego language inline or fetching from an external policy registry, and authorization based on Kubernetes SubjectAccessReview.
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.
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 runtime authorization policies. The policies can be written in Rego and executed by the built-in OPA module, evaluated against the Kubernetes RBAC via SubjectAccessReview API, 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.
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 redirecting to the API, Authorino can optionally inject custom HTTP headers and Envoy dynamic metadata. Additionally, Authorino can issue Festival Wristband tokens: signed OIDC-compliant JWTs 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 AuthConfig
custom resource, this is what an API protection policy based on OIDC authentication, and enforcing RBAC and UBAC policy rules, looks like:
apiVersion: apiVersion: authorino.kuadrant.io/v1beta1
kind: AuthConfig
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
when:
- selector: auth.identity.roles
operator: excl
value: admin
json:
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: apiVersion: authorino.kuadrant.io/v1beta1
kind: AuthConfig
metadata:
name: my-api-protection-2
spec:
hosts:
- my-other-api.io
identity:
- name: k8s-users
kubernetes: {}
- name: api-key-users
apiKey:
labelSelectors:
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. There, you will find many user guides and tutorials based on several use cases, detailed information about the architecture and how Authorino works, a full list of features with documentation, and more.
Authorino is in the beta stage right now, soon to start getting official releases. 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.
Join us on our open channel on Slack: kuadrant.slack.com.
Last updated: July 25, 2023