or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdauthorization.mdcore-setup.mddatabase.mdindex.mdpassword-management.mdregistration.mdtwo-factor.mdunified-signin.mdutilities.mdwebauthn.md

utilities.mddocs/

0

# Utility Functions

1

2

Helper functions for URLs, tokens, validation, communication, and other common security operations that support Flask-Security's core functionality.

3

4

## Capabilities

5

6

### URL and Navigation Utilities

7

8

Functions for generating security-related URLs and handling navigation within Flask-Security.

9

10

```python { .api }

11

def url_for_security(endpoint, **values):

12

"""

13

Generate URLs for Flask-Security endpoints.

14

15

Parameters:

16

- endpoint: Security endpoint name (e.g., 'login', 'register', 'reset_password')

17

- values: Additional URL parameters and query arguments

18

19

Returns:

20

Generated URL string for the security endpoint

21

"""

22

23

def get_url(endpoint_or_url, qparams=None, **values):

24

"""

25

Generate URLs with query parameters.

26

27

Parameters:

28

- endpoint_or_url: Flask endpoint name or absolute URL

29

- qparams: Dictionary of query parameters to append

30

- values: Additional URL generation values

31

32

Returns:

33

Complete URL with query parameters

34

"""

35

36

def transform_url(url, qparams=None, **params):

37

"""

38

Transform URLs with custom logic and parameters.

39

40

Parameters:

41

- url: Base URL to transform

42

- qparams: Query parameters to add or modify

43

- params: Additional transformation parameters

44

45

Returns:

46

Transformed URL string

47

"""

48

49

def get_post_login_redirect():

50

"""

51

Get redirect URL after successful login.

52

53

Returns:

54

URL string for post-login redirect, considering 'next' parameter

55

"""

56

57

def get_logout_redirect():

58

"""

59

Get redirect URL after logout.

60

61

Returns:

62

URL string for post-logout redirect

63

"""

64

```

65

66

### Token and Security Utilities

67

68

Functions for generating, validating, and managing security tokens and cryptographic operations.

69

70

```python { .api }

71

def get_hmac(password):

72

"""

73

Generate HMAC for token security and password operations.

74

75

Parameters:

76

- password: Password or data to generate HMAC for

77

78

Returns:

79

HMAC digest string

80

"""

81

82

def check_and_get_token_status(token, serializer, max_age=None):

83

"""

84

Validate token status and return token information.

85

86

Parameters:

87

- token: Token string to validate

88

- serializer: Token serializer instance

89

- max_age: Maximum token age in seconds (optional)

90

91

Returns:

92

Tuple of (is_expired: bool, is_invalid: bool, token_data: dict)

93

"""

94

95

def generate_token(data, salt=None):

96

"""

97

Generate secure token from data.

98

99

Parameters:

100

- data: Data to encode in token

101

- salt: Salt for token generation (optional)

102

103

Returns:

104

Generated token string

105

"""

106

107

def verify_token(token, salt=None, max_age=None):

108

"""

109

Verify and decode token data.

110

111

Parameters:

112

- token: Token string to verify

113

- salt: Salt used for token generation (optional)

114

- max_age: Maximum acceptable token age in seconds

115

116

Returns:

117

Decoded token data if valid, None if invalid or expired

118

"""

119

```

120

121

### Password Validation Utilities

122

123

Functions for validating password strength, complexity, and security requirements.

124

125

```python { .api }

126

def password_length_validator(password, min_length=None, max_length=None):

127

"""

128

Validate password length requirements.

129

130

Parameters:

131

- password: Password string to validate

132

- min_length: Minimum required length (default: from config)

133

- max_length: Maximum allowed length (default: from config)

134

135

Returns:

136

True if valid, raises ValidationError if invalid

137

"""

138

139

def password_complexity_validator(password, **requirements):

140

"""

141

Validate password complexity requirements.

142

143

Parameters:

144

- password: Password string to validate

145

- requirements: Complexity requirements dict (uppercase, lowercase, digits, symbols)

146

147

Returns:

148

True if valid, raises ValidationError if invalid

149

"""

150

151

def password_breached_validator(password, check_breach_count=True):

152

"""

153

Check password against known breach databases.

154

155

Parameters:

156

- password: Password string to check

157

- check_breach_count: Whether to check breach count threshold

158

159

Returns:

160

True if password is safe, raises ValidationError if breached

161

"""

162

163

def pwned(password, user_agent=None, request_timeout=1.0):

164

"""

165

Check if password appears in HaveIBeenPwned breach database.

166

167

Parameters:

168

- password: Password string to check

169

- user_agent: Custom User-Agent for API requests

170

- request_timeout: Timeout for API request in seconds

171

172

Returns:

173

Number of times password appears in breaches, 0 if safe

174

"""

175

```

