or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

adaptive-authentication.mdauthentication-handlers.mdauthentication-policies.mdcredential-handling.mdindex.mdpassword-policies.mdprincipal-resolution.md

authentication-handlers.mddocs/

0

# Authentication Handlers

1

2

Authentication handlers are core components responsible for validating credentials against various authentication sources such as LDAP directories, databases, web services, and local user stores. The CAS authentication API provides a comprehensive framework for implementing and configuring authentication handlers.

3

4

## Core Handler Interface

5

6

```java { .api }

7

package org.apereo.cas.authentication;

8

9

import java.security.GeneralSecurityException;

10

11

public interface AuthenticationHandler {

12

String getName();

13

boolean supports(Credential credential);

14

AuthenticationHandlerExecutionResult authenticate(Credential credential)

15

throws GeneralSecurityException, PreventedException;

16

Integer getOrder();

17

AuthenticationHandlerStates getState();

18

void setState(AuthenticationHandlerStates state);

19

Predicate<Credential> getCredentialSelectionPredicate();

20

}

21

```

22

23

## Base Handler Implementation

24

25

```java { .api }

26

package org.apereo.cas.authentication;

27

28

import org.apereo.cas.authentication.principal.PrincipalFactory;

29

import org.apereo.cas.services.ServicesManager;

30

31

public abstract class AbstractAuthenticationHandler implements AuthenticationHandler {

32

protected final PrincipalFactory principalFactory;

33

private final ServicesManager servicesManager;

34

private final String name;

35

private final Integer order;

36

private AuthenticationHandlerStates state;

37

38

protected AbstractAuthenticationHandler(String name,

39

ServicesManager servicesManager,

40

PrincipalFactory principalFactory,

41

Integer order) {

42

this.name = name;

43

this.servicesManager = servicesManager;

44

this.principalFactory = principalFactory;

45

this.order = order;

46

this.state = AuthenticationHandlerStates.ACTIVE;

47

}

48

49

public String getName() { return name; }

50

public Integer getOrder() { return order; }

51

public AuthenticationHandlerStates getState() { return state; }

52

public void setState(AuthenticationHandlerStates state) { this.state = state; }

53

54

protected ServicesManager getServicesManager() { return servicesManager; }

55

protected PrincipalFactory getPrincipalFactory() { return principalFactory; }

56

}

57

```

58

59

## Username/Password Authentication

60

61

### Abstract Username/Password Handler

62

63

```java { .api }

64

package org.apereo.cas.authentication.handler.support;

65

66

import org.apereo.cas.authentication.AbstractAuthenticationHandler;

67

import org.apereo.cas.authentication.AuthenticationHandlerExecutionResult;

68

import org.apereo.cas.authentication.Credential;

69

import org.apereo.cas.authentication.credential.UsernamePasswordCredential;

70

import org.apereo.cas.authentication.principal.PrincipalFactory;

71

import org.apereo.cas.services.ServicesManager;

72

73

public abstract class AbstractUsernamePasswordAuthenticationHandler

74

extends AbstractAuthenticationHandler {

75

76

protected AbstractUsernamePasswordAuthenticationHandler(String name,

77

ServicesManager servicesManager,

78

PrincipalFactory principalFactory,

79

Integer order) {

80

super(name, servicesManager, principalFactory, order);

81

}

82

83

public boolean supports(Credential credential) {

84

return credential instanceof UsernamePasswordCredential;

85

}

86

87

public final AuthenticationHandlerExecutionResult authenticate(Credential credential)

88

throws GeneralSecurityException, PreventedException {

89

90

UsernamePasswordCredential usernamePasswordCredential = (UsernamePasswordCredential) credential;

91

String originalPassword = usernamePasswordCredential.toPassword();

92

93

AuthenticationHandlerExecutionResult result =

94

authenticateUsernamePasswordInternal(usernamePasswordCredential, originalPassword);

95

96

return result;

97

}

98

99

protected abstract AuthenticationHandlerExecutionResult

100

authenticateUsernamePasswordInternal(UsernamePasswordCredential credential,

101

String originalPassword)

102

throws GeneralSecurityException, PreventedException;

103

}

104

```

