or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

analytics-monetization.mdcamera-media.mddevice-sensors.mddevice-system.mdindex.mdinput-hardware.mdlocation-maps.mdnetwork-communication.mdnotifications-ui.mdsecurity-auth.mdsocial-sharing.mdstorage-files.md
tile.json

security-auth.mddocs/

0

# Security & Authentication

1

2

Biometric authentication, secure storage, device security features, and advanced authentication methods for protecting user data and ensuring app security.

3

4

## Capabilities

5

6

### Touch ID Authentication

7

8

iOS Touch ID fingerprint authentication for secure app access and user verification.

9

10

```typescript { .api }

11

/**

12

* TouchID class for iOS fingerprint authentication

13

*/

14

class TouchID {

15

/**

16

* Check if Touch ID is available on device

17

* @returns Promise resolving to availability status string

18

*/

19

static isAvailable(): Promise<string>;

20

21

/**

22

* Verify fingerprint with default message

23

* @param message Message to display in authentication dialog

24

* @returns Promise indicating authentication success

25

*/

26

static verifyFingerprint(message: string): Promise<any>;

27

28

/**

29

* Verify fingerprint with custom password fallback

30

* @param message Message to display in authentication dialog

31

* @returns Promise indicating authentication success

32

*/

33

static verifyFingerprintWithCustomPasswordFallback(message: string): Promise<any>;

34

35

/**

36

* Verify fingerprint with custom labels and password fallback

37

* @param message Message to display in authentication dialog

38

* @param enterPasswordLabel Label for password entry button

39

* @returns Promise indicating authentication success

40

*/

41

static verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel(message: string, enterPasswordLabel: string): Promise<any>;

42

}

43

```

44

45

**Usage Examples:**

46

47

```typescript

48

import { TouchID } from 'ionic-native';

49

50

// Touch ID authentication service

51

class TouchIDService {

52

53

async checkAvailability(): Promise<boolean> {

54

try {

55

const result = await TouchID.isAvailable();

56

console.log('Touch ID availability:', result);

57

return true;

58

} catch (error) {

59

console.log('Touch ID not available:', error);

60

return false;

61

}

62

}

63

64

async authenticate(reason: string = 'Authenticate to access the app'): Promise<boolean> {

65

try {

66

const isAvailable = await this.checkAvailability();

67

if (!isAvailable) {

68

throw new Error('Touch ID not available');

69

}

70

71

await TouchID.verifyFingerprint(reason);

72

console.log('Touch ID authentication successful');

73

return true;

74

} catch (error) {

75

console.error('Touch ID authentication failed:', error);

76

return false;

77

}

78

}

79

80

async authenticateWithFallback(reason: string = 'Authenticate to continue'): Promise<boolean> {

81

try {

82

await TouchID.verifyFingerprintWithCustomPasswordFallback(reason);

83

console.log('Authentication successful (Touch ID or passcode)');

84

return true;

85

} catch (error) {

86

console.error('Authentication failed:', error);

87

return false;

88

}

89

}

90

91

async authenticateWithCustomLabels(

92

reason: string = 'Verify your identity',

93

passwordLabel: string = 'Enter Passcode'

94

): Promise<boolean> {

95

try {

96

await TouchID.verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel(reason, passwordLabel);

97

console.log('Authentication successful with custom labels');

98

return true;

99

} catch (error) {

100

console.error('Authentication with custom labels failed:', error);

101

return false;

102

}

103

}

104

}

105

106

// Usage in app

107

const touchID = new TouchIDService();

108

109

// Check and authenticate

110

async function secureLaunch() {

111

const available = await touchID.checkAvailability();

112

113

if (available) {

114

const authenticated = await touchID.authenticate('Please verify your identity to access your account');

115

116

if (authenticated) {

117

// Proceed to main app

118

navigateToMainApp();

119

} else {

120

// Handle authentication failure

121

showAuthenticationError();

122

}

123

} else {

124

// Fallback to other authentication methods

125

showPasswordLogin();

126

}

127

}

128

```

129

130

### Fingerprint AIO (All-in-One)

131

132

Cross-platform fingerprint authentication supporting both iOS and Android devices.

133

134

```typescript { .api }

135

/**

136

* Fingerprint authentication options

137

*/

138

interface FingerprintOptions {

139

/** Client ID for keychain access */

140

clientId: string;

141

/** Client secret for additional security */

142

clientSecret: string;

143

/** Disable backup authentication methods */

144

disableBackup?: boolean;

145

/** Localized fallback title */

146

localizedFallbackTitle?: string;

147

/** Localized cancel title */

148

localizedCancelTitle?: string;

149

}

150

151

/**

152

* FingerprintAIO class for cross-platform fingerprint authentication

153

*/

154

class FingerprintAIO {

155

/**

156

* Check if fingerprint authentication is available

157

* @returns Promise resolving to availability information

158

*/

159

static isAvailable(): Promise<any>;

160

161

/**

162

* Show fingerprint authentication dialog

163

* @param options Authentication configuration options

164

* @returns Promise indicating authentication result

165

*/

166

static show(options: FingerprintOptions): Promise<any>;

167

}

168

```

169

170

**Usage Examples:**

171

172

```typescript

173

import { FingerprintAIO, FingerprintOptions } from 'ionic-native';

174

175

// Cross-platform fingerprint authentication

176

class BiometricAuthService {

177

178

async checkBiometricSupport(): Promise<{

179

available: boolean;

180

type?: string;

181

hasEnrolledFingerprints?: boolean;

182

}> {

183

try {

184

const result = await FingerprintAIO.isAvailable();

185

186

return {

187

available: true,

188

type: result.type, // 'finger' or 'face'

189

hasEnrolledFingerprints: result.hasEnrolledFingerprints

190

};

191

} catch (error) {

192

console.log('Biometric authentication not available:', error);

193

return { available: false };

194

}

195

}

196

197

async authenticate(options: {

198

title?: string;

199

subtitle?: string;

200

description?: string;

201

fallbackEnabled?: boolean;

202

} = {}): Promise<boolean> {

203

try {

204

const support = await this.checkBiometricSupport();

205

if (!support.available) {

206

throw new Error('Biometric authentication not available');

207

}

208

209

if (!support.hasEnrolledFingerprints) {

210

throw new Error('No biometrics enrolled on device');

211

}

212

213

const fingerprintOptions: FingerprintOptions = {

214

clientId: 'myAppBiometric',

215

clientSecret: 'password123', // Use secure secret in production

216

disableBackup: !options.fallbackEnabled,

217

localizedFallbackTitle: 'Use Password',

218

localizedCancelTitle: 'Cancel'

219

};

220

221

await FingerprintAIO.show(fingerprintOptions);

222

console.log('Biometric authentication successful');

223

return true;

224

225

} catch (error) {

226

console.error('Biometric authentication failed:', error);

227

228

// Handle specific error cases

229

if (error.message === 'BiometricLockedOut') {

230

throw new Error('Too many failed attempts. Please try again later.');

231

} else if (error.message === 'BiometricNotEnrolled') {

232

throw new Error('No biometrics enrolled. Please set up biometric authentication in device settings.');

233

} else if (error.message === 'UserCancel') {

234

throw new Error('Authentication cancelled by user');

235

}

236

237

return false;

238

}

239

}

240

241

async authenticateForPayment(amount: number, currency: string = 'USD'): Promise<boolean> {

242

return await this.authenticate({

243

title: 'Authenticate Payment',

244

subtitle: `Confirm payment of ${amount} ${currency}`,

245

description: 'Place your finger on the sensor to authorize this transaction',

246

fallbackEnabled: true

247

});

248

}

249

250

async authenticateForSensitiveData(): Promise<boolean> {

251

return await this.authenticate({

252

title: 'Access Sensitive Data',

253

subtitle: 'Biometric verification required',

254

description: 'Verify your identity to view sensitive information',

255

fallbackEnabled: false

256

});

257

}

258

}

259

260

// Enhanced biometric service with security features

261

class SecureBiometricService extends BiometricAuthService {

262

private maxAttempts = 3;

263

private attemptCount = 0;

264

private lockoutTime = 30000; // 30 seconds

265

private isLockedOut = false;

266

267

async secureAuthenticate(purpose: string): Promise<boolean> {

268

if (this.isLockedOut) {

269

throw new Error('Authentication temporarily locked due to too many failed attempts');

270

}

271

272

try {

273

const result = await this.authenticate({

274

title: 'Secure Authentication',

275

subtitle: purpose,

276

description: 'Verify your identity to continue',

277

fallbackEnabled: true

278

});

279

280

// Reset attempt counter on success

281

this.attemptCount = 0;

282

return result;

283

284

} catch (error) {

285

this.attemptCount++;

286

287

if (this.attemptCount >= this.maxAttempts) {

288

this.lockoutUser();

289

}

290

291

throw error;

292

}

293

}

294

295

private lockoutUser() {

296

this.isLockedOut = true;

297

console.warn('User locked out due to too many failed authentication attempts');

298

299

// Auto-unlock after timeout

300

setTimeout(() => {

301

this.isLockedOut = false;

302

this.attemptCount = 0;

303

console.log('Authentication lockout expired');

304

}, this.lockoutTime);

305

}

306

307

getRemainingAttempts(): number {

308

return Math.max(0, this.maxAttempts - this.attemptCount);

309

}

310

311

isCurrentlyLockedOut(): boolean {

312

return this.isLockedOut;

313

}

314

}

315

```

316

317

### Secure Storage Implementation

318

319

Advanced secure storage implementation with encryption and key management.

320

321

```typescript { .api }

322

/**

323

* Advanced secure storage service with encryption

324

*/

325

class AdvancedSecureStorage {

326

private storage: any;

327

private encryptionKey: string;

328

329

async initialize(storeName: string = 'secure_app_store'): Promise<void> {

330

try {

331

const secureStorage = new SecureStorage();

332

this.storage = await secureStorage.create(storeName);

333

334

// Generate or retrieve encryption key

335

this.encryptionKey = await this.getOrCreateEncryptionKey();

336

337

console.log('Secure storage initialized');

338

} catch (error) {

339

console.error('Secure storage initialization failed:', error);

340

throw error;

341

}

342

}

343

344

async storeSecureData(key: string, data: any, requireBiometric: boolean = false): Promise<void> {

345

try {

346

if (requireBiometric) {

347

const biometricService = new BiometricAuthService();

348

const authenticated = await biometricService.authenticate({

349

title: 'Secure Data Storage',

350

subtitle: 'Authenticate to store sensitive data',

351

fallbackEnabled: true

352

});

353

354

if (!authenticated) {

355

throw new Error('Biometric authentication required for secure storage');

356

}

357

}

358

359

// Encrypt data before storage

360

const encryptedData = this.encrypt(JSON.stringify(data));

361

await this.storage.set(key, encryptedData);

362

363

console.log(`Secure data stored with key: ${key}`);

364

} catch (error) {

365

console.error('Secure data storage failed:', error);

366

throw error;

367

}

368

}

369

370

async retrieveSecureData(key: string, requireBiometric: boolean = false): Promise<any> {

371

try {

372

if (requireBiometric) {

373

const biometricService = new BiometricAuthService();

374

const authenticated = await biometricService.authenticate({

375

title: 'Access Secure Data',

376

subtitle: 'Authenticate to access sensitive data',

377

fallbackEnabled: true

378

});

379

380

if (!authenticated) {

381

throw new Error('Biometric authentication required for secure access');

382

}

383

}

384

385

const encryptedData = await this.storage.get(key);

386

387

if (!encryptedData) {

388

return null;

389

}

390

391

// Decrypt data after retrieval

392

const decryptedData = this.decrypt(encryptedData);

393

return JSON.parse(decryptedData);

394

395

} catch (error) {

396

console.error('Secure data retrieval failed:', error);

397

throw error;

398

}

399

}

400

401

async removeSecureData(key: string, requireBiometric: boolean = false): Promise<void> {

402

try {

403

if (requireBiometric) {

404

const biometricService = new BiometricAuthService();

405

const authenticated = await biometricService.authenticate({

406

title: 'Remove Secure Data',

407

subtitle: 'Authenticate to remove sensitive data',

408

fallbackEnabled: true

409

});

410

411

if (!authenticated) {

412

throw new Error('Biometric authentication required for secure removal');

413

}

414

}

415

416

await this.storage.remove(key);

417

console.log(`Secure data removed for key: ${key}`);

418

} catch (error) {

419

console.error('Secure data removal failed:', error);

420

throw error;

421

}

422

}

423

424

async listSecureKeys(): Promise<string[]> {

425

try {

426

return await this.storage.keys();

427

} catch (error) {

428

console.error('Failed to list secure keys:', error);

429

return [];

430

}

431

}

432

433

async clearAllSecureData(requireBiometric: boolean = true): Promise<void> {

434

try {

435

if (requireBiometric) {

436

const biometricService = new BiometricAuthService();

437

const authenticated = await biometricService.authenticate({

438

title: 'Clear All Data',

439

subtitle: 'Authenticate to clear all secure data',

440

description: 'This action cannot be undone',

441

fallbackEnabled: true

442

});

443

444

if (!authenticated) {

445

throw new Error('Biometric authentication required to clear all data');

446

}

447

}

448

449

await this.storage.clear();

450

console.log('All secure data cleared');

451

} catch (error) {

452

console.error('Failed to clear secure data:', error);

453

throw error;

454

}

455

}

456

457

private async getOrCreateEncryptionKey(): Promise<string> {

458

try {

459

let key = await this.storage.get('_encryption_key');

460

461

if (!key) {

462

key = this.generateEncryptionKey();

463

await this.storage.set('_encryption_key', key);

464

}

465

466

return key;

467

} catch (error) {

468

console.error('Encryption key management failed:', error);

469

throw error;

470

}

471

}

472

473

private generateEncryptionKey(): string {

474

// Simple key generation (use proper crypto library in production)

475

const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

476

let key = '';

477

for (let i = 0; i < 32; i++) {

478

key += chars.charAt(Math.floor(Math.random() * chars.length));

479

}

480

return key;

481

}

482

483

private encrypt(data: string): string {

484

// Simple XOR encryption (use proper encryption in production)

485

let encrypted = '';

486

for (let i = 0; i < data.length; i++) {

487

const keyChar = this.encryptionKey.charCodeAt(i % this.encryptionKey.length);

488

const dataChar = data.charCodeAt(i);

489

encrypted += String.fromCharCode(dataChar ^ keyChar);

490

}

491

return btoa(encrypted); // Base64 encode

492

}

493

494

private decrypt(encryptedData: string): string {

495

const data = atob(encryptedData); // Base64 decode

496

let decrypted = '';

497

for (let i = 0; i < data.length; i++) {

498

const keyChar = this.encryptionKey.charCodeAt(i % this.encryptionKey.length);

499

const dataChar = data.charCodeAt(i);

500

decrypted += String.fromCharCode(dataChar ^ keyChar);

501

}

502

return decrypted;

503

}

504

}

505

```

