or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdconfiguration-utilities.mdcore-application.mddatabase-models.mdindex.mdmonitoring-metrics.mdrbac-permissions.mdrest-api.mdservices-oauth.mdsingleuser-integration.mdspawners.md

authentication.mddocs/

0

# Authentication System

1

2

JupyterHub's authentication system provides a pluggable architecture for user authentication supporting multiple backends including PAM, OAuth, LDAP, and custom implementations. The system handles user login, session management, and authorization for notebook server access.

3

4

## Capabilities

5

6

### Base Authenticator Class

7

8

The foundation class for all authentication providers in JupyterHub.

9

10

```python { .api }

11

class Authenticator(LoggingConfigurable):

12

"""

13

Base class for authenticating users to JupyterHub.

14

15

Subclass this to implement custom authentication schemes.

16

"""

17

18

# Configuration attributes

19

admin_users: Set[str] # Set of admin usernames

20

blocked_users: Set[str] # Set of blocked usernames

21

allowed_users: Set[str] # Set of allowed usernames

22

auto_login: bool # Whether to automatically login users

23

username_pattern: str # Regex pattern for valid usernames

24

25

async def authenticate(self, handler, data):

26

"""

27

Authenticate a user with login form data.

28

29

Args:

30

handler: The current request handler

31

data: Dictionary of login form data (username, password, etc.)

32

33

Returns:

34

Username string if authentication succeeds, None if it fails,

35

or a dictionary with additional user info

36

"""

37

38

async def pre_spawn_start(self, user, spawner):

39

"""

40

Hook called before spawning a user's server.

41

42

Args:

43

user: The User object

44

spawner: The Spawner instance

45

"""

46

47

def pre_spawn_hook(self, spawner):

48

"""

49

Deprecated hook called before spawning (use pre_spawn_start).

50

51

Args:

52

spawner: The Spawner instance

53

"""

54

55

def normalize_username(self, username):

56

"""

57

Normalize a username for consistent handling.

58

59

Args:

60

username: The username to normalize

61

62

Returns:

63

Normalized username string

64

"""

65

66

def check_blocked_users(self, username, authentication=None):

67

"""

68

Check if a user is blocked.

69

70

Args:

71

username: Username to check

72

authentication: Authentication result

73

74

Returns:

75

True if user is blocked

76

"""

77

78

def check_allowed_users(self, username, authentication=None):

79

"""

80

Check if a user is allowed.

81

82

Args:

83

username: Username to check

84

authentication: Authentication result

85

86

Returns:

87

True if user is allowed

88

"""

89

```

90

91

### Local System Authenticators

92

93

Authenticators that work with local system users.

94

95

```python { .api }

96

class LocalAuthenticator(Authenticator):

97

"""

98

Base class for authenticators that work with local system users.

99

100

Provides functionality for creating and managing local user accounts.

101

"""

102

103

create_system_users: bool # Whether to create system users if they don't exist

104

105

def system_user_exists(self, user):

106

"""

107

Check if a user exists on the system.

108

109

Args:

110

user: User object or username string

111

112

Returns:

113

True if user exists on system

114

"""

115

116

def add_system_user(self, user):

117

"""

118

Create a new system user account.

119

120

Args:

121

user: User object or username string

122

"""

123

124

class PAMAuthenticator(LocalAuthenticator):

125

"""

126

Authenticate users with PAM (Pluggable Authentication Modules).

127

128

Uses the system's PAM configuration for authentication.

129

"""

130

131

service: str # PAM service name (default: 'login')

132

encoding: str # Text encoding (default: 'utf8')

133

134

async def authenticate(self, handler, data):

135

"""

136

Authenticate using PAM.

137

138

Args:

139

handler: Current request handler

140

data: Login form data with 'username' and 'password'

141

142

Returns:

143

Username if authentication succeeds, None otherwise

144

"""

145

```

146

147

### Development and Testing Authenticators

148

149

Simple authenticators for development and testing scenarios.

150

151

```python { .api }

152

class DummyAuthenticator(Authenticator):

153

"""

154

Dummy authenticator for testing.

155

156

Any username/password combination will succeed, with the password

157

set as an attribute on the returned user object.

158

"""

159

160

password: str # Optional fixed password

161

162

async def authenticate(self, handler, data):

163

"""

164

Authenticate any username/password combination.

165

166

Args:

167

handler: Current request handler

168

data: Login form data

169

170

Returns:

171

Dictionary with username and authentication info

172

"""

173

174

class NullAuthenticator(Authenticator):

175

"""

176

No-op authenticator that allows any username without a password.

177

178

Useful for completely open JupyterHub installations.

179

"""

180

181

auto_login: bool = True # Automatically login users

182

183

async def authenticate(self, handler, data):

184

"""

185

Accept any username without password validation.

186

187

Args:

188

handler: Current request handler

189

data: Login form data

190

191

Returns:

192

Username from the form data

193

"""

194

```

