or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication-sessions.mdcomponent-framework.mdcore-models.mdcredential-management.mdindex.mdorganization-management.mdprovider-framework.mdsession-management.mduser-storage.mdvalidation-framework.mdvault-integration.md

credential-management.mddocs/

0

# Credential Management

1

2

The credential management framework provides extensible support for various credential types including passwords, OTP tokens, WebAuthn, and custom credential types. It enables validation, storage, and lifecycle management of user credentials.

3

4

## Core Credential Interfaces

5

6

### CredentialProvider

7

8

Base interface for credential providers that manage specific credential types.

9

10

```java { .api }

11

public interface CredentialProvider extends Provider {

12

/**

13

* Gets the credential type handled by this provider.

14

*

15

* @return credential type string

16

*/

17

String getType();

18

19

/**

20

* Creates a credential for a user.

21

*

22

* @param realm the realm

23

* @param user the user

24

* @param credentialModel the credential to create

25

* @return created credential model

26

*/

27

CredentialModel createCredential(RealmModel realm, UserModel user, CredentialModel credentialModel);

28

29

/**

30

* Deletes a credential by ID.

31

*

32

* @param realm the realm

33

* @param user the user

34

* @param credentialId the credential ID

35

* @return true if deleted successfully

36

*/

37

boolean deleteCredential(RealmModel realm, UserModel user, String credentialId);

38

39

/**

40

* Gets a credential from the stored model.

41

*

42

* @param model the stored credential model

43

* @return credential model

44

*/

45

CredentialModel getCredentialFromModel(CredentialModel model);

46

47

/**

48

* Gets the default credential for a user.

49

*

50

* @param realm the realm

51

* @param user the user

52

* @return default credential or null

53

*/

54

default CredentialModel getDefaultCredential(RealmModel realm, UserModel user) {

55

return null;

56

}

57

58

/**

59

* Checks if the credential type is configured for a user.

60

*

61

* @param realm the realm

62

* @param user the user

63

* @return true if configured

64

*/

65

default boolean isConfiguredFor(RealmModel realm, UserModel user) {

66

return false;

67

}

68

69

/**

70

* Gets metadata for credential types.

71

*

72

* @param user the user

73

* @return credential type metadata

74

*/

75

default CredentialTypeMetadata getCredentialTypeMetadata(CredentialTypeMetadataContext metadataContext) {

76

return CredentialTypeMetadata.builder()

77

.type(getType())

78

.category(CredentialTypeMetadata.Category.BASIC_AUTHENTICATION)

79

.helpText("credential." + getType() + ".helpText")

80

.build(session);

81

}

82

}

83

```

84

85

### CredentialInputValidator

86

87

Validates credential input for authentication.

88

89

```java { .api }

90

public interface CredentialInputValidator {

91

/**

92

* Checks if this validator supports the credential type.

93

*

94

* @param credentialType the credential type

95

* @return true if supported

96

*/

97

boolean supportsCredentialType(String credentialType);

98

99

/**

100

* Checks if the credential type is configured for a user.

101

*

102

* @param realm the realm

103

* @param user the user

104

* @param credentialType the credential type

105

* @return true if configured

106

*/

107

boolean isConfiguredFor(RealmModel realm, UserModel user, String credentialType);

108

109

/**

110

* Validates credential input.

111

*

112

* @param realm the realm

113

* @param user the user

114

* @param input the credential input

115

* @return true if valid

116

*/

117

boolean isValid(RealmModel realm, UserModel user, CredentialInput input);

118

}

119

```

120

121

### CredentialInputUpdater

122

123

Updates user credentials.

124

125

