or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdindex.mdjaas.mdlogin-services.mdsecurity-framework.mduser-identity.md

user-identity.mddocs/

0

# User Identity Management

1

2

User identity management in Jetty Security encompasses user principals, roles, identity services, and the association of security contexts with execution threads.

3

4

## Core Identity Interfaces

5

6

### UserIdentity

7

8

Central interface representing an authenticated user:

9

10

```java { .api }

11

public interface UserIdentity {

12

13

// Core identity access

14

Subject getSubject();

15

Principal getUserPrincipal();

16

17

// Role checking

18

boolean isUserInRole(String role);

19

20

// Static factory methods

21

static UserIdentity from(Subject subject, Principal userPrincipal, String... roles);

22

}

23

```

24

25

### UserIdentity Implementation

26

27

```java { .api }

28

public class UserIdentityExample {

29

30

public void createUserIdentity() {

31

32

// Create subject for user

33

Subject subject = new Subject();

34

35

// Create user principal

36

UserPrincipal userPrincipal = new UserPrincipal("john",

37

Credential.getCredential("password123"));

38

39

// Create user identity with roles

40

UserIdentity identity = UserIdentity.from(subject, userPrincipal,

41

"user", "developer", "api-access");

42

43

// Role checking

44

boolean canAccess = identity.isUserInRole("developer");

45

boolean isAdmin = identity.isUserInRole("admin");

46

47

// Access underlying components

48

Subject userSubject = identity.getSubject();

49

Principal principal = identity.getUserPrincipal();

50

}

51

}

52

```

53

54

## Identity Service

55

56

### IdentityService Interface

57

58

Manages associations between user identities and execution threads:

59

60

```java { .api }

61

public interface IdentityService {

62

63

// Thread association

64

Association associate(UserIdentity user, RunAsToken runAsToken);

65

66

// User lifecycle

67

void onLogout(UserIdentity user);

68

69

// Factory methods

70

UserIdentity newUserIdentity(Subject subject, Principal userPrincipal, String[] roles);

71

RunAsToken newRunAsToken(String roleName);

72

73

// System user access

74

UserIdentity getSystemUserIdentity();

75

76

// Nested interfaces

77

interface Association extends AutoCloseable {

78

@Override

79

void close();

80

}

81

82

interface RunAsToken {

83

// Opaque token for run-as operations

84

}

85

}

86

```

87

88

### DefaultIdentityService

89

90

Default implementation of IdentityService:

91

92

```java { .api }

93

public class DefaultIdentityService implements IdentityService {

94

95

@Override

96

public Association associate(UserIdentity user, RunAsToken runAsToken) {

97

98

// Associate user identity with current thread

99

return new AssociationImpl(user, runAsToken);

100

}

101

102

@Override

103

public void onLogout(UserIdentity user) {

104

// Clear any thread associations for this user

105

clearThreadAssociations(user);

106

}

107

108

@Override

109

public UserIdentity newUserIdentity(Subject subject, Principal userPrincipal, String[] roles) {

110

111

// Create DefaultUserIdentity with provided components

112

return new DefaultUserIdentity(subject, userPrincipal, roles);

113

}

114

115

@Override

116

public RunAsToken newRunAsToken(String roleName) {

117

118

// Create run-as token for the specified role

119

return new RoleRunAsToken(roleName);

120

}

121

122

@Override

123

public UserIdentity getSystemUserIdentity() {

124

125

// Return null - no system user by default

126

return null;

127

}

128

129

// Static utility methods

130

public static boolean isRoleAssociated(String role);

131

132

// Private implementation classes

133

private static class AssociationImpl implements Association {

134

// Implementation details

135

}

136

}

137

```

138

139

## User Principals

140

141

### UserPrincipal

142

143

Represents a user with authentication capabilities:

144

145

```java { .api }

146

public class UserPrincipal implements Principal {

147

148

// Constructor

149

public UserPrincipal(String name, Credential credential);

150

151

@Override

152

public String getName();

153

154

// Authentication methods

155

public boolean authenticate(Object credentials);

156

public boolean authenticate(Credential c);

157

public boolean authenticate(UserPrincipal u);

158

159

// Subject integration

160

public void configureSubject(Subject subject);

161

public void deconfigureSubject(Subject subject);

162

163

// Utility methods

164

@Override

165

public boolean equals(Object other);

166

167

@Override

168

public int hashCode();

169

170

@Override

171

public String toString();

172

}

173

```