176

177

### Communication Utilities

178

179

Functions for sending emails, SMS messages, and other forms of communication.

180

181

```python { .api }

182

def send_mail(subject, recipient, template, **context):

183

"""

184

Send email utility function with template rendering.

185

186

Parameters:

187

- subject: Email subject line

188

- recipient: Recipient email address

189

- template: Template name for email body

190

- context: Template context variables

191

192

Returns:

193

True if email sent successfully, False otherwise

194

"""

195

196

class MailUtil:

197

"""

198

Email handling and template rendering utility class.

199

"""

200

201

def __init__(self, app=None):

202

"""

203

Initialize mail utility.

204

205

Parameters:

206

- app: Flask application instance (optional)

207

"""

208

209

def init_app(self, app):

210

"""

211

Initialize mail utility with Flask app.

212

213

Parameters:

214

- app: Flask application instance

215

"""

216

217

def send_mail(self, template, subject, recipient, sender=None, **kwargs):

218

"""

219

Send templated email.

220

221

Parameters:

222

- template: Email template name

223

- subject: Email subject

224

- recipient: Recipient email address

225

- sender: Sender email address (optional)

226

- kwargs: Template context variables

227

228

Returns:

229

True if sent successfully, False otherwise

230

"""

231

232

def render_template(self, template, **kwargs):

233

"""

234

Render email template with context.

235

236

Parameters:

237

- template: Template name to render

238

- kwargs: Template context variables

239

240

Returns:

241

Rendered template string

242

"""

243

244

class EmailValidateException(Exception):

245

"""Exception raised for email validation errors."""

246

pass

247

```

248

249

### SMS Communication Classes

250

251

Classes and factory for SMS message sending with multiple provider support.

252

253

```python { .api }

254

class SmsSenderBaseClass:

255

"""

256

Abstract base class for SMS senders.

257

"""

258

259

def __init__(self, **kwargs):

260

"""

261

Initialize SMS sender.

262

263

Parameters:

264

- kwargs: Provider-specific configuration

265

"""

266

267

def send_sms(self, from_number, to_number, msg):

268

"""

269

Send SMS message.

270

271

Parameters:

272

- from_number: Sender phone number

273

- to_number: Recipient phone number

274

- msg: Message content

275

276

Returns:

277

True if sent successfully, False otherwise

278

"""

279

280

class SmsSenderFactory:

281

"""

282

Factory for creating SMS sender instances.

283

"""

284

285

@staticmethod

286

def createSender(name, **kwargs):

287

"""

288

Create SMS sender instance by name.

289

290

Parameters:

291

- name: SMS service name ('Dummy', 'Twilio', etc.)

292

- kwargs: Service-specific configuration

293

294

Returns:

295

SMS sender instance

296

"""

297

298

class DummySmsSender(SmsSenderBaseClass):

299

"""

300

Dummy SMS sender implementation for testing and development.

301

"""

302

303

def send_sms(self, from_number, to_number, msg):

304

"""Send SMS (dummy implementation that logs message)."""

305

print(f"SMS to {to_number}: {msg}")

306

return True

307

```

308

309

### Time and Request Utilities

310

311

Utility functions for handling time operations and request context management.

312

313

```python { .api }

314

def naive_utcnow():

315

"""

316

Get current UTC time as naive datetime.

317

318

Returns:

319

Datetime object representing current UTC time without timezone info

320

"""

321

322

def get_request_attr(name):

323

"""

324

Get attribute from current request context.

325

326

Parameters:

327

- name: Attribute name to retrieve from request

328

329

Returns:

330

Attribute value if found, None otherwise

331

"""

332

333

def get_request_attr_or_default(name, default=None):

334

"""

335

Get request attribute with default fallback.

336

337

Parameters:

338

- name: Attribute name to retrieve

339

- default: Default value if attribute not found

340

341

Returns:

342

Attribute value or default

343

"""

344

```

345

346

### Specialized Utility Classes

347

348

Utility classes for managing specific Flask-Security features and operations.

349

350