105

106

### Accept Users Handler

107

108

Simple handler that authenticates against a predefined map of users and passwords:

109

110

```java { .api }

111

package org.apereo.cas.authentication;

112

113

import org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;

114

import org.apereo.cas.authentication.principal.PrincipalFactory;

115

import org.apereo.cas.services.ServicesManager;

116

117

import java.util.Map;

118

119

public class AcceptUsersAuthenticationHandler

120

extends AbstractUsernamePasswordAuthenticationHandler {

121

122

private Map<String, String> users;

123

124

public AcceptUsersAuthenticationHandler(Map<String, String> users) {

125

this(AcceptUsersAuthenticationHandler.class.getSimpleName(),

126

null, new DefaultPrincipalFactory(), null, users);

127

}

128

129

public AcceptUsersAuthenticationHandler(String name,

130

ServicesManager servicesManager,

131

PrincipalFactory principalFactory,

132

Integer order,

133

Map<String, String> users) {

134

super(name, servicesManager, principalFactory, order);

135

this.users = users;

136

}

137

138

protected AuthenticationHandlerExecutionResult

139

authenticateUsernamePasswordInternal(UsernamePasswordCredential credential,

140

String originalPassword)

141

throws GeneralSecurityException {

142

143

String username = credential.getUsername();

144

String password = credential.toPassword();

145

146

String expectedPassword = users.get(username);

147

if (expectedPassword != null && expectedPassword.equals(password)) {

148

Principal principal = principalFactory.createPrincipal(username);

149

return createHandlerResult(credential, principal, null);

150

}

151

152

throw new FailedLoginException();

153

}

154

155

public void setUsers(Map<String, String> users) {

156

this.users = users;

157

}

158

}

159

```

160

161

## Pre/Post Processing Handler

162

163

```java { .api }

164

package org.apereo.cas.authentication.handler.support;

165

166

import org.apereo.cas.authentication.AbstractAuthenticationHandler;

167

import org.apereo.cas.authentication.AuthenticationHandlerExecutionResult;

168

import org.apereo.cas.authentication.Credential;

169

import org.apereo.cas.authentication.PreventedException;

170

171

import java.security.GeneralSecurityException;

172

173

public abstract class AbstractPreAndPostProcessingAuthenticationHandler

174

extends AbstractAuthenticationHandler {

175

176

protected AbstractPreAndPostProcessingAuthenticationHandler(String name,

177

ServicesManager servicesManager,

178

PrincipalFactory principalFactory,

179

Integer order) {

180

super(name, servicesManager, principalFactory, order);

181

}

182

183

public final AuthenticationHandlerExecutionResult authenticate(Credential credential)

184

throws GeneralSecurityException, PreventedException {

185

186

if (!preProcess(credential)) {

187

throw new PreventedException("Pre-processing failed");

188

}

189

190

try {

191

AuthenticationHandlerExecutionResult result = doAuthentication(credential);

192

if (!postProcess(credential, result)) {

193

throw new PreventedException("Post-processing failed");

194

}

195

return result;

196

} catch (Exception e) {

197

handleAuthenticationException(credential, e);

198

throw e;

199

}

200

}

201

202

protected boolean preProcess(Credential credential) { return true; }

203

protected boolean postProcess(Credential credential,

204

AuthenticationHandlerExecutionResult result) { return true; }

205

protected void handleAuthenticationException(Credential credential, Exception e) { }

206

207

protected abstract AuthenticationHandlerExecutionResult doAuthentication(Credential credential)

208

throws GeneralSecurityException, PreventedException;

209

}

210

```

211

212

## Proxy Authentication Handler

213

214

