Identity Enrollment Flow for Ziti Android SDK

I’m building a simple chat app with a backend server. Originally, the frontend connected to the backend through an NGINX web service. I've now added a Ziti network so that only enrolled and authorized clients can reach the NGINX server.

So far, everything works correctly when using Ziti Edge Desktop — I can access the backend API through the Ziti network.

Now I want to connect the Android frontend app to the backend using Ziti SDK for Android.

According to the Ziti SDK for Android GitHub page:

“Java SDK provides a way to enroll and generate identity file. The default identity format for Java SDK is Java KeyStore stored as .p12/.pfx files, however it can use identity JSON files generated by ziti-enroller as well.”

I tried the following:

  • Created a device identity using ziti edge create identity
  • Enrolled it on the server with ziti edge enroll
  • Passed the resulting .json identity file to the Android app

My initial idea was to share a single Ziti identity across all app users, assigning it access to only the required services — similar to using a shared RBAC role or service account. However, when I try to use that identity in the app, I get an error about unsupported format.


My questions:

  1. What does "ziti-enroller" refer to in the SDK docs? Is it the same as using ziti edge enroll, or is it a separate tool?
  2. Is it valid or recommended to generate and enroll a single identity server-side for all users of the app(like I did), and then pass the identity file to the client app?
  3. If that’s not the best approach, does each client device need to enroll its own identity via .jwt? Because in my case, I need many devices to access the network, and manually creating and managing identities for each user is not viable. I would assume that I have to build a backend service (e.g. in Express.js) that:
  • Authenticates users
  • Dynamically creates and enrolls identities
  • Returns a .jwt to the Android app for secure enrollment?

I'd love some guidance from the community on what’s considered best practice here — especially around managing device identities securely at scale in a mobile environment.

It should work this way. Let's ensure the JSON configuration file you generated with the ziti CLI's built-in enrollment command is valid JSON, has the expected schema, and your Android app has read and write permission on the JSON file. These sanity checks will identify the most common issues, and I'll escalate to a Java SDK expert if there's still a problem.

This is the expected schema.

{
  "ztAPI": "string",
  "ztAPIs": [
    "string"
  ],
  "id": {
    "cert": "string",
    "key": "string",
    "ca": "string"
  }
}
  1. That separate tool was integrated into ziti CLI. You found the correct tool.
  2. It'll work in many cases, but it limits the expressive potential of the system you're building, and it can reduce your ability to understand your system's logs. For example, if you're investigating an event that mentions that identity, you won't as easily know which instance of the identity is relevant. Of course, you will lose the ability to enforce different policies if all clients are clones.
  3. The best approach is to implement enrollment for each instance. You have several options, including a one-time token (OTT as JWT) from the OpenZiti Controller. Alternatives include tokens or certificates from a trusted third party. Here's the "Security" section of the OpenZiti documentation that talks about authentication and enrollment. A simple example is your central platform/application server could possess an OpenZiti admin credential and provision a OTT for each of your users. You could deliver the token to their application through some bootstrapping process so it can enroll, which involves generating its private key, requesting a client certificate, and saving the JSON configuration file with those inside, along with a certificate trust bundle. In all, the JSON file is analogous to a Java keytool keystore containing cryptographic material.