506

507

### Authentication Manager

508

509

Comprehensive authentication system combining multiple security layers.

510

511

```typescript

512

// Multi-factor authentication manager

513

class AuthenticationManager {

514

private biometricService: SecureBiometricService;

515

private secureStorage: AdvancedSecureStorage;

516

private sessionTimeout = 300000; // 5 minutes

517

private sessionTimer: any;

518

519

constructor() {

520

this.biometricService = new SecureBiometricService();

521

this.secureStorage = new AdvancedSecureStorage();

522

}

523

524

async initialize(): Promise<void> {

525

await this.secureStorage.initialize('auth_manager_store');

526

this.startSessionManager();

527

}

528

529

async authenticateUser(options: {

530

requireBiometric?: boolean;

531

purpose?: string;

532

sessionDuration?: number;

533

} = {}): Promise<{

534

success: boolean;

535

sessionToken?: string;

536

expiresAt?: Date;

537

}> {

538

try {

539

let authenticated = false;

540

541

if (options.requireBiometric) {

542

const support = await this.biometricService.checkBiometricSupport();

543

544

if (support.available && support.hasEnrolledFingerprints) {

545

authenticated = await this.biometricService.secureAuthenticate(

546

options.purpose || 'Authenticate to access the application'

547

);

548

} else {

549

throw new Error('Biometric authentication required but not available');

550

}

551

} else {

552

// Try biometric first, fallback to other methods

553

try {

554

authenticated = await this.biometricService.secureAuthenticate(

555

options.purpose || 'Verify your identity'

556

);

557

} catch (error) {

558

// Fallback to PIN/Password

559

authenticated = await this.showPasswordPrompt();

560

}

561

}

562

563

if (authenticated) {

564

const sessionToken = this.generateSessionToken();

565

const expiresAt = new Date(Date.now() + (options.sessionDuration || this.sessionTimeout));

566

567

// Store session info securely

568

await this.secureStorage.storeSecureData('active_session', {

569

token: sessionToken,

570

expiresAt: expiresAt.toISOString(),

571

createdAt: new Date().toISOString()

572

});

573

574

this.resetSessionTimer();

575

576

return {

577

success: true,

578

sessionToken,

579

expiresAt

580

};

581

}

582

583

return { success: false };

584

585

} catch (error) {

586

console.error('Authentication failed:', error);

587

return { success: false };

588

}

589

}

590

591

async validateSession(): Promise<boolean> {

592

try {

593

const sessionData = await this.secureStorage.retrieveSecureData('active_session');

594

595

if (!sessionData) {

596

return false;

597

}

598

599

const expiresAt = new Date(sessionData.expiresAt);

600

const now = new Date();

601

602

if (now > expiresAt) {

603

await this.endSession();

604

return false;

605

}

606

607

return true;

608

} catch (error) {

609

console.error('Session validation failed:', error);

610

return false;

611

}

612

}

613

614

async endSession(): Promise<void> {

615

try {

616

await this.secureStorage.removeSecureData('active_session');

617

this.clearSessionTimer();

618

console.log('Session ended');

619

} catch (error) {

620

console.error('Failed to end session:', error);

621

}

622

}

623

624

async extendSession(additionalTime: number = 300000): Promise<void> {

625

try {

626

const sessionData = await this.secureStorage.retrieveSecureData('active_session');

627

628

if (sessionData) {

629

const newExpiresAt = new Date(Date.now() + additionalTime);

630

sessionData.expiresAt = newExpiresAt.toISOString();

631

632

await this.secureStorage.storeSecureData('active_session', sessionData);

633

this.resetSessionTimer();

634

635

console.log('Session extended until:', newExpiresAt);

636

}

637

} catch (error) {

638

console.error('Failed to extend session:', error);

639

}

640

}

641

642

async requireSecureAccess(action: string): Promise<boolean> {

643

// Check if user has current valid session

644

const hasValidSession = await this.validateSession();

645

646

if (!hasValidSession) {

647

// Require fresh authentication

648

const authResult = await this.authenticateUser({

649

requireBiometric: true,

650

purpose: `Authenticate to ${action}`

651

});

652

653

return authResult.success;

654

}

655

656

// For sensitive operations, require fresh biometric even with valid session

657

if (this.isSensitiveAction(action)) {

658

return await this.biometricService.secureAuthenticate(`Confirm ${action}`);

659

}

660

661

return true;

662

}

663

664

private isSensitiveAction(action: string): boolean {

665

const sensitiveActions = [

666

'delete account',

667

'change password',

668

'export data',

669

'financial transaction',

670

'modify security settings'

671

];

672

673

return sensitiveActions.some(sensitive =>

674

action.toLowerCase().includes(sensitive)

675

);

676

}

677

678

private generateSessionToken(): string {

679

const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

680

let token = '';

681

for (let i = 0; i < 64; i++) {

682

token += chars.charAt(Math.floor(Math.random() * chars.length));

683

}

684

return token;

685

}

686

687

private async showPasswordPrompt(): Promise<boolean> {

688

// Implement custom password/PIN prompt

689

// This would show a secure input dialog

690

return new Promise((resolve) => {

691

// Placeholder implementation

692

const password = prompt('Enter your password:');

693

resolve(password === 'correct_password'); // Replace with real validation

694

});

695

}

696

697

private startSessionManager(): void {

698

// Check session validity periodically

699

setInterval(async () => {

700

const isValid = await this.validateSession();

701

if (!isValid) {

702

this.onSessionExpired();

703

}

704

}, 60000); // Check every minute

705

}

706

707

private resetSessionTimer(): void {

708

this.clearSessionTimer();

709

this.sessionTimer = setTimeout(() => {

710

this.endSession();

711

this.onSessionExpired();

712

}, this.sessionTimeout);

713

}

714

715

private clearSessionTimer(): void {

716

if (this.sessionTimer) {

717

clearTimeout(this.sessionTimer);

718

this.sessionTimer = null;

719

}

720

}

721

722

private onSessionExpired(): void {

723

console.log('Session expired - user needs to re-authenticate');

724

// Implement UI to handle session expiry

725

// e.g., redirect to login screen, show re-auth dialog

726

}

727

}

728

729

// Usage example

730

const authManager = new AuthenticationManager();

731

732

async function secureAppFlow() {

733

await authManager.initialize();

734

735

// Authenticate user on app start

736

const authResult = await authManager.authenticateUser({

737

requireBiometric: false,

738

purpose: 'Access your account'

739

});

740

741

if (authResult.success) {

742

console.log('User authenticated successfully');

743

744

// Later, for sensitive operations

745

const canDelete = await authManager.requireSecureAccess('delete account');

746

if (canDelete) {

747

// Proceed with sensitive operation

748

console.log('User authorized for sensitive operation');

749

}

750

}

751

}

752

```