```python { .api }

351

class PasswordUtil:

352

"""

353

Password management and policy utility class.

354

"""

355

356

def __init__(self, app=None):

357

"""Initialize password utility."""

358

359

def init_app(self, app):

360

"""Initialize with Flask app."""

361

362

def hash_password(self, password):

363

"""

364

Hash password using configured algorithm.

365

366

Parameters:

367

- password: Plain text password to hash

368

369

Returns:

370

Hashed password string

371

"""

372

373

def verify_password(self, password, password_hash):

374

"""

375

Verify password against hash.

376

377

Parameters:

378

- password: Plain text password

379

- password_hash: Stored password hash

380

381

Returns:

382

True if password matches, False otherwise

383

"""

384

385

def validate_password(self, password):

386

"""

387

Validate password against configured policies.

388

389

Parameters:

390

- password: Password to validate

391

392

Returns:

393

True if valid, raises ValidationError if invalid

394

"""

395

396

class PhoneUtil:

397

"""

398

Phone number validation and formatting utility class.

399

"""

400

401

def __init__(self, app=None):

402

"""Initialize phone utility."""

403

404

def init_app(self, app):

405

"""Initialize with Flask app."""

406

407

def validate_phone_number(self, phone_number):

408

"""

409

Validate phone number format.

410

411

Parameters:

412

- phone_number: Phone number string to validate

413

414

Returns:

415

True if valid, False otherwise

416

"""

417

418

def normalize_phone_number(self, phone_number):

419

"""

420

Normalize phone number to standard format.

421

422

Parameters:

423

- phone_number: Phone number to normalize

424

425

Returns:

426

Normalized phone number string

427

"""

428

429

class UsernameUtil:

430

"""

431

Username validation and management utility class.

432

"""

433

434

def __init__(self, app=None):

435

"""Initialize username utility."""

436

437

def init_app(self, app):

438

"""Initialize with Flask app."""

439

440

def validate_username(self, username):

441

"""

442

Validate username format and requirements.

443

444

Parameters:

445

- username: Username to validate

446

447

Returns:

448

True if valid, raises ValidationError if invalid

449

"""

450

451

def normalize_username(self, username):

452

"""

453

Normalize username format.

454

455

Parameters:

456

- username: Username to normalize

457

458

Returns:

459

Normalized username string

460

"""

461

```

462

463

### TOTP Utility Class

464

465

Time-based One-Time Password generation and validation for two-factor authentication.

466

467

```python { .api }

468

class Totp:

469

"""

470

Time-based One-Time Password generation and validation utility class.

471

"""

472

473

def __init__(self, secret=None, issuer=None):

474

"""

475

Initialize TOTP utility.

476

477

Parameters:

478

- secret: Base32-encoded secret key (optional, generates if not provided)

479

- issuer: Issuer name for TOTP (optional)

480

"""

481

482

def generate_password(self, counter=None):

483

"""

484

Generate TOTP password for current time window.

485

486

Parameters:

487

- counter: Time counter (optional, uses current time if not provided)

488

489

Returns:

490

6-digit TOTP code as string

491

"""

492

493

def verify(self, token, window=0):

494

"""

495

Verify TOTP token against current time.

496

497

Parameters:

498

- token: TOTP token string to verify

499

- window: Number of time windows to check (default: 0)

500

501

Returns:

502

True if token is valid, False otherwise

503

"""

504

505

def generate_qr_code(self, name, issuer=None):

506

"""

507

Generate QR code for TOTP secret.

508

509

Parameters:

510

- name: Account name for QR code

511

- issuer: Issuer name (optional)

512

513

Returns:

514

QR code image data as base64 string

515

"""

516

517

@property

518

def secret(self):

519

"""

520

Get TOTP secret key.

521

522

Returns:

523

Base32-encoded secret string

524

"""

525

526

@property

527

def provisioning_uri(self):

528

"""

529

Get provisioning URI for authenticator apps.

530

531

Returns:

532

otpauth:// URI string

533

"""

534

```

535

536

## Usage Examples

537

538

### URL Generation and Navigation

539

540

```python

541

from flask_security import url_for_security, get_url

542

543

@app.route('/custom-login')

544

def custom_login_redirect():

545

"""Redirect to Flask-Security login page."""

546

login_url = url_for_security('login', next='/dashboard')

547

return redirect(login_url)

548

549

@app.route('/user-profile')

550

@login_required

551

def user_profile():

552

"""Display user profile with navigation links."""

553

554

# Generate security URLs

555

change_password_url = url_for_security('change_password')

556

logout_url = url_for_security('logout')

557

558

# Add query parameters

559

reset_url = get_url('security.forgot_password',

560

qparams={'email': current_user.email})

561

562

return render_template('profile.html',

563

change_password_url=change_password_url,

564

logout_url=logout_url,

565

reset_url=reset_url)

566

```