174

175

### UserPrincipal Usage

176

177

```java { .api }

178

public class UserPrincipalExample {

179

180

public void createAndUseUserPrincipal() {

181

182

// Create user principal with password

183

Credential password = Credential.getCredential("secretPassword");

184

UserPrincipal user = new UserPrincipal("alice", password);

185

186

// Test authentication

187

boolean validPassword = user.authenticate("secretPassword");

188

boolean invalidPassword = user.authenticate("wrongPassword");

189

190

// Test credential object authentication

191

Credential testCred = Credential.getCredential("secretPassword");

192

boolean credValid = user.authenticate(testCred);

193

194

// Test user-to-user authentication

195

UserPrincipal sameUser = new UserPrincipal("alice", password);

196

boolean sameUserAuth = user.authenticate(sameUser);

197

198

// Configure subject

199

Subject subject = new Subject();

200

user.configureSubject(subject);

201

202

// Subject now contains the user principal

203

Set<Principal> principals = subject.getPrincipals();

204

boolean containsUser = principals.contains(user);

205

}

206

207

public void createUserWithHashedPassword() {

208

209

// Create user with MD5 hashed password

210

Credential md5Cred = Credential.getCredential("MD5:5d41402abc4b2a76b9719d911017c592");

211

UserPrincipal user = new UserPrincipal("bob", md5Cred);

212

213

// Authenticate with plain text (will be hashed for comparison)

214

boolean authenticated = user.authenticate("hello");

215

216

// Create user with crypt password

217

Credential cryptCred = Credential.getCredential("CRYPT:$1$salt$hash");

218

UserPrincipal cryptUser = new UserPrincipal("charlie", cryptCred);

219

}

220

}

221

```

222

223

## Credential Management

224

225

### Credential

226

227

Utility class for secure credential handling and password storage:

228

229

```java { .api }

230

public abstract class Credential {

231

232

// Factory method for creating credentials

233

public static Credential getCredential(String credential);

234

235

// Credential verification

236

public abstract boolean check(Object credentials);

237

238

// Common credential types supported:

239

// - Plain text passwords: "password123"

240

// - MD5 hashed: "MD5:5d41402abc4b2a76b9719d911017c592"

241

// - Crypt hashed: "CRYPT:$1$salt$hash"

242

// - BCrypt hashed: "$2y$10$..."

243

}

244

```

245

246

The Credential class provides secure password storage and verification. It automatically detects the credential type and applies appropriate hashing and verification algorithms.

247

248

## Role Principals

249

250

### RolePrincipal

251

252

Represents a role that can be associated with subjects:

253

254

```java { .api }

255

public class RolePrincipal implements Principal {

256

257

// Constructor

258

public RolePrincipal(String name);

259

260

@Override

261

public String getName();

262

263

// Subject integration

264

public void configureSubject(Subject subject);

265

public void deconfigureSubject(Subject subject);

266

267

@Override

268

public boolean equals(Object other);

269

270

@Override

271

public int hashCode();

272

273

@Override

274

public String toString();

275

}

276

```

277

278

### Role Management

279

280

