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

organization-management.mddocs/

0

# Organization Management

1

2

Organization management provides multi-tenant capabilities within Keycloak, allowing for the creation and management of organizations with their own members, identity providers, and domain-based authentication routing. This SPI enables enterprise scenarios where multiple organizations share a single Keycloak realm while maintaining organizational boundaries.

3

4

## Capabilities

5

6

### Organization Provider

7

8

The primary interface for managing organizations and their associated data within a realm.

9

10

```java { .api }

11

/**

12

* A Provider that manages organization and its data within the scope of a realm.

13

*/

14

public interface OrganizationProvider extends Provider {

15

16

/**

17

* Creates a new organization with given name and alias to the realm.

18

* @param name the name of the organization

19

* @param alias the alias of the organization. If not set, defaults to name. Once set, the alias is immutable

20

* @throws ModelDuplicateException If there is already an organization with the given name or alias

21

* @return Model of the created organization

22

*/

23

OrganizationModel create(String name, String alias);

24

25

/**

26

* Creates a new organization with given id, name, and alias to the realm

27

* @param id the id of the organization

28

* @param name the name of the organization

29

* @param alias the alias of the organization

30

* @throws ModelDuplicateException If there is already an organization with the given name or alias

31

* @return Model of the created organization

32

*/

33

OrganizationModel create(String id, String name, String alias);

34

35

/**

36

* Returns an OrganizationModel by its id

37

* @param id the id of an organization

38

* @return the organization with the given id or null if there is no such organization

39

*/

40

OrganizationModel getById(String id);

41

42

/**

43

* Returns an OrganizationModel by its internet domain

44

* @param domainName the organization's internet domain (e.g. redhat.com)

45

* @return the organization that is linked to the given internet domain

46

*/

47

OrganizationModel getByDomainName(String domainName);

48

49

/**

50

* Returns an OrganizationModel with the given alias

51

* @param alias the alias

52

* @return the organization

53

*/

54

OrganizationModel getByAlias(String alias);

55

56

/**

57

* Returns all organizations in the realm

58

* @return a Stream of the realm's organizations

59

*/

60

Stream<OrganizationModel> getAllStream();

61

62

/**

63

* Returns all organizations in the realm filtered according to the specified parameters

64

* @param search a String representing either an organization name or domain

65

* @param exact if true, organizations will be searched using exact match

66

* @param first the position of the first result to be processed (pagination offset)

67

* @param max the maximum number of results to be returned

68

* @return a Stream of the matched organizations

69

*/

70

Stream<OrganizationModel> getAllStream(String search, Boolean exact, Integer first, Integer max);

71

72

/**

73

* Returns all organizations in the realm filtered according to the specified parameters

74

* @param attributes a Map containing the attributes (name/value) that must match organization attributes

75

* @param first the position of the first result to be processed (pagination offset)

76

* @param max the maximum number of results to be returned

77

* @return a Stream of the matched organizations

78

*/

79

Stream<OrganizationModel> getAllStream(Map<String, String> attributes, Integer first, Integer max);

80

81

/**

82

* Removes the given organization from the realm together with the data associated with it

83

* @param organization Organization to be removed

84

* @throws ModelException if the organization doesn't exist or doesn't belong to the realm

85

* @return true if the organization was removed, false otherwise

86

*/

87

boolean remove(OrganizationModel organization);

88

89

/**

90

* Removes all organizations from the realm

91

*/

92

void removeAll();

93

94

/**

95

* Returns number of organizations in the realm

96

* @return Number of organizations

97

*/

98

long count();

99

100

/**

101

* Indicates if the current realm supports organization

102

* @return true if organization is supported, false otherwise

103

*/

104

boolean isEnabled();

105

}

106

```

107

108

### Organization Member Management

109

110

Comprehensive member management with support for both managed and unmanaged members.

111

112