567

568

### Token Generation and Validation

569

570

```python

571

from flask_security import generate_token, verify_token

572

573

@app.route('/send-invite', methods=['POST'])

574

@roles_required('admin')

575

def send_invite():

576

"""Send invitation token to new user."""

577

email = request.form.get('email')

578

579

# Generate invitation token

580

token_data = {'email': email, 'action': 'invite'}

581

token = generate_token(token_data, salt='invite-salt')

582

583

# Send invitation email

584

invite_url = url_for('accept_invite', token=token, _external=True)

585

send_mail(

586

subject='You are invited to join our platform',

587

recipient=email,

588

template='invite_email',

589

invite_url=invite_url

590

)

591

592

flash(f'Invitation sent to {email}')

593

return redirect(url_for('admin_users'))

594

595

@app.route('/accept-invite/<token>')

596

def accept_invite(token):

597

"""Accept invitation using token."""

598

599

# Verify token (valid for 7 days)

600

token_data = verify_token(token, salt='invite-salt', max_age=604800)

601

602

if not token_data:

603

flash('Invalid or expired invitation link')

604

return redirect(url_for('security.register'))

605

606

# Pre-fill registration form with invited email

607

return redirect(url_for('security.register', email=token_data['email']))

608

```

609

610

### Password Validation

611

612

```python

613

from flask_security import (

614

password_length_validator,

615

password_complexity_validator,

616

password_breached_validator

617

)

618

619

def validate_new_password(password):

620

"""Custom password validation with multiple checks."""

621

622

try:

623

# Check length requirements

624

password_length_validator(password, min_length=8, max_length=128)

625

626

# Check complexity requirements

627

password_complexity_validator(password, {

628

'uppercase': 1,

629

'lowercase': 1,

630

'digits': 1,

631

'symbols': 1

632

})

633

634

# Check against breach database

635

password_breached_validator(password)

636

637

return True

638

639

except ValidationError as e:

640

return False, str(e)

641

642

@app.route('/validate-password', methods=['POST'])

643

def validate_password_endpoint():

644

"""API endpoint for password validation."""

645

password = request.json.get('password')

646

647

is_valid, error_message = validate_new_password(password)

648

649

return jsonify({

650

'valid': is_valid,

651

'error': error_message if not is_valid else None

652

})

653

```

654

655

### Email Communication

656

657

```python

658

from flask_security import send_mail, MailUtil

659

660

# Initialize mail utility

661

mail_util = MailUtil(app)

662

663

@app.route('/send-welcome-email')

664

@login_required

665

def send_welcome_email():

666

"""Send welcome email to new user."""

667

668

success = send_mail(

669

subject='Welcome to Our Platform!',

670

recipient=current_user.email,

671

template='welcome_email',

672

user=current_user,

673

login_url=url_for_security('login', _external=True)

674

)

675

676

if success:

677

flash('Welcome email sent successfully')

678

else:

679

flash('Failed to send welcome email')

680

681

return redirect(url_for('dashboard'))

682

683

@app.route('/send-custom-notification', methods=['POST'])

684

@roles_required('admin')

685

def send_custom_notification():

686

"""Send custom notification to users."""

687

688

subject = request.form.get('subject')

689

message = request.form.get('message')

690

recipient_emails = request.form.getlist('recipients')

691

692

sent_count = 0

693

for email in recipient_emails:

694

if mail_util.send_mail(

695

template='notification_email',

696

subject=subject,

697

recipient=email,

698

message=message,

699

admin_name=current_user.email

700

):

701

sent_count += 1

702

703

flash(f'Notification sent to {sent_count} users')

704

return redirect(url_for('admin_notifications'))

705

```

706

707

### SMS Integration

708

709