```java { .api }

281

public class RoleManagementExample {

282

283

public void manageUserRoles() {

284

285

// Create user

286

UserPrincipal user = new UserPrincipal("manager",

287

Credential.getCredential("password"));

288

289

// Create roles

290

RolePrincipal userRole = new RolePrincipal("user");

291

RolePrincipal managerRole = new RolePrincipal("manager");

292

RolePrincipal adminRole = new RolePrincipal("admin");

293

294

// Create subject and configure

295

Subject subject = new Subject();

296

user.configureSubject(subject);

297

userRole.configureSubject(subject);

298

managerRole.configureSubject(subject);

299

300

// Create user identity

301

IdentityService identityService = new DefaultIdentityService();

302

UserIdentity identity = identityService.newUserIdentity(subject, user,

303

new String[]{"user", "manager"});

304

305

// Check roles

306

boolean isUser = identity.isUserInRole("user"); // true

307

boolean isManager = identity.isUserInRole("manager"); // true

308

boolean isAdmin = identity.isUserInRole("admin"); // false

309

}

310

311

public void createHierarchicalRoles() {

312

313

// Create role hierarchy

314

Map<String, Set<String>> roleHierarchy = new HashMap<>();

315

roleHierarchy.put("admin", Set.of("admin", "manager", "user"));

316

roleHierarchy.put("manager", Set.of("manager", "user"));

317

roleHierarchy.put("user", Set.of("user"));

318

319

// Custom identity service with role hierarchy

320

IdentityService hierarchicalService = new HierarchicalIdentityService(roleHierarchy);

321

322

// User with only "manager" role

323

UserPrincipal user = new UserPrincipal("supervisor",

324

Credential.getCredential("password"));

325

Subject subject = new Subject();

326

user.configureSubject(subject);

327

328

UserIdentity identity = hierarchicalService.newUserIdentity(subject, user,

329

new String[]{"manager"});

330

331

// Manager can act as user due to hierarchy

332

boolean canActAsUser = identity.isUserInRole("user"); // true

333

boolean canActAsManager = identity.isUserInRole("manager"); // true

334

boolean canActAsAdmin = identity.isUserInRole("admin"); // false

335

}

336

337

// Custom identity service with role hierarchy

338

private static class HierarchicalIdentityService extends DefaultIdentityService {

339

private final Map<String, Set<String>> roleHierarchy;

340

341

public HierarchicalIdentityService(Map<String, Set<String>> roleHierarchy) {

342

this.roleHierarchy = roleHierarchy;

343

}

344

345

@Override

346

public UserIdentity newUserIdentity(Subject subject, Principal userPrincipal, String[] roles) {

347

348

// Expand roles based on hierarchy

349

Set<String> expandedRoles = new HashSet<>();

350

for (String role : roles) {

351

Set<String> impliedRoles = roleHierarchy.get(role);

352

if (impliedRoles != null) {

353

expandedRoles.addAll(impliedRoles);

354

} else {

355

expandedRoles.add(role);

356

}

357

}

358

359

return super.newUserIdentity(subject, userPrincipal,

360

expandedRoles.toArray(new String[0]));

361

}

362

}

363

}

364

```

365

366

## Identity Association and RunAs

367

368

### Thread Association

369

370

```java { .api }

371

public class ThreadAssociationExample {

372

373

public void demonstrateThreadAssociation() {

374

375

IdentityService identityService = new DefaultIdentityService();

376

377

// Create user identity

378

UserPrincipal user = new UserPrincipal("worker",

379

Credential.getCredential("password"));

380

Subject subject = new Subject();

381

UserIdentity identity = identityService.newUserIdentity(subject, user,

382

new String[]{"worker", "api-user"});

383

384

// Associate with current thread

385

try (IdentityService.Association association =

386

identityService.associate(identity, null)) {

387

388

// Code in this block runs with user identity

389

performSecureOperation();

390

391

// Association is automatically cleaned up when block exits

392

}

393

394

// User identity is no longer associated with thread

395

}

396

397

public void demonstrateRunAs() {

398

399

IdentityService identityService = new DefaultIdentityService();

400

401

// Create regular user

402

UserIdentity regularUser = createUserIdentity("john", "user");

403

404

// Create run-as token for admin role

405

IdentityService.RunAsToken adminToken = identityService.newRunAsToken("admin");

406

407

// Associate regular user but run as admin

408

try (IdentityService.Association association =

409

identityService.associate(regularUser, adminToken)) {

410

411

// Check if admin role is associated with thread

412

boolean isAdmin = DefaultIdentityService.isRoleAssociated("admin");

413

414

// Perform admin operations

415

performAdminOperation();

416

}

417

}

418

419

public void demonstrateNestedAssociations() {

420

421

IdentityService identityService = new DefaultIdentityService();

422

423

UserIdentity user1 = createUserIdentity("alice", "user");

424

UserIdentity user2 = createUserIdentity("bob", "manager");

425

426

try (IdentityService.Association outer = identityService.associate(user1, null)) {

427

428

// Outer context: alice as user

429

performUserOperation();

430

431

try (IdentityService.Association inner = identityService.associate(user2, null)) {

432

433

// Inner context: bob as manager

434

performManagerOperation();

435

436

} // bob's association ends

437

438

// Back to alice's context

439

performUserOperation();

440

441

} // alice's association ends

442

}

443

444

private UserIdentity createUserIdentity(String name, String role) {

445

IdentityService identityService = new DefaultIdentityService();

446

UserPrincipal user = new UserPrincipal(name, Credential.getCredential("password"));

447

Subject subject = new Subject();

448

return identityService.newUserIdentity(subject, user, new String[]{role});

449

}

450

451

private void performSecureOperation() {

452

// Implementation

453

}

454

455

private void performAdminOperation() {

456

// Implementation requiring admin privileges

457

}

458

459

private void performUserOperation() {

460

// Implementation for regular users

461

}

462

463

private void performManagerOperation() {

464

// Implementation for managers

465

}

466

}

467

```