```java { .api }

215

package org.apereo.cas.authentication.handler.support;

216

217

import org.apereo.cas.authentication.AbstractAuthenticationHandler;

218

import org.apereo.cas.authentication.AuthenticationHandlerExecutionResult;

219

import org.apereo.cas.authentication.Credential;

220

import org.apereo.cas.authentication.credential.HttpBasedServiceCredential;

221

import org.apereo.cas.authentication.principal.PrincipalFactory;

222

import org.apereo.cas.services.ServicesManager;

223

224

public class ProxyAuthenticationHandler extends AbstractAuthenticationHandler {

225

226

public ProxyAuthenticationHandler(String name,

227

ServicesManager servicesManager,

228

PrincipalFactory principalFactory,

229

Integer order) {

230

super(name, servicesManager, principalFactory, order);

231

}

232

233

public boolean supports(Credential credential) {

234

return credential instanceof HttpBasedServiceCredential;

235

}

236

237

public AuthenticationHandlerExecutionResult authenticate(Credential credential)

238

throws GeneralSecurityException, PreventedException {

239

240

HttpBasedServiceCredential httpCredential = (HttpBasedServiceCredential) credential;

241

242

if (httpCredential.getService() != null && httpCredential.getCallbackUrl() != null) {

243

Principal principal = principalFactory.createPrincipal(httpCredential.getId());

244

return createHandlerResult(credential, principal, null);

245

}

246

247

throw new FailedLoginException("Invalid HTTP-based service credential");

248

}

249

}

250

```

251

252

## Handler Resolvers

253

254

Handler resolvers determine which authentication handlers should be used for specific authentication requests.

255

256

### Default Handler Resolver

257

258

```java { .api }

259

package org.apereo.cas.authentication.handler;

260

261

import org.apereo.cas.authentication.AuthenticationHandler;

262

import org.apereo.cas.authentication.AuthenticationTransaction;

263

264

import java.util.Set;

265

266

public interface AuthenticationHandlerResolver {

267

Set<AuthenticationHandler> resolve(Set<AuthenticationHandler> candidateHandlers,

268

AuthenticationTransaction transaction);

269

boolean supports(Set<AuthenticationHandler> handlers,

270

AuthenticationTransaction transaction);

271

}

272

273

public class DefaultAuthenticationHandlerResolver implements AuthenticationHandlerResolver {

274

275

public Set<AuthenticationHandler> resolve(Set<AuthenticationHandler> candidateHandlers,

276

AuthenticationTransaction transaction) {

277

return candidateHandlers.stream()

278

.filter(handler -> handler.getState() == AuthenticationHandlerStates.ACTIVE)

279

.filter(handler -> transaction.getCredentials().stream()

280

.anyMatch(handler::supports))

281

.collect(Collectors.toSet());

282

}

283

284

public boolean supports(Set<AuthenticationHandler> handlers,

285

AuthenticationTransaction transaction) {

286

return true;

287

}

288

}

289

```

290

291

### Credential Type Resolver

292

293

```java { .api }

294

package org.apereo.cas.authentication.handler;

295

296

import org.apereo.cas.authentication.AuthenticationHandler;

297

import org.apereo.cas.authentication.AuthenticationTransaction;

298

import org.apereo.cas.authentication.Credential;

299

300

public class ByCredentialTypeAuthenticationHandlerResolver

301

implements AuthenticationHandlerResolver {

302

303

private Class<? extends Credential> credentialType;

304

305

public ByCredentialTypeAuthenticationHandlerResolver(Class<? extends Credential> credentialType) {

306

this.credentialType = credentialType;

307

}

308

309

public Set<AuthenticationHandler> resolve(Set<AuthenticationHandler> candidateHandlers,

310

AuthenticationTransaction transaction) {

311

return candidateHandlers.stream()

312

.filter(handler -> transaction.getCredentials().stream()

313

.anyMatch(credential -> credentialType.isInstance(credential) && handler.supports(credential)))

314

.collect(Collectors.toSet());

315

}

316

317

public boolean supports(Set<AuthenticationHandler> handlers,

318

AuthenticationTransaction transaction) {

319

return transaction.getCredentials().stream()

320

.anyMatch(credentialType::isInstance);

321

}

322

}

323

```

324

325

### Credential Source Resolver

326

327