```java { .api }

126

public interface CredentialInputUpdater {

127

/**

128

* Checks if this updater supports the credential type.

129

*

130

* @param credentialType the credential type

131

* @return true if supported

132

*/

133

boolean supportsCredentialType(String credentialType);

134

135

/**

136

* Updates a user's credential.

137

*

138

* @param realm the realm

139

* @param user the user

140

* @param input the credential input

141

* @return true if updated successfully

142

*/

143

boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input);

144

145

/**

146

* Disables a credential type for a user.

147

*

148

* @param realm the realm

149

* @param user the user

150

* @param credentialType the credential type to disable

151

*/

152

void disableCredentialType(RealmModel realm, UserModel user, String credentialType);

153

154

/**

155

* Gets disabled credential types for a user.

156

*

157

* @param realm the realm

158

* @param user the user

159

* @return stream of disabled credential types

160

*/

161

default Stream<String> getDisableableCredentialTypesStream(RealmModel realm, UserModel user) {

162

return Stream.empty();

163

}

164

}

165

```

166

167

## Credential Models

168

169

### CredentialModel

170

171

Represents a stored credential.

172

173

```java { .api }

174

public class CredentialModel {

175

public static final String PASSWORD = "password";

176

public static final String PASSWORD_HISTORY = "password-history";

177

public static final String TOTP = "otp";

178

public static final String HOTP = "hotp";

179

public static final String CLIENT_CERT = "cert";

180

public static final String KERBEROS = "kerberos";

181

public static final String SECRET = "secret";

182

public static final String WEBAUTHN = "webauthn";

183

public static final String WEBAUTHN_PASSWORDLESS = "webauthn-passwordless";

184

public static final String RECOVERY_AUTHN_CODES = "recovery-authn-codes";

185

186

private String id;

187

private String type;

188

private String userLabel;

189

private Long createdDate;

190

private String secretData;

191

private String credentialData;

192

193

// Constructors

194

public CredentialModel() {}

195

196

// Getters and setters

197

public String getId() { return id; }

198

public void setId(String id) { this.id = id; }

199

200

public String getType() { return type; }

201

public void setType(String type) { this.type = type; }

202

203

public String getUserLabel() { return userLabel; }

204

public void setUserLabel(String userLabel) { this.userLabel = userLabel; }

205

206

public Long getCreatedDate() { return createdDate; }

207

public void setCreatedDate(Long createdDate) { this.createdDate = createdDate; }

208

209

public String getSecretData() { return secretData; }

210

public void setSecretData(String secretData) { this.secretData = secretData; }

211

212

public String getCredentialData() { return credentialData; }

213

public void setCredentialData(String credentialData) { this.credentialData = credentialData; }

214

215

// Utility methods

216

public boolean challengeResponse(String response) {

217

// Default implementation

218

return false;

219

}

220

221

@Override

222

public boolean equals(Object obj) {

223

if (this == obj) return true;

224

if (obj == null || getClass() != obj.getClass()) return false;

225

CredentialModel that = (CredentialModel) obj;

226

return Objects.equals(id, that.id);

227

}

228

229

@Override

230

public int hashCode() {

231

return Objects.hash(id);

232

}

233

}

234

```

235

236

### CredentialInput

237

238

Interface for credential input during authentication.

239

240

```java { .api }

241

public interface CredentialInput {

242

/**

243

* Gets the credential type.

244

*

245

* @return credential type

246

*/

247

String getType();

248

249

/**

250

* Gets the challenge response.

251

*

252

* @return challenge response

253

*/

254

String getChallengeResponse();

255

256

/**

257

* Gets the credential ID.

258

*

259

* @return credential ID

260

*/

261

default String getCredentialId() {

262

return null;

263

}

264

}

265

```

266

267

## Specific Credential Types

268

269

### Password Credentials

270

271

#### PasswordCredentialModel

272

273

Model for password credentials.

274

275

