How to Manage Jenkins Users: A Complete Guide to the User API

Jenkins represents each user with the hudson.model.User class, providing lifecycle management, persistence to XML, security integration, and REST API access through the core/src/main/java/hudson/model/User.java source file.

Managing Jenkins users programmatically requires understanding the core User model that powers both the web interface and automation scripts. The hudson.model.User class in the jenkinsci/jenkins repository handles everything from on-demand creation to deletion, storing each user's configuration in individual XML files under $JENKINS_HOME. Whether you are administering users through the script console, Groovy scripts, or HTTP requests, the underlying architecture remains consistent and extensible through the UserProperty system.

Understanding the Jenkins User Architecture

The Jenkins user management system is built around several key components that work together to provide a pluggable, secure identity framework.

Core Components

  • User object – Defined in core/src/main/java/hudson/model/User.java, this class holds the user ID, full name, description, and a collection of UserProperty instances. The class header defines the model between lines 26-34.

  • On-demand creation – User objects are instantiated lazily through factory methods. The getOrCreateById factory and private constructor ensure that User.get(id, true) only creates records when explicitly requested.

  • Persistence layer – Each user is stored in its own folder under $JENKINS_HOME/users/<hashed-folder>/config.xml. The getConfigFile() method builds this path, while save() writes the XML representation.

  • User registry – User.AllUsers acts as a singleton registry holding a map of all loaded users, keyed by the canonical ID strategy. The registry populates at startup via AllUsers.scanAll() (lines 990-1014).

  • Security integration – The User class implements AccessControlled, with getACL() (lines 606-614) granting users full control over themselves while deferring to the global security strategy for other permissions.

  • Extensible properties – The properties list stores UserProperty objects such as API tokens and profile pictures. Adding a property via addProperty() automatically persists the change.

Creating and Retrieving Users

Jenkins uses lazy initialization for user objects. The primary factory method User.get(String idOrFullName, boolean create) retrieves existing users or creates new ones on demand.

Script Console Method

Run this Groovy code in Manage Jenkins > Script Console to create or retrieve a user:

// Retrieve an existing user or create a new one on-demand
def jenkins = jenkins.model.Jenkins.instance
def alice = hudson.model.User.get("alice", true)   // true => create if missing
alice.fullName = "Alice Example"
alice.description = "Team lead for UI"
alice.save()   // persists to $JENKINS_HOME/users/…
println "Created user: ${alice.id} (${alice.fullName})"

The save() method validates the user ID against restricted names (such as anonymous, system, or unknown) using isIdOrFullnameAllowed() before writing to disk.

Managing User Properties

User properties extend the base User object with additional functionality like API tokens and avatar images. The UserProperty base class lives in core/src/main/java/hudson/model/UserProperty.java.

Adding an API Token

import jenkins.security.ApiTokenProperty

def bob = hudson.model.User.get("bob", true)
def tokenProp = new ApiTokenProperty()
bob.addProperty(tokenProp)   // automatically persists the property
println "API token for ${bob.id}: ${tokenProp.getApiToken()}"

Calling addProperty() immediately updates the user's config.xml file. The UserPropertyDescriptor class (core/src/main/java/hudson/model/UserPropertyDescriptor.java) provides the descriptor pattern for creating default property instances.

Listing All Users

To enumerate every user in the system, access the singleton registry through User.getAll():

hudson.model.User.getAll().each { u ->
    println "${u.id} – ${u.fullName}"
}

This method returns a collection of all loaded User objects from the AllUsers internal cache.

Deleting Users

Jenkins provides multiple deletion pathways, all requiring the ADMINISTER permission and preventing self-deletion.

REST API Deletion


# Delete user "dave" via HTTP POST (requires ADMINISTER permission)

curl -X POST -u admin:adminToken \
  http://jenkins.example.com/user/dave/doDelete

The doDoDelete() method (lines 122-131) performs permission checks, validates that the current user is not deleting themselves, removes the user's folder from $JENKINS_HOME/users/, and clears the cache entry from User.AllUsers.

Accessing Users via the REST API

Every user exposes a REST endpoint for programmatic access to their data.

JSON Endpoint

curl -u admin:adminToken http://jenkins.example.com/user/alice/api/json

The getApi() method (lines 915-917) returns a new Api object that handles the serialization of User properties to JSON or XML.

Updating Descriptions via POST

curl -X POST -u admin:adminToken \
  -F "description=New description for Carol" \
  http://jenkins.example.com/user/carol/submitDescription

The doSubmitDescription() method processes this request and persists changes through the standard save() mechanism.

Security Implementation Details

The User class implements AccessControlled to integrate with Jenkins' role-based security model. The getACL() implementation combines a per-user access control list (granting full control to the user over their own record) with the global security realm's ACL. For authentication caching, Jenkins uses UserDetailsCache (core/src/main/java/jenkins/security/UserDetailsCache.java) and ImpersonatingUserDetailsService2 to handle user impersonation and session management.

Summary

  • User model – The hudson.model.User class in core/src/main/java/hudson/model/User.java provides the core identity management functionality.
  • Lazy creation – Use User.get(id, true) to create users on demand through the Groovy script console.
  • Persistence – Users are stored as XML files in $JENKINS_HOME/users/<hashed-folder>/config.xml.
  • Extensibility – Attach UserProperty objects (API tokens, profiles) via addProperty() for automatic persistence.
  • Deletion safety – The doDoDelete() method requires ADMINISTER permission and prevents self-deletion.
  • Programmatic access – Access user data via /user/<id>/api/json endpoints exposed by getApi().

Frequently Asked Questions

How are Jenkins users stored on disk?

Each user is stored in a separate directory under $JENKINS_HOME/users/ using a hashed folder name. Inside each folder, a config.xml file contains the serialized User object and its properties. The getConfigFile() method constructs this path, and save() handles the XML serialization.

Can I create Jenkins users without using the web UI?

Yes. Use the Groovy script console with hudson.model.User.get("username", true) to create users programmatically. Set the fullName and description properties, then call save() to persist. You can also use the REST API to modify existing user properties via POST requests to endpoints like /user/<id>/submitDescription.

What prevents invalid user IDs in Jenkins?

The isIdOrFullnameAllowed() method validates user IDs during the save() operation. It rejects reserved system names including anonymous, system, and unknown to prevent conflicts with Jenkins' internal security contexts and special user accounts.

How does Jenkins handle user deletion permissions?

The doDoDelete() method enforces strict security controls. It requires the ADMINISTER global permission, prevents users from deleting their own accounts (self-deletion protection), and removes both the on-disk folder and the in-memory cache entry from User.AllUsers to ensure complete removal from the system.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →