or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdconfiguration.mdcore-application.mddatabase.mdindex.mdmetrics.mdrest-api.mdtesting.mdvalidation.md

authentication.mddocs/

0

# Authentication

1

2

Pluggable authentication system supporting basic auth, OAuth, and custom authentication schemes with fine-grained authorization control.

3

4

## Capabilities

5

6

### Authenticator Interface

7

8

Core interface for converting credentials into authenticated principals.

9

10

```java { .api }

11

package io.dropwizard.auth;

12

13

public interface Authenticator<C, P> {

14

/**

15

* Authenticates the given credentials and returns an optional principal.

16

* @param credentials the credentials to authenticate

17

* @return the authenticated principal if successful, empty otherwise

18

* @throws AuthenticationException if authentication fails

19

*/

20

Optional<P> authenticate(C credentials) throws AuthenticationException;

21

}

22

```

23

24

**Usage Example:**

25

26

```java

27

public class SimpleAuthenticator implements Authenticator<BasicCredentials, User> {

28

private final UserService userService;

29

30

public SimpleAuthenticator(UserService userService) {

31

this.userService = userService;

32

}

33

34

@Override

35

public Optional<User> authenticate(BasicCredentials credentials) throws AuthenticationException {

36

if ("secret".equals(credentials.getPassword())) {

37

return userService.findByUsername(credentials.getUsername());

38

}

39

return Optional.empty();

40

}

41

}

42

```

43

44

### Authorizer Interface

45

46

Interface for implementing authorization logic to control access to resources based on roles or permissions.

47

48

```java { .api }

49

package io.dropwizard.auth;

50

51

public interface Authorizer<P> {

52

/**

53

* Determines if the principal is authorized for the given role.

54

* @param principal the authenticated principal

55

* @param role the role to check authorization for

56

* @return true if authorized, false otherwise

57

*/

58

boolean authorize(P principal, String role);

59

}

60

```

61

62

**Usage Example:**

63

64

```java

65

public class SimpleAuthorizer implements Authorizer<User> {

66

@Override

67

public boolean authorize(User user, String role) {

68

return user.getRoles().contains(role);

69

}

70

}

71

```

72

73

### Authentication Filters

74

75

Pre-built authentication filters for common authentication schemes.

76

77

```java { .api }

78

package io.dropwizard.auth;

79

80

public class BasicCredentialAuthFilter<P> extends AuthFilter<BasicCredentials, P> {

81

public static class Builder<P> extends AuthFilterBuilder<BasicCredentials, P, BasicCredentialAuthFilter<P>> {

82

public Builder<P> setAuthenticator(Authenticator<BasicCredentials, P> authenticator);

83

public Builder<P> setAuthorizer(Authorizer<P> authorizer);

84

public Builder<P> setRealm(String realm);

85

public BasicCredentialAuthFilter<P> buildAuthFilter();

86

}

87

}

88

89

public class OAuthCredentialAuthFilter<P> extends AuthFilter<String, P> {

90

public static class Builder<P> extends AuthFilterBuilder<String, P, OAuthCredentialAuthFilter<P>> {

91

public Builder<P> setAuthenticator(Authenticator<String, P> authenticator);

92

public Builder<P> setAuthorizer(Authorizer<P> authorizer);

93

public Builder<P> setPrefix(String prefix);

94

public OAuthCredentialAuthFilter<P> buildAuthFilter();

95

}

96

}

97

```

98

99

**Usage Example:**

100

101

```java

102

@Override

103

public void run(MyConfiguration configuration, Environment environment) {

104

// Basic Authentication

105

environment.jersey().register(new AuthDynamicFeature(

106

new BasicCredentialAuthFilter.Builder<User>()

107

.setAuthenticator(new SimpleAuthenticator(userService))

108

.setAuthorizer(new SimpleAuthorizer())

109

.setRealm("SUPER SECRET STUFF")

110

.buildAuthFilter()

111

));

112

113

// OAuth Authentication

114

environment.jersey().register(new AuthDynamicFeature(

115

new OAuthCredentialAuthFilter.Builder<User>()

116

.setAuthenticator(new OAuthAuthenticator(tokenService))

117

.setAuthorizer(new SimpleAuthorizer())

118

.setPrefix("Bearer")

119

.buildAuthFilter()

120

));

121

122

// Enable authorization annotations

123

environment.jersey().register(RolesAllowedDynamicFeature.class);

124

}

125

```

126

127

### Auth Dynamic Feature

128

129

Jersey dynamic feature for registering authentication filters with the application.

130

131

```java { .api }

132

package io.dropwizard.auth;

133

134

public class AuthDynamicFeature implements DynamicFeature {

135

/**

136

* Creates an auth dynamic feature with the given auth filter.

137

*/

138

public AuthDynamicFeature(AuthFilter<?, ?> authFilter);

139

140

@Override

141

public void configure(ResourceInfo resourceInfo, FeatureContext context);

142

}

143

144

@Provider

145

public class RolesAllowedDynamicFeature implements DynamicFeature {

146

/**

147

* Enables @RolesAllowed, @PermitAll, and @DenyAll annotations.

148

*/

149

@Override

150

public void configure(ResourceInfo resourceInfo, FeatureContext context);

151

}

152

```

153

154

### Authentication Annotations

155

156

JAX-RS security annotations for protecting resources and methods.

157

158

```java { .api }

159

// Security annotations

160

@RolesAllowed({"ADMIN", "USER"})

161

@PermitAll

162

@DenyAll

163

164

// Authentication context

165

@Auth Principal principal

166

```

167

168

**Usage Example:**

169

170

```java

171

@Path("/admin")

172

@RolesAllowed("ADMIN")

173

public class AdminResource {

174

175

@GET

176

@Path("/users")

177

public List<User> getAllUsers(@Auth User currentUser) {

178

// Only accessible by users with ADMIN role

179

return userService.findAll();

180

}

181

182

@POST

183

@Path("/users")

184

@RolesAllowed({"ADMIN", "MODERATOR"})

185

public User createUser(@Auth User currentUser, @Valid User newUser) {

186

// Accessible by ADMIN or MODERATOR roles

187

return userService.create(newUser);

188

}

189

}

190

191

@Path("/public")

192

@PermitAll

193

public class PublicResource {

194

195

@GET

196

@Path("/health")

197

public String health() {

198

// Publicly accessible

199

return "OK";

200

}

201

}

202

```

203

204

### Custom Authentication Schemes

205

206

Creating custom authentication filters for specialized authentication requirements.

207

208

```java { .api }

209

package io.dropwizard.auth;

210

211

public abstract class AuthFilter<C, P> implements ContainerRequestFilter {

212

/**

213

* Extracts credentials from the request.

214

*/

215

public abstract C getCredentials(ContainerRequestContext requestContext);

216

217

/**

218

* Called when authentication fails.

219

*/

220

public abstract void onAuthenticationFailure(String challenge,

221

ContainerRequestContext requestContext);

222

223

/**

224

* Called when authorization fails.

225

*/

226

public abstract void onAuthorizationFailure(String challenge,

227

ContainerRequestContext requestContext);

228

}

229

230

public abstract class AuthFilterBuilder<C, P, T extends AuthFilter<C, P>> {

231

public abstract T buildAuthFilter();

232

233

protected AuthFilterBuilder<C, P, T> setAuthenticator(Authenticator<C, P> authenticator);

234

protected AuthFilterBuilder<C, P, T> setAuthorizer(Authorizer<P> authorizer);

235

}

236

```

237

238

**Usage Example:**

239

240