468

469

## RoleDelegateUserIdentity

470

471

### Delegated Role Checking

472

473

```java { .api }

474

public class RoleDelegateUserIdentity implements UserIdentity {

475

476

private final UserIdentity delegate;

477

private final Subject subject;

478

private final Principal userPrincipal;

479

480

// Constructor

481

public RoleDelegateUserIdentity(UserIdentity delegate, Subject subject, Principal userPrincipal);

482

483

@Override

484

public Subject getSubject() {

485

return subject;

486

}

487

488

@Override

489

public Principal getUserPrincipal() {

490

return userPrincipal;

491

}

492

493

@Override

494

public boolean isUserInRole(String role) {

495

496

// Delegate role checking to another UserIdentity

497

return delegate.isUserInRole(role);

498

}

499

}

500

```

501

502

### Role Delegation Usage

503

504

```java { .api }

505

public class RoleDelegationExample {

506

507

public void demonstrateRoleDelegation() {

508

509

// Create primary user identity with roles

510

UserPrincipal primaryUser = new UserPrincipal("primary",

511

Credential.getCredential("password"));

512

Subject primarySubject = new Subject();

513

IdentityService identityService = new DefaultIdentityService();

514

UserIdentity primaryIdentity = identityService.newUserIdentity(primarySubject,

515

primaryUser, new String[]{"admin", "manager", "user"});

516

517

// Create secondary user with different principal but same role checking

518

UserPrincipal secondaryUser = new UserPrincipal("secondary",

519

Credential.getCredential("password"));

520

Subject secondarySubject = new Subject();

521

522

// Create role delegate identity

523

RoleDelegateUserIdentity delegateIdentity = new RoleDelegateUserIdentity(

524

primaryIdentity, // Delegate role checking to primary

525

secondarySubject, // But use secondary subject

526

secondaryUser // And secondary principal

527

);

528

529

// Identity has secondary user's principal

530

String name = delegateIdentity.getUserPrincipal().getName(); // "secondary"

531

532

// But role checking is delegated to primary user

533

boolean isAdmin = delegateIdentity.isUserInRole("admin"); // true (from primary)

534

boolean isManager = delegateIdentity.isUserInRole("manager"); // true (from primary)

535

}

536

537

public void createServiceAccountWithUserRoles() {

538

539

// Create service account identity

540

UserPrincipal serviceAccount = new UserPrincipal("api-service",

541

Credential.getCredential("service-key"));

542

Subject serviceSubject = new Subject();

543

544

// Get user identity to delegate roles from

545

UserIdentity userIdentity = getCurrentUserIdentity(); // Assume this returns current user

546

547

// Create service account that inherits user's roles

548

RoleDelegateUserIdentity serviceIdentity = new RoleDelegateUserIdentity(

549

userIdentity, // Delegate to current user's roles

550

serviceSubject, // Service account subject

551

serviceAccount // Service account principal

552

);

553

554

// Service account can perform operations with user's roles

555

try (IdentityService.Association association =

556

new DefaultIdentityService().associate(serviceIdentity, null)) {

557

558

performServiceOperation();

559

}

560

}

561

562

private UserIdentity getCurrentUserIdentity() {

563

// Implementation to get current user identity

564

return null;

565

}

566

567

private void performServiceOperation() {

568

// Service operation that requires user's roles

569

}

570

}

571

```

572

573

## User Store Integration

574

575

### UserStore Interface

576

577

```java { .api }

578

public interface UserStore {

579

580

// User retrieval

581

UserPrincipal getUserPrincipal(String username);

582

List<RolePrincipal> getRolePrincipals(String username);

583

584

// User management (optional)

585

default void addUser(String username, Credential credential, String[] roles) {

586

throw new UnsupportedOperationException();

587

}

588

589

default void removeUser(String username) {

590

throw new UnsupportedOperationException();

591

}

592

593

default void updateUser(String username, Credential credential, String[] roles) {

594

throw new UnsupportedOperationException();

595

}

596

}

597

```

598

599

### Custom Identity Management

600

601