```java { .api }

328

package org.apereo.cas.authentication.handler;

329

330

import org.apereo.cas.authentication.AuthenticationHandler;

331

import org.apereo.cas.authentication.AuthenticationTransaction;

332

import org.apereo.cas.authentication.credential.UsernamePasswordCredential;

333

334

public class ByCredentialSourceAuthenticationHandlerResolver

335

implements AuthenticationHandlerResolver {

336

337

private String source;

338

339

public ByCredentialSourceAuthenticationHandlerResolver(String source) {

340

this.source = source;

341

}

342

343

public Set<AuthenticationHandler> resolve(Set<AuthenticationHandler> candidateHandlers,

344

AuthenticationTransaction transaction) {

345

return candidateHandlers.stream()

346

.filter(handler -> transaction.getCredentials().stream()

347

.anyMatch(credential -> matchesSource(credential) && handler.supports(credential)))

348

.collect(Collectors.toSet());

349

}

350

351

private boolean matchesSource(Credential credential) {

352

if (credential instanceof UsernamePasswordCredential) {

353

UsernamePasswordCredential upc = (UsernamePasswordCredential) credential;

354

return source.equals(upc.getSource());

355

}

356

return false;

357

}

358

359

public boolean supports(Set<AuthenticationHandler> handlers,

360

AuthenticationTransaction transaction) {

361

return transaction.getCredentials().stream()

362

.anyMatch(this::matchesSource);

363

}

364

}

365

```

366

367

### Registered Service Resolver

368

369

```java { .api }

370

package org.apereo.cas.authentication.handler;

371

372

import org.apereo.cas.authentication.AuthenticationHandler;

373

import org.apereo.cas.authentication.AuthenticationTransaction;

374

import org.apereo.cas.services.RegisteredService;

375

import org.apereo.cas.services.ServicesManager;

376

377

public class RegisteredServiceAuthenticationHandlerResolver

378

implements AuthenticationHandlerResolver {

379

380

private ServicesManager servicesManager;

381

382

public RegisteredServiceAuthenticationHandlerResolver(ServicesManager servicesManager) {

383

this.servicesManager = servicesManager;

384

}

385

386

public Set<AuthenticationHandler> resolve(Set<AuthenticationHandler> candidateHandlers,

387

AuthenticationTransaction transaction) {

388

Service service = transaction.getService();

389

if (service == null) {

390

return candidateHandlers;

391

}

392

393

RegisteredService registeredService = servicesManager.findServiceBy(service);

394

if (registeredService == null || registeredService.getAuthenticationPolicy() == null) {

395

return candidateHandlers;

396

}

397

398

Set<String> requiredHandlers = registeredService.getAuthenticationPolicy()

399

.getRequiredAuthenticationHandlers();

400

401

if (requiredHandlers.isEmpty()) {

402

return candidateHandlers;

403

}

404

405

return candidateHandlers.stream()

406

.filter(handler -> requiredHandlers.contains(handler.getName()))

407

.collect(Collectors.toSet());

408

}

409

410

public boolean supports(Set<AuthenticationHandler> handlers,

411

AuthenticationTransaction transaction) {

412

return transaction.getService() != null;

413

}

414

}

415

```

416

417

### Groovy Handler Resolver

418

419

```java { .api }

420

package org.apereo.cas.authentication.handler;

421

422

import org.apereo.cas.authentication.AuthenticationHandler;

423

import org.apereo.cas.authentication.AuthenticationTransaction;

424

import org.apereo.cas.util.scripting.ExecutableCompiledGroovyScript;

425

426

public class GroovyAuthenticationHandlerResolver implements AuthenticationHandlerResolver {

427

428

private ExecutableCompiledGroovyScript watchableScript;

429

430

public GroovyAuthenticationHandlerResolver(ExecutableCompiledGroovyScript watchableScript) {

431

this.watchableScript = watchableScript;

432

}

433

434

public Set<AuthenticationHandler> resolve(Set<AuthenticationHandler> candidateHandlers,

435

AuthenticationTransaction transaction) {

436

Object result = watchableScript.execute(candidateHandlers, transaction,

437

AuthenticationHandler.class);

438

439

if (result instanceof Set) {

440

return (Set<AuthenticationHandler>) result;

441

} else if (result instanceof Collection) {

442

return new LinkedHashSet<>((Collection<AuthenticationHandler>) result);

443

}

444

445

return candidateHandlers;

446

}

447

448

public boolean supports(Set<AuthenticationHandler> handlers,

449

AuthenticationTransaction transaction) {

450

return watchableScript != null;

451

}

452

}

453

```