```java

241

public class ApiKeyAuthFilter extends AuthFilter<String, User> {

242

243

@Override

244

public String getCredentials(ContainerRequestContext requestContext) {

245

return requestContext.getHeaderString("X-API-Key");

246

}

247

248

@Override

249

public void onAuthenticationFailure(String challenge,

250

ContainerRequestContext requestContext) {

251

requestContext.abortWith(

252

Response.status(Response.Status.UNAUTHORIZED)

253

.header(HttpHeaders.WWW_AUTHENTICATE, challenge)

254

.entity("Invalid API key")

255

.build()

256

);

257

}

258

259

@Override

260

public void onAuthorizationFailure(String challenge,

261

ContainerRequestContext requestContext) {

262

requestContext.abortWith(

263

Response.status(Response.Status.FORBIDDEN)

264

.entity("Insufficient permissions")

265

.build()

266

);

267

}

268

269

public static class Builder extends AuthFilterBuilder<String, User, ApiKeyAuthFilter> {

270

@Override

271

protected ApiKeyAuthFilter newInstance() {

272

return new ApiKeyAuthFilter();

273

}

274

}

275

}

276

```

277

278

### Caching Authenticators

279

280

Wrapper authenticators that cache authentication results to improve performance.

281

282

```java { .api }

283

package io.dropwizard.auth;

284

285

public class CachingAuthenticator<C, P> implements Authenticator<C, P> {

286

/**

287

* Creates a caching authenticator with the given cache spec.

288

*/

289

public static <C, P> CachingAuthenticator<C, P> wrap(

290

Authenticator<C, P> underlying,

291

CacheBuilderSpec cacheSpec);

292

293

/**

294

* Creates a caching authenticator with a cache builder.

295

*/

296

public static <C, P> CachingAuthenticator<C, P> wrap(

297

Authenticator<C, P> underlying,

298

CacheBuilder<Object, Object> cacheBuilder);

299

}

300

```

301

302

**Usage Example:**

303

304

```java

305

@Override

306

public void run(MyConfiguration configuration, Environment environment) {

307

// Cache authentication results for 10 minutes

308

Authenticator<BasicCredentials, User> authenticator =

309

CachingAuthenticator.wrap(

310

new DatabaseAuthenticator(userService),

311

CacheBuilderSpec.parse("maximumSize=1000, expireAfterWrite=10m")

312

);

313

314

environment.jersey().register(new AuthDynamicFeature(

315

new BasicCredentialAuthFilter.Builder<User>()

316

.setAuthenticator(authenticator)

317

.setAuthorizer(new SimpleAuthorizer())

318

.setRealm("My Service")

319

.buildAuthFilter()

320

));

321

}

322

```

323

324

## Authentication Patterns

325

326

### JWT Token Authentication

327

328

Example implementation for JSON Web Token authentication.

329

330

```java

331

public class JWTAuthenticator implements Authenticator<String, User> {

332

private final JWTVerifier verifier;

333

private final UserService userService;

334

335

public JWTAuthenticator(JWTVerifier verifier, UserService userService) {

336

this.verifier = verifier;

337

this.userService = userService;

338

}

339

340

@Override

341

public Optional<User> authenticate(String token) throws AuthenticationException {

342

try {

343

DecodedJWT jwt = verifier.verify(token);

344

String username = jwt.getSubject();

345

return userService.findByUsername(username);

346

} catch (JWTVerificationException e) {

347

return Optional.empty();

348

}

349

}

350

}

351

```

352

353

### Multi-Factor Authentication

354

355

Combining multiple authentication factors for enhanced security.

356

357

```java

358

public class MFAAuthenticator implements Authenticator<BasicCredentials, User> {

359

private final Authenticator<BasicCredentials, User> primaryAuth;

360

private final TOTPService totpService;

361

362

@Override

363

public Optional<User> authenticate(BasicCredentials credentials) throws AuthenticationException {

364

// First factor: username/password

365

Optional<User> user = primaryAuth.authenticate(credentials);

366

if (!user.isPresent()) {

367

return Optional.empty();

368

}

369

370

// Second factor: TOTP code (assumed to be in password field after |)

371

String[] parts = credentials.getPassword().split("\\|");

372

if (parts.length != 2) {

373

return Optional.empty();

374

}

375

376

String totpCode = parts[1];

377

if (!totpService.verify(user.get().getTotpSecret(), totpCode)) {

378

return Optional.empty();

379

}

380

381

return user;

382

}

383

}

384

```