```python

710

from flask_security import SmsSenderFactory

711

712

# Configure SMS service

713

app.config['SECURITY_SMS_SERVICE'] = 'Twilio'

714

app.config['SECURITY_SMS_SERVICE_CONFIG'] = {

715

'ACCOUNT_SID': 'your-account-sid',

716

'AUTH_TOKEN': 'your-auth-token',

717

'FROM_NUMBER': '+1234567890'

718

}

719

720

# Create SMS sender

721

sms_sender = SmsSenderFactory.createSender(

722

app.config['SECURITY_SMS_SERVICE'],

723

**app.config['SECURITY_SMS_SERVICE_CONFIG']

724

)

725

726

@app.route('/send-sms-code', methods=['POST'])

727

@login_required

728

def send_sms_code():

729

"""Send SMS verification code to user."""

730

731

if not current_user.us_phone_number:

732

flash('Phone number not configured')

733

return redirect(url_for('profile'))

734

735

# Generate verification code

736

code = generate_random_code(6)

737

738

# Store code in session with expiration

739

session['sms_verification_code'] = code

740

session['sms_code_expires'] = (datetime.utcnow() + timedelta(minutes=5)).isoformat()

741

742

# Send SMS

743

message = f"Your verification code is: {code}"

744

success = sms_sender.send_sms(

745

from_number=app.config['SECURITY_SMS_SERVICE_CONFIG']['FROM_NUMBER'],

746

to_number=current_user.us_phone_number,

747

msg=message

748

)

749

750

if success:

751

flash('Verification code sent to your phone')

752

else:

753

flash('Failed to send SMS')

754

755

return redirect(url_for('verify_phone'))

756

757

def generate_random_code(length=6):

758

"""Generate random numeric code."""

759

import random

760

import string

761

return ''.join(random.choices(string.digits, k=length))

762

```

763

764

### TOTP Two-Factor Authentication

765

766

```python

767

from flask_security import Totp

768

769

@app.route('/setup-2fa')

770

@login_required

771

def setup_2fa():

772

"""Setup TOTP two-factor authentication."""

773

774

# Generate TOTP secret

775

totp = Totp()

776

777

# Store secret in session temporarily

778

session['totp_setup_secret'] = totp.secret

779

780

# Generate QR code for authenticator apps

781

qr_code = totp.generate_qr_code(

782

name=current_user.email,

783

issuer='My Secure App'

784

)

785

786

return render_template('setup_2fa.html',

787

secret=totp.secret,

788

qr_code=qr_code)

789

790

@app.route('/verify-2fa-setup', methods=['POST'])

791

@login_required

792

def verify_2fa_setup():

793

"""Verify TOTP setup with user-provided code."""

794

795

code = request.form.get('code')

796

secret = session.get('totp_setup_secret')

797

798

if not secret:

799

flash('Setup session expired')

800

return redirect(url_for('setup_2fa'))

801

802

# Verify the code

803

totp = Totp(secret=secret)

804

if totp.verify(code, window=1):

805

# Save TOTP secret to user

806

current_user.tf_totp_secret = secret

807

current_user.tf_primary_method = 'authenticator'

808

db.session.commit()

809

810

# Clear setup session

811

session.pop('totp_setup_secret', None)

812

813

flash('Two-factor authentication enabled successfully')

814

return redirect(url_for('profile'))

815

else:

816

flash('Invalid code. Please try again.')

817

return redirect(url_for('setup_2fa'))

818

819

@app.route('/verify-2fa', methods=['GET', 'POST'])

820

@login_required

821

def verify_2fa():

822

"""Verify TOTP code for authentication."""

823

824

if request.method == 'POST':

825

code = request.form.get('code')

826

827

if current_user.tf_totp_secret:

828

totp = Totp(secret=current_user.tf_totp_secret)

829

if totp.verify(code, window=1):

830

session['2fa_verified'] = True

831

return redirect(request.args.get('next', '/dashboard'))

832

else:

833

flash('Invalid authentication code')

834

835

return render_template('verify_2fa.html')

836

```

837

838

### Utility Class Integration

839

840

```python

841

from flask_security import PasswordUtil, PhoneUtil, UsernameUtil

842

843

# Initialize utility classes

844

password_util = PasswordUtil(app)

845

phone_util = PhoneUtil(app)

846

username_util = UsernameUtil(app)

847

848

@app.route('/validate-profile', methods=['POST'])

849

@login_required

850

def validate_profile():

851

"""Validate user profile data."""

852

853

username = request.form.get('username')

854

phone = request.form.get('phone')

855

new_password = request.form.get('new_password')

856

857

errors = []

858

859

# Validate username if provided

860

if username:

861

try:

862

username_util.validate_username(username)

863

normalized_username = username_util.normalize_username(username)

864

except ValidationError as e:

865

errors.append(f"Username: {e}")

866

867

# Validate phone number if provided

868

if phone:

869

if phone_util.validate_phone_number(phone):

870

normalized_phone = phone_util.normalize_phone_number(phone)

871

else:

872

errors.append("Invalid phone number format")

873

874

# Validate new password if provided

875

if new_password:

876

try:

877

password_util.validate_password(new_password)

878

except ValidationError as e:

879

errors.append(f"Password: {e}")

880

881

if errors:

882

return jsonify({'success': False, 'errors': errors})

883

884

# Update user profile

885

if username:

886

current_user.username = normalized_username

887

if phone:

888

current_user.us_phone_number = normalized_phone

889

if new_password:

890

current_user.password = password_util.hash_password(new_password)

891

892

db.session.commit()

893

894

return jsonify({'success': True, 'message': 'Profile updated successfully'})

895

```