454

455

## JAAS Authentication Support

456

457

The authentication API provides JAAS (Java Authentication and Authorization Service) integration:

458

459

```java { .api }

460

package org.apereo.cas.authentication.handler.support.jaas;

461

462

import javax.security.auth.login.LoginContext;

463

import javax.security.auth.login.LoginException;

464

465

public class JaasAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler {

466

467

private String realm;

468

private String kerberosKdcSystemProperty;

469

private String kerberosRealmSystemProperty;

470

471

public JaasAuthenticationHandler(String name,

472

ServicesManager servicesManager,

473

PrincipalFactory principalFactory,

474

Integer order,

475

String realm) {

476

super(name, servicesManager, principalFactory, order);

477

this.realm = realm;

478

}

479

480

protected AuthenticationHandlerExecutionResult

481

authenticateUsernamePasswordInternal(UsernamePasswordCredential credential,

482

String originalPassword)

483

throws GeneralSecurityException {

484

485

try {

486

String username = credential.getUsername();

487

LoginContext loginContext = createLoginContext(credential);

488

loginContext.login();

489

490

Principal principal = principalFactory.createPrincipal(username);

491

return createHandlerResult(credential, principal, null);

492

493

} catch (LoginException e) {

494

throw new FailedLoginException("JAAS authentication failed: " + e.getMessage());

495

}

496

}

497

498

private LoginContext createLoginContext(UsernamePasswordCredential credential)

499

throws LoginException {

500

return new LoginContext(realm, new JaasUsernamePasswordCallbackHandler(

501

credential.getUsername(), credential.getPassword()));

502

}

503

}

504

```

505

506

## Handler Configuration Examples

507

508

### Spring Configuration

509

510

```java { .api }

511

@Configuration

512

@EnableConfigurationProperties(CasConfigurationProperties.class)

513

public class AuthenticationHandlerConfiguration {

514

515

@Bean

516

public AuthenticationHandler acceptUsersAuthenticationHandler() {

517

Map<String, String> users = Map.of(

518

"admin", "password",

519

"user", "secret"

520

);

521

return new AcceptUsersAuthenticationHandler(users);

522

}

523

524

@Bean

525

public AuthenticationHandlerResolver defaultAuthenticationHandlerResolver() {

526

return new DefaultAuthenticationHandlerResolver();

527

}

528

529

@Bean

530

public AuthenticationHandlerResolver credentialTypeResolver() {

531

return new ByCredentialTypeAuthenticationHandlerResolver(

532

UsernamePasswordCredential.class);

533

}

534

}

535

```

536

537

### Programmatic Configuration

538

539

```java { .api }

540

// Create authentication handler

541

AcceptUsersAuthenticationHandler handler = new AcceptUsersAuthenticationHandler(

542

"TestHandler",

543

servicesManager,

544

new DefaultPrincipalFactory(),

545

100,

546

Map.of("testuser", "testpass")

547

);

548

549

// Configure handler state

550

handler.setState(AuthenticationHandlerStates.ACTIVE);

551

552

// Create resolver for specific credential types

553

AuthenticationHandlerResolver resolver =

554

new ByCredentialTypeAuthenticationHandlerResolver(UsernamePasswordCredential.class);

555

556

// Register in execution plan

557

authenticationEventExecutionPlan.registerAuthenticationHandler(handler);

558

authenticationEventExecutionPlan.registerAuthenticationHandlerResolver(resolver);

559

```

560

561

Authentication handlers provide the core credential validation logic in CAS authentication workflows. They can be customized and extended to integrate with virtually any authentication source or protocol, making them a flexible foundation for enterprise authentication requirements.