```java { .api }

113

public interface OrganizationProvider extends Provider {

114

115

/**

116

* Adds the given UserModel as a managed member of the given OrganizationModel.

117

* @param organization the organization

118

* @param user the user

119

* @throws ModelException if the UserModel is member of different organization

120

* @return true if the user was added as a member, false otherwise

121

*/

122

boolean addManagedMember(OrganizationModel organization, UserModel user);

123

124

/**

125

* Adds the given UserModel as an unmanaged member of the given OrganizationModel.

126

* @param organization the organization

127

* @param user the user

128

* @throws ModelException if the UserModel is member of different organization

129

* @return true if the user was added as a member, false otherwise

130

*/

131

boolean addMember(OrganizationModel organization, UserModel user);

132

133

/**

134

* Returns the members of a given OrganizationModel filtered according to the specified filters.

135

* @param organization the organization

136

* @param filters Map containing filters for member search

137

* @param exact if true, exact match for filters

138

* @param first the position of the first result (pagination offset)

139

* @param max the maximum number of results to be returned

140

* @return Stream of the members

141

*/

142

Stream<UserModel> getMembersStream(OrganizationModel organization, Map<String, String> filters, Boolean exact, Integer first, Integer max);

143

144

/**

145

* Returns number of members in the organization

146

* @param organization the organization

147

* @return Number of members in the organization

148

*/

149

long getMembersCount(OrganizationModel organization);

150

151

/**

152

* Returns the member of the OrganizationModel by its id

153

* @param organization the organization

154

* @param id the member id

155

* @return the member of the OrganizationModel with the given id

156

*/

157

UserModel getMemberById(OrganizationModel organization, String id);

158

159

/**

160

* Returns the OrganizationModel that the member belongs to

161

* @param member the member of an organization

162

* @return the organizations the member belongs to or an empty stream if the user doesn't belong to any

163

*/

164

Stream<OrganizationModel> getByMember(UserModel member);

165

166

/**

167

* Indicates if the given member is managed by the organization.

168

* A member is managed by the organization whenever the member cannot exist without the organization

169

* @param organization the organization

170

* @param member the member

171

* @return true if the member is managed by the given organization

172

*/

173

boolean isManagedMember(OrganizationModel organization, UserModel member);

174

175

/**

176

* Indicates if the given user is a member of the given organization

177

* @param organization the organization

178

* @param user the member

179

* @return true if the user is a member, false otherwise

180

*/

181

boolean isMember(OrganizationModel organization, UserModel user);

182

183

/**

184

* Removes a member from the organization.

185

* This method can either remove the given member entirely from the realm or only remove the link to the organization.

186

* The decision depends on whether the user is managed by the organization or not.

187

* @param organization the organization

188

* @param member the member

189

* @return true if the given member is a member and was successfully removed from the organization

190

*/

191

boolean removeMember(OrganizationModel organization, UserModel member);

192

}

193

```

194

195

### Identity Provider Association

196

197

Associate identity providers with organizations for automatic user routing and federated authentication.

198

199

```java { .api }

200

public interface OrganizationProvider extends Provider {

201

202

/**

203

* Associate the given IdentityProviderModel with the given OrganizationModel

204

* @param organization the organization

205

* @param identityProvider the identityProvider

206

* @return true if the identityProvider was associated with the organization, false otherwise

207

*/

208

boolean addIdentityProvider(OrganizationModel organization, IdentityProviderModel identityProvider);

209

210

/**

211

* Returns Stream of the identity providers associated with the given organization

212

* @param organization the organization

213

* @return Stream of the identity providers associated with the organization

214

*/

215

Stream<IdentityProviderModel> getIdentityProviders(OrganizationModel organization);

216

217

/**

218

* Removes the link between the given OrganizationModel and the identity provider if such a link exists

219

* @param organization the organization

220

* @param identityProvider the identity provider

221

* @return true if the link was removed, false otherwise

222

*/

223

boolean removeIdentityProvider(OrganizationModel organization, IdentityProviderModel identityProvider);

224

}

225

```

226

227

### Organization Model

228

229

The core model representing an organization with its attributes, domains, and configuration.