896

897

### Custom Security Decorators Using Utilities

898

899

```python

900

from functools import wraps

901

from flask_security import get_request_attr, naive_utcnow

902

903

def rate_limit(max_requests=10, window_seconds=60):

904

"""Rate limiting decorator using utilities."""

905

906

def decorator(f):

907

@wraps(f)

908

def decorated_function(*args, **kwargs):

909

910

# Get client IP using utility

911

client_ip = get_request_attr('remote_addr') or 'unknown'

912

913

# Simple in-memory rate limiting (use Redis in production)

914

current_time = naive_utcnow()

915

916

if not hasattr(app, 'rate_limit_store'):

917

app.rate_limit_store = {}

918

919

key = f"rate_limit:{client_ip}:{f.__name__}"

920

921

if key in app.rate_limit_store:

922

requests, window_start = app.rate_limit_store[key]

923

924

# Check if window expired

925

if (current_time - window_start).total_seconds() > window_seconds:

926

# Reset window

927

app.rate_limit_store[key] = (1, current_time)

928

elif requests >= max_requests:

929

# Rate limit exceeded

930

return jsonify({'error': 'Rate limit exceeded'}), 429

931

else:

932

# Increment counter

933

app.rate_limit_store[key] = (requests + 1, window_start)

934

else:

935

# First request in window

936

app.rate_limit_store[key] = (1, current_time)

937

938

return f(*args, **kwargs)

939

return decorated_function

940

return decorator

941

942

@app.route('/api/sensitive-endpoint')

943

@login_required

944

@rate_limit(max_requests=5, window_seconds=60)

945

def sensitive_endpoint():

946

"""Rate-limited API endpoint."""

947

return jsonify({'data': 'sensitive information'})

948

```

949

950

## Configuration

951

952

Flask-Security utilities can be configured through various configuration variables:

953

954

```python

955

# Email configuration

956

app.config['MAIL_SERVER'] = 'smtp.gmail.com'

957

app.config['MAIL_PORT'] = 587

958

app.config['MAIL_USE_TLS'] = True

959

app.config['MAIL_USERNAME'] = 'your-email@gmail.com'

960

app.config['MAIL_PASSWORD'] = 'your-password'

961

962

# Password validation configuration

963

app.config['SECURITY_PASSWORD_LENGTH_MIN'] = 8

964

app.config['SECURITY_PASSWORD_COMPLEXITY_CHECKER'] = 'zxcvbn'

965

966

# Token configuration

967

app.config['SECURITY_TOKEN_AUTHENTICATION_KEY'] = 'auth_token'

968

app.config['SECURITY_TOKEN_MAX_AGE'] = 86400 # 24 hours

969

970

# SMS configuration

971

app.config['SECURITY_SMS_SERVICE'] = 'Twilio'

972

app.config['SECURITY_SMS_SERVICE_CONFIG'] = {

973

'ACCOUNT_SID': 'your-sid',

974

'AUTH_TOKEN': 'your-token'

975

}

976

```

977

978

## Security Considerations

979

980

### Token Security

981

- Use cryptographically secure random token generation

982

- Implement proper token expiration and rotation

983

- Store tokens securely with appropriate hashing

984

- Validate token signatures to prevent tampering

985

986

### Communication Security

987

- Use TLS/SSL for all email and SMS communications

988

- Validate recipient addresses before sending messages

989

- Implement rate limiting for communication endpoints

990

- Log security-related communications for audit trails

991

992

### Password Security

993

- Use strong password hashing algorithms (bcrypt, Argon2)

994

- Implement comprehensive password policies

995

- Check passwords against known breach databases

996

- Provide clear feedback on password requirements

997

998

### General Security

999

- Validate all user inputs using utility functions

1000

- Implement proper error handling without information disclosure

1001

- Use secure random number generation for codes and tokens

1002

- Monitor and log security-related utility function usage