```java { .api }

276

public class PasswordCredentialModel extends CredentialModel {

277

public static final String TYPE = "password";

278

public static final String PASSWORD_HISTORY = "password-history";

279

280

private PasswordCredentialData credentialData;

281

private PasswordSecretData secretData;

282

283

private PasswordCredentialModel(String credentialId, PasswordCredentialData credentialData, PasswordSecretData secretData) {

284

setId(credentialId);

285

setType(TYPE);

286

setCredentialData(JsonSerialization.writeValueAsString(credentialData));

287

setSecretData(JsonSerialization.writeValueAsString(secretData));

288

setCreatedDate(Time.currentTimeMillis());

289

this.credentialData = credentialData;

290

this.secretData = secretData;

291

}

292

293

public static PasswordCredentialModel createFromValues(String algorithm, byte[] salt, int hashIterations, String encodedPassword) {

294

PasswordCredentialData credentialData = new PasswordCredentialData(hashIterations, algorithm);

295

PasswordSecretData secretData = new PasswordSecretData(encodedPassword, salt);

296

return new PasswordCredentialModel(generateId(), credentialData, secretData);

297

}

298

299

public static PasswordCredentialModel createFromCredentialModel(CredentialModel credential) {

300

try {

301

PasswordCredentialData credentialData = JsonSerialization.readValue(credential.getCredentialData(), PasswordCredentialData.class);

302

PasswordSecretData secretData = JsonSerialization.readValue(credential.getSecretData(), PasswordSecretData.class);

303

PasswordCredentialModel passwordCredentialModel = new PasswordCredentialModel(credential.getId(), credentialData, secretData);

304

passwordCredentialModel.setUserLabel(credential.getUserLabel());

305

passwordCredentialModel.setCreatedDate(credential.getCreatedDate());

306

return passwordCredentialModel;

307

} catch (IOException e) {

308

throw new ModelException(e);

309

}

310

}

311

312

public PasswordCredentialData getPasswordCredentialData() {

313

return credentialData;

314

}

315

316

public PasswordSecretData getPasswordSecretData() {

317

return secretData;

318

}

319

320

private static String generateId() {

321

return KeycloakModelUtils.generateId();

322

}

323

}

324

```

325

326

### OTP Credentials

327

328

#### OTPCredentialModel

329

330

Model for OTP (One-Time Password) credentials.

331

332

```java { .api }

333

public class OTPCredentialModel extends CredentialModel {

334

public static final String TYPE = "otp";

335

public static final String TOTP = "totp";

336

public static final String HOTP = "hotp";

337

338

private OTPCredentialData credentialData;

339

private OTPSecretData secretData;

340

341

private OTPCredentialModel(String credentialId, OTPCredentialData credentialData, OTPSecretData secretData) {

342

setId(credentialId);

343

setType(TYPE);

344

setCredentialData(JsonSerialization.writeValueAsString(credentialData));

345

setSecretData(JsonSerialization.writeValueAsString(secretData));

346

setCreatedDate(Time.currentTimeMillis());

347

this.credentialData = credentialData;

348

this.secretData = secretData;

349

}

350

351

public static OTPCredentialModel createFromPolicy(RealmModel realm, String secretEncodedBase32) {

352

return createFromPolicy(realm, secretEncodedBase32, null);

353

}

354

355

public static OTPCredentialModel createFromPolicy(RealmModel realm, String secretEncodedBase32, String userLabel) {

356

OTPPolicy policy = realm.getOTPPolicy();

357

OTPCredentialData credentialData = new OTPCredentialData(policy.getType(), policy.getDigits(),

358

policy.getPeriod(), policy.getInitialCounter(),

359

policy.getAlgorithm());

360

OTPSecretData secretData = new OTPSecretData(secretEncodedBase32);

361

362

OTPCredentialModel credential = new OTPCredentialModel(generateId(), credentialData, secretData);

363

if (userLabel != null) {

364

credential.setUserLabel(userLabel);

365

}

366

return credential;

367

}

368

369

public static OTPCredentialModel createFromCredentialModel(CredentialModel credential) {

370

try {

371

OTPCredentialData credentialData = JsonSerialization.readValue(credential.getCredentialData(), OTPCredentialData.class);

372

OTPSecretData secretData = JsonSerialization.readValue(credential.getSecretData(), OTPSecretData.class);

373

OTPCredentialModel otpCredentialModel = new OTPCredentialModel(credential.getId(), credentialData, secretData);

374

otpCredentialModel.setUserLabel(credential.getUserLabel());

375

otpCredentialModel.setCreatedDate(credential.getCreatedDate());

376

return otpCredentialModel;

377

} catch (IOException e) {

378

throw new ModelException(e);

379

}

380

}

381

382

public OTPCredentialData getOTPCredentialData() {

383

return credentialData;

384

}

385

386

public OTPSecretData getOTPSecretData() {

387

return secretData;

388

}

389

390

private static String generateId() {

391

return KeycloakModelUtils.generateId();

392

}

393

}

394

```