```java { .api }

602

public class CustomIdentityManager {

603

604

private final IdentityService identityService;

605

private final UserStore userStore;

606

607

public CustomIdentityManager(IdentityService identityService, UserStore userStore) {

608

this.identityService = identityService;

609

this.userStore = userStore;

610

}

611

612

public UserIdentity authenticateUser(String username, String password) {

613

614

// Get user principal from store

615

UserPrincipal userPrincipal = userStore.getUserPrincipal(username);

616

if (userPrincipal == null) {

617

return null;

618

}

619

620

// Authenticate credentials

621

if (!userPrincipal.authenticate(password)) {

622

return null;

623

}

624

625

// Get user roles

626

List<RolePrincipal> rolePrincipals = userStore.getRolePrincipals(username);

627

String[] roles = rolePrincipals.stream()

628

.map(RolePrincipal::getName)

629

.toArray(String[]::new);

630

631

// Create subject and configure

632

Subject subject = new Subject();

633

userPrincipal.configureSubject(subject);

634

for (RolePrincipal role : rolePrincipals) {

635

role.configureSubject(subject);

636

}

637

638

// Create user identity

639

return identityService.newUserIdentity(subject, userPrincipal, roles);

640

}

641

642

public boolean addUser(String username, String password, String... roles) {

643

644

try {

645

// Create credential

646

Credential credential = Credential.getCredential(password);

647

648

// Add to user store

649

userStore.addUser(username, credential, roles);

650

651

return true;

652

653

} catch (Exception e) {

654

logger.error("Failed to add user: " + username, e);

655

return false;

656

}

657

}

658

659

public boolean updateUserRoles(String username, String... newRoles) {

660

661

try {

662

// Get existing user

663

UserPrincipal existing = userStore.getUserPrincipal(username);

664

if (existing == null) {

665

return false;

666

}

667

668

// Update with new roles (keeping same credential)

669

userStore.updateUser(username, existing.getCredential(), newRoles);

670

671

return true;

672

673

} catch (Exception e) {

674

logger.error("Failed to update user roles: " + username, e);

675

return false;

676

}

677

}

678

679

public void logoutUser(UserIdentity user) {

680

681

// Notify identity service of logout

682

identityService.onLogout(user);

683

684

// Additional cleanup if needed

685

performLogoutCleanup(user);

686

}

687

688

private void performLogoutCleanup(UserIdentity user) {

689

// Custom logout cleanup logic

690

}

691

}

692

```

693

694

## Advanced Identity Patterns

695

696

### Composite Identity Service

697

698

```java { .api }

699

public class CompositeIdentityService implements IdentityService {

700

701

private final List<IdentityService> delegates;

702

703

public CompositeIdentityService(IdentityService... delegates) {

704

this.delegates = Arrays.asList(delegates);

705

}

706

707

@Override

708

public Association associate(UserIdentity user, RunAsToken runAsToken) {

709

710

// Associate with all delegates

711

List<Association> associations = delegates.stream()

712

.map(service -> service.associate(user, runAsToken))

713

.collect(Collectors.toList());

714

715

return new CompositeAssociation(associations);

716

}

717

718

@Override

719

public UserIdentity newUserIdentity(Subject subject, Principal userPrincipal, String[] roles) {

720

721

// Use first delegate for identity creation

722

return delegates.get(0).newUserIdentity(subject, userPrincipal, roles);

723

}

724

725

@Override

726

public void onLogout(UserIdentity user) {

727

728

// Notify all delegates

729

delegates.forEach(service -> service.onLogout(user));

730

}

731

732

@Override

733

public RunAsToken newRunAsToken(String roleName) {

734

735

// Create composite run-as token

736

List<RunAsToken> tokens = delegates.stream()

737

.map(service -> service.newRunAsToken(roleName))

738

.collect(Collectors.toList());

739

740

return new CompositeRunAsToken(tokens);

741

}

742

743

@Override

744

public UserIdentity getSystemUserIdentity() {

745

746

// Return system user from first delegate that has one

747

return delegates.stream()

748

.map(IdentityService::getSystemUserIdentity)

749

.filter(Objects::nonNull)

750

.findFirst()

751

.orElse(null);

752

}

753

754

private static class CompositeAssociation implements Association {

755

private final List<Association> associations;

756

757

public CompositeAssociation(List<Association> associations) {

758

this.associations = associations;

759

}

760

761

@Override

762

public void close() {

763

associations.forEach(Association::close);

764

}

765

}

766

767

private static class CompositeRunAsToken implements RunAsToken {

768

private final List<RunAsToken> tokens;

769

770

public CompositeRunAsToken(List<RunAsToken> tokens) {

771

this.tokens = tokens;

772

}

773

}

774

}

775

```