230

231

```java { .api }

232

/**

233

* Model representation of an organization within a realm.

234

*/

235

public interface OrganizationModel {

236

237

String ORGANIZATION_ATTRIBUTE = "kc.org";

238

String ORGANIZATION_NAME_ATTRIBUTE = "kc.org.name";

239

String ORGANIZATION_DOMAIN_ATTRIBUTE = "kc.org.domain";

240

String ALIAS = "alias";

241

242

/**

243

* Identity provider redirect modes for organization-based routing.

244

*/

245

enum IdentityProviderRedirectMode {

246

EMAIL_MATCH("kc.org.broker.redirect.mode.email-matches");

247

248

private final String key;

249

250

IdentityProviderRedirectMode(String key) {

251

this.key = key;

252

}

253

254

public boolean isSet(IdentityProviderModel broker) {

255

return Boolean.parseBoolean(broker.getConfig().get(key));

256

}

257

258

public String getKey() {

259

return key;

260

}

261

}

262

263

/**

264

* Returns the unique identifier of the organization

265

* @return the organization ID

266

*/

267

String getId();

268

269

/**

270

* Sets the name of the organization

271

* @param name the organization name

272

*/

273

void setName(String name);

274

275

/**

276

* Returns the name of the organization

277

* @return the organization name

278

*/

279

String getName();

280

281

/**

282

* Returns the alias of the organization

283

* @return the organization alias

284

*/

285

String getAlias();

286

287

/**

288

* Sets the alias of the organization

289

* @param alias the organization alias

290

*/

291

void setAlias(String alias);

292

293

/**

294

* Returns whether the organization is enabled

295

* @return true if enabled, false otherwise

296

*/

297

boolean isEnabled();

298

299

/**

300

* Sets whether the organization is enabled

301

* @param enabled true to enable, false to disable

302

*/

303

void setEnabled(boolean enabled);

304

305

/**

306

* Returns the description of the organization

307

* @return the organization description

308

*/

309

String getDescription();

310

311

/**

312

* Sets the description of the organization

313

* @param description the organization description

314

*/

315

void setDescription(String description);

316

317

/**

318

* Returns the redirect URL for the organization

319

* @return the redirect URL

320

*/

321

String getRedirectUrl();

322

323

/**

324

* Sets the redirect URL for the organization

325

* @param redirectUrl the redirect URL

326

*/

327

void setRedirectUrl(String redirectUrl);

328

329

/**

330

* Returns the organization's attributes

331

* @return Map of organization attributes

332

*/

333

Map<String, List<String>> getAttributes();

334

335

/**

336

* Sets the organization's attributes

337

* @param attributes Map of organization attributes

338

*/

339

void setAttributes(Map<String, List<String>> attributes);

340

341

/**

342

* Returns the domains associated with the organization

343

* @return Stream of organization domains

344

*/

345

Stream<OrganizationDomainModel> getDomains();

346

347

/**

348

* Sets the domains associated with the organization

349

* @param domains Set of organization domains

350

*/

351

void setDomains(Set<OrganizationDomainModel> domains);

352

353

/**

354

* Returns the identity providers associated with the organization

355

* @return Stream of identity providers

356

*/

357

Stream<IdentityProviderModel> getIdentityProviders();

358

359

/**

360

* Indicates if the given user is managed by the organization

361

* @param user the user

362

* @return true if the user is managed by the organization

363

*/

364

boolean isManaged(UserModel user);

365

366

/**

367

* Indicates if the given user is a member of the organization

368

* @param user the user

369

* @return true if the user is a member of the organization

370

*/

371

boolean isMember(UserModel user);

372

}

373

```

374

375

### Organization Domain Model

376

377

Model representing internet domains associated with organizations for email-based routing and verification.

378

379

