or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application.mdauthentication.mdbroker.mdcommand-line.mdevents.mdindex.mdrest-api.mdtasks.mdutilities.mdweb-interface.mdworkers.md

authentication.mddocs/

0

# Authentication

1

2

Multiple authentication methods including Basic Auth and OAuth2 integration with various providers for securing Flower web interface and API access.

3

4

## Capabilities

5

6

### Authentication Functions

7

8

```python { .api }

9

def authenticate(pattern, email):

10

"""

11

Check if email matches authentication pattern.

12

13

Args:

14

pattern (str): Authentication pattern (regex or email list)

15

email (str): User email to validate

16

17

Returns:

18

bool: True if email is authorized

19

20

Supports regex patterns and comma-separated email lists.

21

"""

22

23

def validate_auth_option(pattern):

24

"""

25

Validate authentication pattern syntax.

26

27

Args:

28

pattern (str): Authentication pattern to validate

29

30

Returns:

31

bool: True if pattern is valid

32

33

Validates regex syntax and email format patterns.

34

"""

35

```

36

37

### OAuth2 Providers

38

39

#### Google OAuth2 Handler

40

41

```python { .api }

42

class GoogleAuth2LoginHandler(BaseHandler, tornado.auth.GoogleOAuth2Mixin):

43

"""

44

Google OAuth2 authentication handler with profile and email scope access.

45

"""

46

47

_OAUTH_SETTINGS_KEY = 'oauth'

48

49

async def get(self):

50

"""

51

Handle OAuth2 authentication flow.

52

53

Processes both authorization redirect and callback phases:

54

- Without code: Redirects to Google OAuth2 authorization

55

- With code: Processes callback and authenticates user

56

"""

57

58

async def _on_auth(self, user):

59

"""

60

Process authentication result from Google.

61

62

Args:

63

user (dict): OAuth2 user data containing access_token

64

65

Raises:

66

tornado.web.HTTPError: 403 if authentication fails or user unauthorized

67

68

Retrieves user email from Google API and validates against auth pattern.

69

Sets secure cookie and redirects to requested page on success.

70

"""

71

```

72

73

#### GitHub OAuth2 Handler

74

75

```python { .api }

76

class GithubLoginHandler(BaseHandler, tornado.auth.OAuth2Mixin):

77

"""

78

GitHub OAuth2 authentication handler with support for GitHub Enterprise.

79

"""

80

81

_OAUTH_DOMAIN = os.getenv("FLOWER_GITHUB_OAUTH_DOMAIN", "github.com")

82

_OAUTH_AUTHORIZE_URL = f'https://{_OAUTH_DOMAIN}/login/oauth/authorize'

83

_OAUTH_ACCESS_TOKEN_URL = f'https://{_OAUTH_DOMAIN}/login/oauth/access_token'

84

_OAUTH_NO_CALLBACKS = False

85

_OAUTH_SETTINGS_KEY = 'oauth'

86

87

async def get_authenticated_user(self, redirect_uri, code):

88

"""

89

Exchange authorization code for access token.

90

91

Args:

92

redirect_uri (str): OAuth2 redirect URI

93

code (str): Authorization code from GitHub

94

95

Returns:

96

dict: Token response containing access_token

97

98

Raises:

99

tornado.auth.AuthError: If token exchange fails

100

"""

101

102

async def get(self):

103

"""

104

Handle OAuth2 authentication flow for GitHub.

105

106

Supports both github.com and GitHub Enterprise instances.

107

Uses 'user:email' scope to access verified email addresses.

108

"""

109

110

async def _on_auth(self, user):

111

"""

112

Process authentication result from GitHub.

113

114

Args:

115

user (dict): OAuth2 user data containing access_token

116

117

Raises:

118

tornado.web.HTTPError: 403 if no verified emails match auth pattern

119

120

Retrieves all verified email addresses and validates against auth pattern.

121

Uses first matching verified email for authentication.

122

"""

123

```

124

125

#### GitLab OAuth2 Handler

126

127