395

396

### WebAuthn Credentials

397

398

#### WebAuthnCredentialModel

399

400

Model for WebAuthn credentials.

401

402

```java { .api }

403

public class WebAuthnCredentialModel extends CredentialModel {

404

public static final String TYPE_TWOFACTOR = "webauthn";

405

public static final String TYPE_PASSWORDLESS = "webauthn-passwordless";

406

407

private WebAuthnCredentialData credentialData;

408

private WebAuthnSecretData secretData;

409

410

private WebAuthnCredentialModel(String credentialId, WebAuthnCredentialData credentialData, WebAuthnSecretData secretData) {

411

setId(credentialId);

412

setType(TYPE_TWOFACTOR);

413

setCredentialData(JsonSerialization.writeValueAsString(credentialData));

414

setSecretData(JsonSerialization.writeValueAsString(secretData));

415

setCreatedDate(Time.currentTimeMillis());

416

this.credentialData = credentialData;

417

this.secretData = secretData;

418

}

419

420

public static WebAuthnCredentialModel create(String type, String userLabel, String aaguid,

421

String credentialId, String attestationStatementFormat,

422

String attestationStatement, String credentialPublicKey,

423

long counter) {

424

WebAuthnCredentialData credentialData = new WebAuthnCredentialData(aaguid, credentialId,

425

attestationStatementFormat,

426

attestationStatement);

427

WebAuthnSecretData secretData = new WebAuthnSecretData(credentialPublicKey, counter);

428

429

WebAuthnCredentialModel credential = new WebAuthnCredentialModel(generateId(), credentialData, secretData);

430

credential.setType(type);

431

credential.setUserLabel(userLabel);

432

return credential;

433

}

434

435

public static WebAuthnCredentialModel createFromCredentialModel(CredentialModel credential) {

436

try {

437

WebAuthnCredentialData credentialData = JsonSerialization.readValue(credential.getCredentialData(), WebAuthnCredentialData.class);

438

WebAuthnSecretData secretData = JsonSerialization.readValue(credential.getSecretData(), WebAuthnSecretData.class);

439

WebAuthnCredentialModel webAuthnCredentialModel = new WebAuthnCredentialModel(credential.getId(), credentialData, secretData);

440

webAuthnCredentialModel.setType(credential.getType());

441

webAuthnCredentialModel.setUserLabel(credential.getUserLabel());

442

webAuthnCredentialModel.setCreatedDate(credential.getCreatedDate());

443

return webAuthnCredentialModel;

444

} catch (IOException e) {

445

throw new ModelException(e);

446

}

447

}

448

449

public WebAuthnCredentialData getWebAuthnCredentialData() {

450

return credentialData;

451

}

452

453

public WebAuthnSecretData getWebAuthnSecretData() {

454

return secretData;

455

}

456

457

private static String generateId() {

458

return KeycloakModelUtils.generateId();

459

}

460

}

461

```

462

463

## Credential Storage

464

465

### UserCredentialStore

466

467

Interface for credential storage operations.

468

469