```java { .api }

380

/**

381

* Model implementation of an organization internet domain.

382

*/

383

public class OrganizationDomainModel implements Serializable {

384

385

/**

386

* Value used to link an identity provider with all domains from the organization.

387

* If the user's email domain matches any of the organization domains, automatic redirection will be performed.

388

*/

389

public static final String ANY_DOMAIN = "ANY";

390

391

/**

392

* Creates a new domain model with the given name (unverified by default)

393

* @param name the domain name

394

*/

395

public OrganizationDomainModel(String name);

396

397

/**

398

* Creates a new domain model with the given name and verification status

399

* @param name the domain name

400

* @param verified whether the domain is verified

401

*/

402

public OrganizationDomainModel(String name, boolean verified);

403

404

/**

405

* Returns the domain name

406

* @return the domain name

407

*/

408

public String getName();

409

410

/**

411

* Returns whether the domain is verified

412

* @return true if verified, false otherwise

413

*/

414

public boolean isVerified();

415

}

416

```

417

418

### Organization Events

419

420

Event interfaces for organization membership lifecycle management.

421

422

```java { .api }

423

public interface OrganizationModel {

424

425

/**

426

* Base interface for organization membership events

427

*/

428

interface OrganizationMembershipEvent extends ProviderEvent {

429

OrganizationModel getOrganization();

430

UserModel getUser();

431

KeycloakSession getSession();

432

}

433

434

/**

435

* Event fired when a user joins an organization

436

*/

437

interface OrganizationMemberJoinEvent extends OrganizationMembershipEvent {

438

static void fire(OrganizationModel organization, UserModel user, KeycloakSession session);

439

}

440

441

/**

442

* Event fired when a user leaves an organization

443

*/

444

interface OrganizationMemberLeaveEvent extends OrganizationMembershipEvent {

445

static void fire(OrganizationModel organization, UserModel user, KeycloakSession session);

446

}

447

}

448

```

449

450

## Usage Examples

451

452

### Creating and Managing Organizations

453

454

```java

455

import org.keycloak.organization.OrganizationProvider;

456

import org.keycloak.models.OrganizationModel;

457

import org.keycloak.models.OrganizationDomainModel;

458

import org.keycloak.models.KeycloakSession;

459

460

public class OrganizationManagementExample {

461

462

public void createOrganization(KeycloakSession session) {

463

OrganizationProvider provider = session.getProvider(OrganizationProvider.class);

464

465

// Create a new organization

466

OrganizationModel org = provider.create("Example Corp", "example-corp");

467

org.setDescription("Example Corporation for demonstrating organization management");

468

org.setEnabled(true);

469

470

// Add domains to the organization

471

Set<OrganizationDomainModel> domains = new HashSet<>();

472

domains.add(new OrganizationDomainModel("example.com", true)); // verified domain

473

domains.add(new OrganizationDomainModel("example.org", false)); // unverified domain

474

org.setDomains(domains);

475

476

// Set custom attributes

477

Map<String, List<String>> attributes = new HashMap<>();

478

attributes.put("industry", Arrays.asList("Technology"));

479

attributes.put("size", Arrays.asList("Enterprise"));

480

org.setAttributes(attributes);

481

}

482

483

public void findOrganizationByDomain(KeycloakSession session, String email) {

484

OrganizationProvider provider = session.getProvider(OrganizationProvider.class);

485

486

// Extract domain from email

487

String domain = email.substring(email.indexOf("@") + 1);

488

489

// Find organization by domain

490

OrganizationModel org = provider.getByDomainName(domain);

491

if (org != null) {

492

System.out.println("Found organization: " + org.getName());

493

}

494

}

495

}

496

```

497

498

### Managing Organization Members

499

500