195

196

### Shared Password Authenticator

197

198

Simple shared password authentication for small deployments.

199

200

```python { .api }

201

class SharedPasswordAuthenticator(Authenticator):

202

"""

203

Authenticator that uses a single shared password for all users.

204

205

Useful for workshops, classes, or small private deployments.

206

"""

207

208

shared_password: str # The shared password for all users

209

210

async def authenticate(self, handler, data):

211

"""

212

Authenticate users with shared password.

213

214

Args:

215

handler: Current request handler

216

data: Login form data with 'username' and 'password'

217

218

Returns:

219

Username if password matches, None otherwise

220

"""

221

```

222

223

## Usage Examples

224

225

### PAM Authentication Setup

226

227

```python

228

# jupyterhub_config.py

229

c = get_config()

230

231

# Use PAM authenticator (default)

232

c.JupyterHub.authenticator_class = 'pam'

233

234

# Configure admin users

235

c.Authenticator.admin_users = {'admin', 'teacher'}

236

237

# Create system users automatically

238

c.LocalAuthenticator.create_system_users = True

239

240

# Set allowed users (optional)

241

c.Authenticator.allowed_users = {'student1', 'student2', 'student3'}

242

```

243

244

### Dummy Authenticator for Development

245

246

```python

247

# Development configuration

248

c.JupyterHub.authenticator_class = 'dummy'

249

250

# Set admin users

251

c.Authenticator.admin_users = {'admin'}

252

253

# Optional: Set a fixed password for all users

254

c.DummyAuthenticator.password = 'test123'

255

```

256

257

### Custom Authenticator Implementation

258

259

```python

260

from jupyterhub.auth import Authenticator

261

262

class CustomAuthenticator(Authenticator):

263

"""Custom authenticator example"""

264

265

async def authenticate(self, handler, data):

266

"""Custom authentication logic"""

267

username = data.get('username')

268

password = data.get('password')

269

270

# Implement your authentication logic here

271

if self.validate_credentials(username, password):

272

return {

273

'name': username,

274

'admin': username in self.admin_users,

275

'auth_model': {

276

'custom_field': 'custom_value'

277

}

278

}

279

return None

280

281

def validate_credentials(self, username, password):

282

"""Custom credential validation"""

283

# Your validation logic here

284

return True

285

286

# Register the authenticator

287

c.JupyterHub.authenticator_class = CustomAuthenticator

288

```

289

290

### OAuth Integration Pattern

291

292

```python

293

# For OAuth-based authenticators (requires additional packages)

294

class OAuthenticator(Authenticator):

295

"""Base OAuth authenticator pattern"""

296

297

client_id: str # OAuth client ID

298

client_secret: str # OAuth client secret

299

oauth_callback_url: str # OAuth callback URL

300

301

def login_url(self, base_url):

302

"""Generate OAuth login URL"""

303

pass

304

305

async def token_to_user(self, token_info):

306

"""Convert OAuth token to user info"""

307

pass

308

```

309

310

### Pre-spawn Hooks

311

312

```python

313

class CustomAuthenticator(Authenticator):

314

"""Authenticator with pre-spawn customization"""

315

316

async def pre_spawn_start(self, user, spawner):

317

"""Customize spawner before starting"""

318

# Set environment variables

319

spawner.environment.update({

320

'USER_ROLE': 'student' if user.name != 'admin' else 'teacher',

321

'JUPYTER_ENABLE_LAB': 'yes'

322

})

323

324

# Set resource limits based on user

325

if user.name in self.admin_users:

326

spawner.mem_limit = '2G'

327

spawner.cpu_limit = 2

328

else:

329

spawner.mem_limit = '1G'

330

spawner.cpu_limit = 1

331

```

332

333

## Configuration Patterns

334

335

### User Management Configuration

336

337

```python

338

# User access controls

339

c.Authenticator.admin_users = {'admin1', 'admin2'}

340

c.Authenticator.allowed_users = {'user1', 'user2', 'user3'}

341

c.Authenticator.blocked_users = {'blocked_user'}

342

343

# Username normalization

344

c.Authenticator.username_pattern = r'^[a-z][a-z0-9\-_]{1,31}$'

345

346

# Automatic login (for some authenticators)

347

c.Authenticator.auto_login = True

348

```

349

350

### Integration with External Systems

351

352

```python

353

# Example: LDAP-style configuration pattern

354

class LDAPAuthenticator(Authenticator):

355

"""LDAP authenticator configuration example"""

356

357

server_address: str = 'ldap://ldap.example.com'

358

bind_dn_template: str = 'uid={username},ou=users,dc=example,dc=com'

359

allowed_groups: Set[str] = set()

360

361

async def authenticate(self, handler, data):

362

"""LDAP authentication implementation"""

363

# LDAP authentication logic would go here

364

pass

365

```