```java { .api }

470

public interface UserCredentialStore {

471

/**

472

* Updates a credential for a user.

473

*

474

* @param realm the realm

475

* @param user the user

476

* @param cred the credential to update

477

*/

478

void updateCredential(RealmModel realm, UserModel user, CredentialModel cred);

479

480

/**

481

* Creates a new credential for a user.

482

*

483

* @param realm the realm

484

* @param user the user

485

* @param cred the credential to create

486

* @return created credential

487

*/

488

CredentialModel createCredential(RealmModel realm, UserModel user, CredentialModel cred);

489

490

/**

491

* Removes a credential for a user.

492

*

493

* @param realm the realm

494

* @param user the user

495

* @param id the credential ID

496

* @return true if removed

497

*/

498

boolean removeCredential(RealmModel realm, UserModel user, String id);

499

500

/**

501

* Gets a specific credential for a user.

502

*

503

* @param realm the realm

504

* @param user the user

505

* @param id the credential ID

506

* @return credential or null

507

*/

508

CredentialModel getUserCredentialById(RealmModel realm, UserModel user, String id);

509

510

/**

511

* Gets all credentials for a user.

512

*

513

* @param realm the realm

514

* @param user the user

515

* @return list of credentials

516

*/

517

List<CredentialModel> getStoredCredentials(RealmModel realm, UserModel user);

518

519

/**

520

* Gets credentials of a specific type for a user.

521

*

522

* @param realm the realm

523

* @param user the user

524

* @param type the credential type

525

* @return list of credentials

526

*/

527

List<CredentialModel> getStoredCredentialsByType(RealmModel realm, UserModel user, String type);

528

529

/**

530

* Gets the most recent credential of a type for a user.

531

*

532

* @param realm the realm

533

* @param user the user

534

* @param type the credential type

535

* @return credential or null

536

*/

537

CredentialModel getStoredCredentialByNameAndType(RealmModel realm, UserModel user, String name, String type);

538

539

/**

540

* Moves a credential to a new position in the list.

541

*

542

* @param realm the realm

543

* @param user the user

544

* @param id the credential ID

545

* @param newPosition the new position

546

*/

547

void moveCredentialTo(RealmModel realm, UserModel user, String id, String newPosition);

548

}

549

```

550

551

### SubjectCredentialManager

552

553

Manages credentials for a specific subject (user).

554

555

```java { .api }

556

public interface SubjectCredentialManager {

557

/**

558

* Checks if a credential type is configured.

559

*

560

* @param type the credential type

561

* @return true if configured

562

*/

563

boolean isConfiguredFor(String type);

564

565

/**

566

* Updates a credential.

567

*

568

* @param input the credential input

569

* @return true if updated

570

*/

571

boolean updateCredential(CredentialInput input);

572

573

/**

574

* Updates a stored credential.

575

*

576

* @param cred the credential model

577

*/

578

void updateStoredCredential(CredentialModel cred);

579

580

/**

581

* Creates a stored credential.

582

*

583

* @param cred the credential model

584

* @return created credential

585

*/

586

CredentialModel createStoredCredential(CredentialModel cred);

587

588

/**

589

* Removes a stored credential.

590

*

591

* @param id the credential ID

592

* @return true if removed

593

*/

594

boolean removeStoredCredential(String id);

595

596

/**

597

* Gets a stored credential by ID.

598

*

599

* @param id the credential ID

600

* @return credential or null

601

*/

602

CredentialModel getStoredCredentialById(String id);

603

604

/**

605

* Gets stored credentials by type.

606

*

607

* @param type the credential type

608

* @return stream of credentials

609

*/

610

Stream<CredentialModel> getStoredCredentialsStream(String type);

611

612

/**

613

* Gets all stored credentials.

614

*

615

* @return stream of credentials

616

*/

617

Stream<CredentialModel> getStoredCredentialsStream();

618

619

/**

620

* Disables a credential type.

621

*

622

* @param credentialType the credential type

623

*/

624

void disableCredentialType(String credentialType);

625

626

/**

627

* Gets disableable credential types.

628

*

629

* @return stream of credential types

630

*/

631

Stream<String> getDisableableCredentialTypesStream();

632

633

/**

634

* Checks if a credential input is valid.

635

*

636

* @param input the credential input

637

* @return true if valid

638

*/

639

boolean isValid(CredentialInput input);

640

641

/**

642

* Gets the credential authentication object.

643

*

644

* @return credential authentication

645

*/

646

CredentialAuthentication authenticate(CredentialInput input);

647

648

/**

649

* Moves a credential to a new position.

650

*

651

* @param credentialId the credential ID

652

* @param newPreviousCredentialId the ID of credential that should be before this one

653

*/

654

void moveStoredCredentialTo(String credentialId, String newPreviousCredentialId);

655

656

/**

657

* Creates a credential from user input.

658

*

659

* @param input the credential input

660

* @return created credential

661

*/

662

boolean createCredentialThroughProvider(CredentialInput input);

663

}

664

```