```java

501

public class OrganizationMembershipExample {

502

503

public void manageMembership(KeycloakSession session, RealmModel realm) {

504

OrganizationProvider provider = session.getProvider(OrganizationProvider.class);

505

OrganizationModel org = provider.getByAlias("example-corp");

506

507

// Add a managed member (lifecycle bound to organization)

508

UserModel managedUser = session.users().getUserByEmail(realm, "employee@example.com");

509

if (managedUser != null) {

510

provider.addManagedMember(org, managedUser);

511

}

512

513

// Add an unmanaged member (existing user joining organization)

514

UserModel unmanagedUser = session.users().getUserByEmail(realm, "partner@otherdomain.com");

515

if (unmanagedUser != null) {

516

provider.addMember(org, unmanagedUser);

517

}

518

519

// Search members with filters

520

Map<String, String> filters = new HashMap<>();

521

filters.put(UserModel.SEARCH, "john");

522

filters.put(MembershipType.NAME, MembershipType.MANAGED.name());

523

524

Stream<UserModel> managedMembers = provider.getMembersStream(org, filters, false, 0, 10);

525

managedMembers.forEach(user -> {

526

System.out.println("Managed member: " + user.getEmail());

527

});

528

529

// Get member count

530

long memberCount = provider.getMembersCount(org);

531

System.out.println("Total members: " + memberCount);

532

}

533

534

public void checkMembershipStatus(KeycloakSession session, UserModel user) {

535

OrganizationProvider provider = session.getProvider(OrganizationProvider.class);

536

537

// Find all organizations the user belongs to

538

Stream<OrganizationModel> userOrganizations = provider.getByMember(user);

539

userOrganizations.forEach(org -> {

540

boolean isManaged = provider.isManagedMember(org, user);

541

System.out.println("User is " + (isManaged ? "managed" : "unmanaged") +

542

" member of " + org.getName());

543

});

544

}

545

}

546

```

547

548

### Identity Provider Association

549

550

```java

551

public class OrganizationIdentityProviderExample {

552

553

public void associateIdentityProvider(KeycloakSession session, RealmModel realm) {

554

OrganizationProvider provider = session.getProvider(OrganizationProvider.class);

555

OrganizationModel org = provider.getByAlias("example-corp");

556

557

// Get an identity provider

558

IdentityProviderModel idp = realm.getIdentityProviderByAlias("corporate-saml");

559

560

if (idp != null) {

561

// Associate identity provider with organization

562

boolean associated = provider.addIdentityProvider(org, idp);

563

564

if (associated) {

565

// Configure email-based routing

566

Map<String, String> config = idp.getConfig();

567

config.put(OrganizationModel.IdentityProviderRedirectMode.EMAIL_MATCH.getKey(), "true");

568

idp.setConfig(config);

569

570

realm.updateIdentityProvider(idp);

571

System.out.println("Identity provider associated with organization");

572

}

573

}

574

575

// List all identity providers for the organization

576

Stream<IdentityProviderModel> orgIdps = provider.getIdentityProviders(org);

577

orgIdps.forEach(identityProvider -> {

578

System.out.println("Organization uses IDP: " + identityProvider.getAlias());

579

});

580

}

581

}

582

```

583

584

### Organization Search and Filtering

585

586

```java

587

public class OrganizationSearchExample {

588

589

public void searchOrganizations(KeycloakSession session) {

590

OrganizationProvider provider = session.getProvider(OrganizationProvider.class);

591

592

// Search by name or domain

593

Stream<OrganizationModel> searchResults = provider.getAllStream("example", false, 0, 10);

594

searchResults.forEach(org -> {

595

System.out.println("Found: " + org.getName() + " (" + org.getAlias() + ")");

596

});

597

598

// Search by attributes

599

Map<String, String> attributes = new HashMap<>();

600

attributes.put("industry", "Technology");

601

Stream<OrganizationModel> attrResults = provider.getAllStream(attributes, 0, 10);

602

603

// Get organization count

604

long totalOrgs = provider.count();

605

System.out.println("Total organizations: " + totalOrgs);

606

607

// Check if organizations are enabled in the realm

608

boolean orgEnabled = provider.isEnabled();

609

System.out.println("Organizations enabled: " + orgEnabled);

610

}

611

}

612

```

613

614

Organization management provides a comprehensive framework for multi-tenant scenarios, enabling domain-based user routing, federated identity integration, and hierarchical membership management within Keycloak realms.