```python { .api }

128

class GitLabLoginHandler(BaseHandler, tornado.auth.OAuth2Mixin):

129

"""

130

GitLab OAuth2 authentication handler with group-based authorization support.

131

"""

132

133

_OAUTH_GITLAB_DOMAIN = os.getenv("FLOWER_GITLAB_OAUTH_DOMAIN", "gitlab.com")

134

_OAUTH_AUTHORIZE_URL = f'https://{_OAUTH_GITLAB_DOMAIN}/oauth/authorize'

135

_OAUTH_ACCESS_TOKEN_URL = f'https://{_OAUTH_GITLAB_DOMAIN}/oauth/token'

136

_OAUTH_NO_CALLBACKS = False

137

138

async def get_authenticated_user(self, redirect_uri, code):

139

"""

140

Exchange authorization code for access token.

141

142

Args:

143

redirect_uri (str): OAuth2 redirect URI

144

code (str): Authorization code from GitLab

145

146

Returns:

147

dict: Token response containing access_token

148

149

Raises:

150

tornado.auth.AuthError: If token exchange fails

151

"""

152

153

async def get(self):

154

"""

155

Handle OAuth2 authentication flow for GitLab.

156

157

Uses 'read_api' scope to access user information and group memberships.

158

Supports both gitlab.com and self-hosted GitLab instances.

159

"""

160

161

async def _on_auth(self, user):

162

"""

163

Process authentication result from GitLab.

164

165

Args:

166

user (dict): OAuth2 user data containing access_token

167

168

Environment Variables:

169

FLOWER_GITLAB_AUTH_ALLOWED_GROUPS: Comma-separated list of allowed groups

170

FLOWER_GITLAB_MIN_ACCESS_LEVEL: Minimum access level (default: 20)

171

172

Raises:

173

tornado.web.HTTPError: 403 if user email or group membership unauthorized

174

175

Validates both email pattern and group membership if groups are configured.

176

"""

177

```

178

179

#### Okta OAuth2 Handler

180

181

```python { .api }

182

class OktaLoginHandler(BaseHandler, tornado.auth.OAuth2Mixin):

183

"""

184

Okta OAuth2 authentication handler with state validation for security.

185

"""

186

187

_OAUTH_NO_CALLBACKS = False

188

_OAUTH_SETTINGS_KEY = 'oauth'

189

190

@property

191

def base_url(self):

192

"""

193

Okta base URL from environment.

194

195

Returns:

196

str: Base URL from FLOWER_OAUTH2_OKTA_BASE_URL environment variable

197

"""

198

199

@property

200

def _OAUTH_AUTHORIZE_URL(self):

201

"""OAuth2 authorization endpoint URL."""

202

return f"{self.base_url}/v1/authorize"

203

204

@property

205

def _OAUTH_ACCESS_TOKEN_URL(self):

206

"""OAuth2 token endpoint URL."""

207

return f"{self.base_url}/v1/token"

208

209

@property

210

def _OAUTH_USER_INFO_URL(self):

211

"""OAuth2 user info endpoint URL."""

212

return f"{self.base_url}/v1/userinfo"

213

214

async def get_access_token(self, redirect_uri, code):

215

"""

216

Exchange authorization code for access token.

217

218

Args:

219

redirect_uri (str): OAuth2 redirect URI

220

code (str): Authorization code from Okta

221

222

Returns:

223

dict: Token response containing access_token

224

225

Raises:

226

tornado.auth.AuthError: If token exchange fails

227

"""

228

229

async def get(self):

230

"""

231

Handle OAuth2 authentication flow for Okta.

232

233

Implements state validation for CSRF protection.

234

Uses 'openid email' scope for authentication.

235

"""

236

237

async def _on_auth(self, access_token_response):

238

"""

239

Process authentication result from Okta.

240

241

Args:

242

access_token_response (dict): Token response containing access_token

243

244

Raises:

245

tornado.web.HTTPError: 403 if email not verified or unauthorized

246

247

Retrieves user info from Okta userinfo endpoint and validates email.

248

Requires verified email address matching auth pattern.

249

"""

250

```

251

252

#### Login Handler Factory

253

254