665

666

## Usage Examples

667

668

### Creating a Custom Credential Provider

669

670

```java

671

public class CustomTokenCredentialProvider implements CredentialProvider, CredentialInputValidator, CredentialInputUpdater {

672

public static final String TYPE = "custom-token";

673

674

private final KeycloakSession session;

675

676

public CustomTokenCredentialProvider(KeycloakSession session) {

677

this.session = session;

678

}

679

680

@Override

681

public String getType() {

682

return TYPE;

683

}

684

685

@Override

686

public CredentialModel createCredential(RealmModel realm, UserModel user, CredentialModel credentialModel) {

687

if (!TYPE.equals(credentialModel.getType())) {

688

return null;

689

}

690

691

// Validate and create the credential

692

CredentialModel credential = new CredentialModel();

693

credential.setId(KeycloakModelUtils.generateId());

694

credential.setType(TYPE);

695

credential.setCreatedDate(Time.currentTimeMillis());

696

credential.setSecretData(credentialModel.getSecretData());

697

credential.setCredentialData(credentialModel.getCredentialData());

698

credential.setUserLabel(credentialModel.getUserLabel());

699

700

return session.userCredentialManager().createStoredCredential(realm, user, credential);

701

}

702

703

@Override

704

public boolean deleteCredential(RealmModel realm, UserModel user, String credentialId) {

705

return session.userCredentialManager().removeStoredCredential(realm, user, credentialId);

706

}

707

708

@Override

709

public CredentialModel getCredentialFromModel(CredentialModel model) {

710

return model;

711

}

712

713

@Override

714

public boolean supportsCredentialType(String credentialType) {

715

return TYPE.equals(credentialType);

716

}

717

718

@Override

719

public boolean isConfiguredFor(RealmModel realm, UserModel user, String credentialType) {

720

if (!supportsCredentialType(credentialType)) {

721

return false;

722

}

723

return !session.userCredentialManager()

724

.getStoredCredentialsByTypeStream(realm, user, TYPE)

725

.findFirst().isEmpty();

726

}

727

728

@Override

729

public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) {

730

if (!supportsCredentialType(input.getType())) {

731

return false;

732

}

733

734

String token = input.getChallengeResponse();

735

if (token == null) {

736

return false;

737

}

738

739

// Validate against stored credential

740

List<CredentialModel> credentials = session.userCredentialManager()

741

.getStoredCredentialsByTypeStream(realm, user, TYPE)

742

.collect(Collectors.toList());

743

744

for (CredentialModel credential : credentials) {

745

if (validateToken(token, credential)) {

746

return true;

747

}

748

}

749

750

return false;

751

}

752

753

@Override

754

public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {

755

if (!supportsCredentialType(input.getType())) {

756

return false;

757

}

758

759

// Remove existing credentials of this type

760

session.userCredentialManager()

761

.getStoredCredentialsByTypeStream(realm, user, TYPE)

762

.forEach(cred -> session.userCredentialManager().removeStoredCredential(realm, user, cred.getId()));

763

764

// Create new credential

765

CredentialModel credential = new CredentialModel();

766

credential.setType(TYPE);

767

credential.setSecretData(input.getChallengeResponse());

768

credential.setUserLabel("Custom Token");

769

770

return createCredential(realm, user, credential) != null;

771

}

772

773

@Override

774

public void disableCredentialType(RealmModel realm, UserModel user, String credentialType) {

775

if (!supportsCredentialType(credentialType)) {

776

return;

777

}

778

779

session.userCredentialManager()

780

.getStoredCredentialsByTypeStream(realm, user, TYPE)

781

.forEach(cred -> session.userCredentialManager().removeStoredCredential(realm, user, cred.getId()));

782

}

783

784

@Override

785

public Stream<String> getDisableableCredentialTypesStream(RealmModel realm, UserModel user) {

786

if (isConfiguredFor(realm, user, TYPE)) {

787

return Stream.of(TYPE);

788

}

789

return Stream.empty();

790

}

791

792

@Override

793

public void close() {

794

// Cleanup resources

795

}

796

797

private boolean validateToken(String inputToken, CredentialModel credential) {

798

String storedToken = credential.getSecretData();

799

return inputToken.equals(storedToken);

800

}

801

}

802

```

