Introduction

When considering migrating a monolithic application to Go microservices, I found that identity authentication was a thorny issue. I researched many gateway-level identity authentication solutions and followed some open source projects, but when actually deploying and using them, they never felt quite right.

Until I discovered ZITADEL. This is a cloud-native identity authentication service developed by a Swiss team based on Golang. After research and local deployment attempts, I must say that this project is relatively well-developed and is guided by product-oriented thinking. The user experience for both developers and end users can rival large commercial IDaaS solutions, such as Authing in China.

The project was established in 2019, and the community is quite active. After deploying and using it myself, I also tried to participate in the open source project, such as contributing to the Chinese language pack and fixing issues with language switching.

Features

  • Identity management (implementing EIAM and CIAM through an organizational abstraction model)
  • Support for RESTful, gRPC
  • SDK
  • Authorization management
  • Project management
  • Application management
  • Cross-organization, project authorization users
  • Passwordless (FaceID, TouchID, and Key, etc.)
  • Multifactor Authentication (FaceID, TouchID, Key, and OTP, etc.)
  • User custom metadata
  • User authentication flow

Concepts

Instance

In ZITADEL, Instance is the highest abstraction layer, which can be understood as a multi-tenant model. For example, each company can be an Instance. Within an Instance, you can manage multiple organizations, and also set external IDPs, password complexity, user locking policies, Passwordless, and MFA policies.

Instance Management

Organizations

Organization is a layer of abstraction for users, used to manage and distinguish the scope of user roles. For example, for enterprises, there may be B-end customers and C-end customers, so these users can be placed in different organizations, while the authentication and authorization of the internal system can be created in another separate organization.

Organizations can also customize external IDPs and branded authentication UIs, as well as override some security settings in the Instance.

Actions and Flows

This part is used to set up trigger flows and actions after user authentication.

Actions and Flows

Domains

The organization’s name is part of the domain, and users need to use a username plus domain to log in, which is somewhat like an email address.

For example: If a company is called Betterde, which is an Instance, and we create an internal personnel organization called Internal, then the username for users under this organization would be [email protected] when logging in.

User

A user is what we understand as a regular user, who can be authorized in projects. If a user is not authorized in a project, they cannot log in through the OAuth flow in applications under the project.

In other words, even if a user has registered information in an organization, they still cannot log in at this point. Administrators need to authorize the applications that the user needs to access in the Console UI, which means granting roles to the user. When the user logs in, their role information in the project will be carried in the ID Token for backend service authorization.

Service User

Used for identity verification between backend services. For example, if identity verification is needed when calling services across companies, a Service User can be created.

Projects

Projects are an abstraction of applications. So why do we need this abstraction layer? In actual company projects, we often divide a project into frontend and backend, or even native apps. And these are one application from the user’s perspective. This approach allows for better management of user authorization and different endpoints of the same project.

Project Management

Applications

Applications here are what we understand as Web Apps, Native Apps, and Service APIs. We can set different authorization methods and token settings for different types of applications.

Application Management

Integration with Existing Systems

As long as the system supports OIDC, ZITADEL can be used as an external IDP for identity authentication, such as MinIO.

MinIO Integration with ZITADEL

Let’s first look at the effect after configuration:

MinIO SSO

ZITADEL Auth

Reference configuration information:

OIDC Configuration

Note: The configuration of Claim Name is very important because there is a compatibility issue between MinIO and ZITADEL. Therefore, we cannot authorize through roles here, but can only get user information through ZITADEL’s user ID, which is the sub field. At the same time, we also need to create corresponding IAM Policies for users in MinIO and set the corresponding access permissions.

Using OIDC in APISIX

APISIX Gateway supports OIDC. Through the OIDC plugin, API Gateway can implement centralized authentication, so backend services don’t need to implement authentication logic in each service. The backend only needs to focus on the business logic itself, which reduces the mental burden on developers!

APISIX’s OIDC plugin supports two introspection modes:

  • Token Introspection: Introspects by requesting the Introspection Endpoint of the IDaaS service, obtains user information, and attaches the user information to the X-Userinfo request header after Base64 encoding;
  • Public Key Introspection: APISIX verifies the signature and validity period of the Access Token or ID Token through the public key, but does not attach the information contained in the Token to the request header, requiring the backend to parse it from the Token itself.

The introspection flow is shown in the following diagram:

API Gateway Centralized Authentication

Similar Projects

Conclusion

Because I was interested in its design and implementation, I read ZITADEL’s source code. Their technology stack impressed me; the backend uses gRPC and then supports RESTful APIs through gRPC-Gateway proxy.

The frontend also interacts with the backend using gRPC-Web, which surprised me. Although I had seen this approach online before, it was in Beta at the time. I didn’t expect that a team would already be applying it to a production environment!

After studying the code, I indeed learned a lot. I’m considering using the same technology stack to build backend services and generate corresponding documentation and frontend/backend code through Proto files in future projects.

I hope this is helpful, Happy hacking…