776

777

### Caching Identity Service

778

779

```java { .api }

780

public class CachingIdentityService implements IdentityService {

781

782

private final IdentityService delegate;

783

private final Cache<String, UserIdentity> identityCache;

784

785

public CachingIdentityService(IdentityService delegate, Duration cacheTTL) {

786

this.delegate = delegate;

787

this.identityCache = Caffeine.newBuilder()

788

.maximumSize(1000)

789

.expireAfterWrite(cacheTTL)

790

.build();

791

}

792

793

@Override

794

public UserIdentity newUserIdentity(Subject subject, Principal userPrincipal, String[] roles) {

795

796

String cacheKey = buildCacheKey(userPrincipal, roles);

797

798

return identityCache.get(cacheKey, key ->

799

delegate.newUserIdentity(subject, userPrincipal, roles));

800

}

801

802

@Override

803

public Association associate(UserIdentity user, RunAsToken runAsToken) {

804

return delegate.associate(user, runAsToken);

805

}

806

807

@Override

808

public void onLogout(UserIdentity user) {

809

810

// Invalidate cache entries for this user

811

String username = user.getUserPrincipal().getName();

812

identityCache.asMap().entrySet().removeIf(entry ->

813

entry.getKey().startsWith(username + ":"));

814

815

delegate.onLogout(user);

816

}

817

818

@Override

819

public RunAsToken newRunAsToken(String roleName) {

820

return delegate.newRunAsToken(roleName);

821

}

822

823

@Override

824

public UserIdentity getSystemUserIdentity() {

825

return delegate.getSystemUserIdentity();

826

}

827

828

private String buildCacheKey(Principal userPrincipal, String[] roles) {

829

return userPrincipal.getName() + ":" + Arrays.toString(roles);

830

}

831

}

832

```

833

834

## Best Practices

835

836

### Identity Management Best Practices

837

838

```java { .api }

839

public class IdentityBestPractices {

840

841

public void configureProductionIdentityService() {

842

843

// Use caching for performance

844

IdentityService baseService = new DefaultIdentityService();

845

IdentityService cachingService = new CachingIdentityService(baseService, Duration.ofMinutes(15));

846

847

// Create secure user store

848

UserStore secureStore = createSecureUserStore();

849

850

// Configure identity manager

851

CustomIdentityManager identityManager = new CustomIdentityManager(cachingService, secureStore);

852

853

// Use with security handler

854

SecurityHandler security = new SecurityHandler.PathMapped();

855

security.setIdentityService(cachingService);

856

}

857

858

private UserStore createSecureUserStore() {

859

860

// Use property store with secure defaults

861

PropertyUserStore store = new PropertyUserStore();

862

store.setConfig(Resource.newResource("secure-users.properties"));

863

store.setReloadInterval(300); // 5 minutes

864

865

return store;

866

}

867

868

public void demonstrateSecureIdentityCreation() {

869

870

IdentityService identityService = new DefaultIdentityService();

871

872

// Create user with strong password

873

String strongPassword = generateStrongPassword();

874

UserPrincipal user = new UserPrincipal("alice",

875

Credential.getCredential(strongPassword));

876

877

// Create subject with proper configuration

878

Subject subject = new Subject();

879

user.configureSubject(subject);

880

881

// Add role principals to subject

882

RolePrincipal userRole = new RolePrincipal("user");

883

RolePrincipal appRole = new RolePrincipal("app-user");

884

userRole.configureSubject(subject);

885

appRole.configureSubject(subject);

886

887

// Create identity with minimal necessary roles

888

UserIdentity identity = identityService.newUserIdentity(subject, user,

889

new String[]{"user", "app-user"});

890

891

// Always use try-with-resources for associations

892

try (IdentityService.Association association =

893

identityService.associate(identity, null)) {

894

895

performUserOperation();

896

}

897

}

898

899

private String generateStrongPassword() {

900

// Implementation to generate cryptographically strong password

901

return "StrongPassword123!";

902

}

903

904

private void performUserOperation() {

905

// Implementation

906

}

907

}

908

```

909

910

User Identity Management provides comprehensive support for user principals, roles, thread associations, and secure identity contexts, enabling fine-grained access control and secure execution environments.