Problem
On a fresh WebProtege install, no user has the SystemAdmin role. This blocks every admin-only operation:
- Cannot open Application Settings (the
EditApplicationSettings capability is required)
- Cannot enable "Empty project creation allowed" for any signed-in user
- Cannot assign roles to other users
- Cannot create projects (unless a role is granted individually)
The only way out today is to manually insert a RoleAssignment document into MongoDB:
db.RoleAssignments.insertOne({
userName: "<some-user>",
projectId: null,
assignedRoles: ["SystemAdmin"],
roleClosure: ["SystemAdmin", "UserAdmin", "ProjectCreator", "ProjectUploader", "AccountCreator"],
capabilityClosure: [ ...every capability spelled out... ]
})
This is brittle, hard to discover, and requires operators to reason about an internal schema.
Proposed solution
Add a config property (webprotege.auth.initialAdminUsername or similar) that the authorization service reads on startup. If set:
- Check whether any user already has
SystemAdmin
- If not, create a
RoleAssignment granting SystemAdmin to the configured username
- Compute
roleClosure and capabilityClosure via the existing role-resolution logic — no hand-rolled closure arrays
- Log the action clearly (so operators know who became the first admin)
- Idempotent: if the user already has
SystemAdmin, do nothing
Implementation sketch — a Spring ApplicationRunner or @EventListener(ApplicationReadyEvent.class) bean in the authorization service, reading the config property via @Value or @ConfigurationProperties.
Considerations
-
What happens if the configured user doesn't exist yet in Keycloak? Still create the RoleAssignment — the authorization service works off username strings, not Keycloak user records, so the role applies as soon as that user signs in.
-
What if the property is changed later to a different username? The new username gets SystemAdmin; the old user keeps theirs. Admins can be revoked manually through the UI once EditApplicationSettings is accessible. Not trying to do anything clever here.
-
Should this be a one-shot (runs only if no admin exists) or continuous (always ensures the configured user has admin)? One-shot is safer — avoids clobbering intentional role removals. The property is a bootstrap aid, not a source of truth.
Deploy-side changes
The webprotege-deploy compose should set this env var from .env:
webprotege-authorization-service:
environment:
WEBPROTEGE_AUTH_INITIALADMINUSERNAME: ${INITIAL_ADMIN_USERNAME:-}
And .env.example should document: "On first boot, set this to the webprotege_username of the user who should become the initial admin. Leave blank for existing installs where an admin already exists."
Tracking issue in the deploy repo will reference this one.
Context
Came up during protegeproject/webprotege-deploy#59 while testing a fresh install end-to-end. After registering a new user, there was no way to reach Application Settings or create projects without direct MongoDB manipulation.
Related: protegeproject/webprotege-backend-service#167 (separating internal user ID from display name — will change the shape of userName in role assignments).
Problem
On a fresh WebProtege install, no user has the
SystemAdminrole. This blocks every admin-only operation:EditApplicationSettingscapability is required)The only way out today is to manually insert a
RoleAssignmentdocument into MongoDB:This is brittle, hard to discover, and requires operators to reason about an internal schema.
Proposed solution
Add a config property (
webprotege.auth.initialAdminUsernameor similar) that the authorization service reads on startup. If set:SystemAdminRoleAssignmentgrantingSystemAdminto the configured usernameroleClosureandcapabilityClosurevia the existing role-resolution logic — no hand-rolled closure arraysSystemAdmin, do nothingImplementation sketch — a Spring
ApplicationRunneror@EventListener(ApplicationReadyEvent.class)bean in the authorization service, reading the config property via@Valueor@ConfigurationProperties.Considerations
What happens if the configured user doesn't exist yet in Keycloak? Still create the
RoleAssignment— the authorization service works off username strings, not Keycloak user records, so the role applies as soon as that user signs in.What if the property is changed later to a different username? The new username gets
SystemAdmin; the old user keeps theirs. Admins can be revoked manually through the UI onceEditApplicationSettingsis accessible. Not trying to do anything clever here.Should this be a one-shot (runs only if no admin exists) or continuous (always ensures the configured user has admin)? One-shot is safer — avoids clobbering intentional role removals. The property is a bootstrap aid, not a source of truth.
Deploy-side changes
The
webprotege-deploycompose should set this env var from.env:And
.env.exampleshould document: "On first boot, set this to thewebprotege_usernameof the user who should become the initial admin. Leave blank for existing installs where an admin already exists."Tracking issue in the deploy repo will reference this one.
Context
Came up during protegeproject/webprotege-deploy#59 while testing a fresh install end-to-end. After registering a new user, there was no way to reach Application Settings or create projects without direct MongoDB manipulation.
Related: protegeproject/webprotege-backend-service#167 (separating internal user ID from display name — will change the shape of
userNamein role assignments).