803

804

### Using Credential Management

805

806

```java

807

// Working with user credentials

808

try (KeycloakSession session = sessionFactory.create()) {

809

RealmModel realm = session.realms().getRealmByName("myrealm");

810

UserModel user = session.users().getUserByUsername(realm, "john");

811

812

// Get user's credential manager

813

SubjectCredentialManager credManager = user.credentialManager();

814

815

// Check if password is configured

816

boolean hasPassword = credManager.isConfiguredFor(PasswordCredentialModel.TYPE);

817

818

// Validate password

819

PasswordUserCredentialModel passwordInput = new PasswordUserCredentialModel("password123");

820

boolean isValid = credManager.isValid(passwordInput);

821

822

// Update password

823

boolean updated = credManager.updateCredential(passwordInput);

824

825

// Get all stored credentials

826

List<CredentialModel> allCredentials = credManager.getStoredCredentialsStream()

827

.collect(Collectors.toList());

828

829

// Get OTP credentials

830

List<CredentialModel> otpCredentials = credManager

831

.getStoredCredentialsStream(OTPCredentialModel.TYPE)

832

.collect(Collectors.toList());

833

834

// Remove a specific credential

835

if (!otpCredentials.isEmpty()) {

836

credManager.removeStoredCredential(otpCredentials.get(0).getId());

837

}

838

}

839

```

840

841

### Creating OTP Credentials

842

843

```java

844

// Setup OTP for a user

845

try (KeycloakSession session = sessionFactory.create()) {

846

RealmModel realm = session.realms().getRealmByName("myrealm");

847

UserModel user = session.users().getUserByUsername(realm, "alice");

848

849

// Generate secret

850

String secret = Base32.random();

851

852

// Create OTP credential from realm policy

853

OTPCredentialModel otpCredential = OTPCredentialModel.createFromPolicy(realm, secret, "My Authenticator");

854

855

// Store the credential

856

user.credentialManager().createStoredCredential(otpCredential);

857

858

// Generate QR code URL for user setup

859

String issuer = realm.getDisplayName() != null ? realm.getDisplayName() : realm.getName();

860

String qrUrl = String.format("otpauth://totp/%s:%s?secret=%s&issuer=%s",

861

issuer, user.getUsername(), secret, issuer);

862

}

863

```

864

865

### Creating Password Credentials

866

867

```java

868

// Set user password

869

try (KeycloakSession session = sessionFactory.create()) {

870

RealmModel realm = session.realms().getRealmByName("myrealm");

871

UserModel user = session.users().getUserByUsername(realm, "bob");

872

873

// Use the password credential input to set password

874

PasswordUserCredentialModel passwordInput = new PasswordUserCredentialModel("newPassword123");

875

boolean success = user.credentialManager().updateCredential(passwordInput);

876

877

if (success) {

878

System.out.println("Password updated successfully");

879

}

880

}

881

```

882

883

### Custom Password Hashing

884

885

```java

886

// Create password credential with custom hashing

887

try (KeycloakSession session = sessionFactory.create()) {

888

RealmModel realm = session.realms().getRealmByName("myrealm");

889

UserModel user = session.users().getUserByUsername(realm, "charlie");

890

891

// Hash password with custom parameters

892

String algorithm = "pbkdf2-sha256";

893

int iterations = 100000;

894

byte[] salt = SecretGenerator.getInstance().randomBytes(16);

895

String hashedPassword = Pbkdf2PasswordEncoder.encode("password123", salt, iterations);

896

897

// Create password credential

898

PasswordCredentialModel passwordCredential = PasswordCredentialModel.createFromValues(

899

algorithm, salt, iterations, hashedPassword);

900

901

// Store the credential

902

user.credentialManager().createStoredCredential(passwordCredential);

903

}

904

```