```python { .api }

255

class LoginHandler(BaseHandler):

256

"""

257

Factory class that instantiates the appropriate OAuth2 handler.

258

259

Uses the auth_provider option to determine which handler to create.

260

Returns NotFoundErrorHandler if no provider is configured.

261

"""

262

263

def __new__(cls, *args, **kwargs):

264

"""

265

Create appropriate login handler instance.

266

267

Returns:

268

BaseHandler: OAuth2 provider handler or NotFoundErrorHandler

269

"""

270

```

271

272

## Configuration Options

273

274

### Basic Authentication

275

276

```bash

277

# Single user

278

--basic-auth=admin:password

279

280

# Multiple users (comma-separated)

281

--basic-auth=admin:secret,user:pass

282

283

# Environment variable

284

export FLOWER_BASIC_AUTH=admin:secret

285

```

286

287

### Email-based Authentication

288

289

```bash

290

# Specific emails

291

--auth=user@domain.com,admin@company.com

292

293

# Domain-based (regex)

294

--auth=.*@company\.com

295

296

# OAuth2 provider with email filtering

297

--auth=google --auth=.*@company\.com

298

```

299

300

### OAuth2 Configuration

301

302

```bash

303

# Google OAuth2

304

--auth=google

305

--oauth2-key=your-client-id

306

--oauth2-secret=your-client-secret

307

--oauth2-redirect-uri=https://flower.example.com/login

308

309

# GitHub OAuth2

310

--auth=github

311

--oauth2-key=github-client-id

312

--oauth2-secret=github-client-secret

313

314

# Environment variables

315

export FLOWER_OAUTH2_KEY=client-id

316

export FLOWER_OAUTH2_SECRET=client-secret

317

export FLOWER_OAUTH2_REDIRECT_URI=https://flower.example.com/login

318

319

# GitLab OAuth2 with custom domain

320

--auth=gitlab

321

export FLOWER_GITLAB_OAUTH_DOMAIN=gitlab.company.com

322

export FLOWER_GITLAB_AUTH_ALLOWED_GROUPS=dev-team,admin-team

323

export FLOWER_GITLAB_MIN_ACCESS_LEVEL=30

324

325

# GitHub Enterprise

326

export FLOWER_GITHUB_OAUTH_DOMAIN=github.company.com

327

328

# Okta OAuth2

329

--auth=okta

330

export FLOWER_OAUTH2_OKTA_BASE_URL=https://company.okta.com/oauth2/default

331

```

332

333

## Usage Examples

334

335

### Basic Auth Setup

336

337

```python

338

from flower.app import Flower

339

from tornado.options import options

340

341

options.basic_auth = ['admin:secret', 'viewer:readonly']

342

flower_app = Flower(options=options)

343

```

344

345

### OAuth2 Setup

346

347

```python

348

options.auth = ['google']

349

options.oauth2_key = 'your-google-client-id'

350

options.oauth2_secret = 'your-google-client-secret'

351

options.oauth2_redirect_uri = 'https://flower.company.com/login'

352

353

flower_app = Flower(options=options)

354

```

355

356

### Custom Authentication

357

358

```python

359

from flower.views.auth import authenticate

360

361

# Custom authentication logic

362

def custom_auth_check(email):

363

# Custom validation logic

364

return email in allowed_users or is_admin(email)

365

366

# Override authenticate function

367

original_authenticate = authenticate

368

def authenticate(pattern, email):

369

return custom_auth_check(email) or original_authenticate(pattern, email)

370

```

371

372

## Authentication Flow

373

374

### Basic Auth Flow

375

1. User accesses protected endpoint

376

2. Browser prompts for username/password

377

3. Credentials validated against configured basic_auth

378

4. Access granted/denied based on validation

379

380

### OAuth2 Flow

381

1. User accesses login URL

382

2. Redirected to OAuth2 provider

383

3. User authenticates with provider

384

4. Provider redirects back with authorization code

385

5. Flower exchanges code for access token

386

6. User email retrieved from provider API

387

7. Email validated against auth pattern

388

8. Session established if authorized

389

390

## Security Considerations

391

392

- Use HTTPS in production for all authentication methods

393

- Store OAuth2 secrets securely (environment variables)

394

- Regularly rotate authentication credentials

395

- Use strict email patterns for OAuth2 filtering

396

- Monitor authentication logs for suspicious activity

397

- Consider session timeout configuration