CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-aws-amplify--auth

Authentication category of AWS Amplify providing APIs and building blocks for creating authentication experiences with Amazon Cognito

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

device-management.mddocs/

Device Management

Trusted device tracking and management for enhanced security and user experience.

Fetch Devices

Get a list of all devices associated with the current user.

function fetchDevices(): Promise<FetchDevicesOutput>;

interface FetchDevicesOutput {
  devices: AWSAuthDevice[];
}

interface AWSAuthDevice {
  id: string;
  name?: string;
  attributes?: Record<string, string>;
  createDate?: Date;
  lastModifiedDate?: Date;
  lastAccessedDate?: Date;
}

Usage Example

import { fetchDevices } from "@aws-amplify/auth";

const { devices } = await fetchDevices();

devices.forEach(device => {
  console.log(`Device ID: ${device.id}`);
  console.log(`Device Name: ${device.name || 'Unknown'}`);
  console.log(`Last Accessed: ${device.lastAccessedDate}`);
  console.log(`Attributes:`, device.attributes);
  console.log('---');
});

Remember Device

Mark the current device as trusted/remembered to skip MFA on future sign-ins.

function rememberDevice(): Promise<void>;

Usage Example

import { rememberDevice } from "@aws-amplify/auth";

// After successful sign-in with MFA, allow user to remember device
const shouldRememberDevice = confirm("Remember this device for future sign-ins?");

if (shouldRememberDevice) {
  await rememberDevice();
  console.log("Device marked as trusted");
}

Forget Device

Remove a device from the trusted devices list, requiring MFA on next sign-in.

function forgetDevice(input?: ForgetDeviceInput): Promise<void>;

interface ForgetDeviceInput {
  device?: {
    id: string;
  };
}

Usage Example

import { forgetDevice, fetchDevices } from "@aws-amplify/auth";

// Forget current device
await forgetDevice();
console.log("Current device forgotten");

// Forget a specific device
const { devices } = await fetchDevices();
const deviceToForget = devices.find(d => d.name === 'Old Phone');

if (deviceToForget) {
  await forgetDevice({
    device: { id: deviceToForget.id }
  });
  console.log(`Device ${deviceToForget.name} forgotten`);
}

Device Management Flow

Initial Device Setup

When a user signs in from a new device with MFA enabled:

import { signIn, confirmSignIn, rememberDevice } from "@aws-amplify/auth";

// Sign in process
const { isSignedIn, nextStep } = await signIn({
  username: "user@example.com",
  password: "MyPassword123!"
});

if (!isSignedIn && nextStep.signInStep === 'CONFIRM_SIGN_IN_WITH_SMS_CODE') {
  // User enters MFA code
  const mfaCode = "123456"; // from user input
  
  const { isSignedIn: mfaComplete } = await confirmSignIn({
    challengeResponse: mfaCode
  });
  
  if (mfaComplete) {
    // Offer to remember device
    const shouldRemember = confirm("Remember this device to skip MFA next time?");
    
    if (shouldRemember) {
      await rememberDevice();
    }
  }
}

Device Management UI

Building a device management interface:

import { fetchDevices, forgetDevice } from "@aws-amplify/auth";

async function buildDeviceManager() {
  const { devices } = await fetchDevices();
  
  const deviceList = devices.map(device => ({
    id: device.id,
    name: device.name || `Device ${device.id.slice(-4)}`,
    lastAccessed: device.lastAccessedDate?.toLocaleDateString(),
    isCurrentDevice: device.id === getCurrentDeviceId(), // Your implementation
    
    async forget() {
      await forgetDevice({ device: { id: device.id } });
      console.log(`Device ${this.name} removed from trusted devices`);
    }
  }));
  
  return deviceList;
}

// Usage in React component or similar
const devices = await buildDeviceManager();
devices.forEach(device => {
  console.log(`${device.name} - Last accessed: ${device.lastAccessed}`);
});

Device Attributes

Device attributes provide additional information about each device:

// Common device attributes
interface DeviceAttributes {
  'device_name'?: string;           // User-friendly device name
  'device_key'?: string;            // Unique device identifier
  'device_group_key'?: string;      // Device group identifier
  'device_remembered_status'?: string; // 'remembered' | 'not_remembered'
  [key: string]: string | undefined;  // Custom attributes
}

// Example of working with device attributes
const { devices } = await fetchDevices();
const currentDevice = devices[0];

if (currentDevice.attributes) {
  const deviceName = currentDevice.attributes['device_name'] || 'Unknown Device';
  const isRemembered = currentDevice.attributes['device_remembered_status'] === 'remembered';
  
  console.log(`Device: ${deviceName}, Remembered: ${isRemembered}`);
}

Security Best Practices

Device Trust Policy

// Example device trust management
class DeviceTrustManager {
  private readonly MAX_TRUSTED_DEVICES = 5;
  private readonly TRUST_DURATION_DAYS = 30;
  
  async manageTrustedDevices() {
    const { devices } = await fetchDevices();
    
    // Remove old trusted devices
    const oldDevices = devices.filter(device => {
      const lastAccessed = device.lastAccessedDate;
      if (!lastAccessed) return true;
      
      const daysSinceAccess = (Date.now() - lastAccessed.getTime()) / (1000 * 60 * 60 * 24);
      return daysSinceAccess > this.TRUST_DURATION_DAYS;
    });
    
    // Forget old devices
    for (const device of oldDevices) {
      await forgetDevice({ device: { id: device.id } });
      console.log(`Removed stale device: ${device.name}`);
    }
    
    // Check device limit
    const remainingDevices = devices.length - oldDevices.length;
    if (remainingDevices >= this.MAX_TRUSTED_DEVICES) {
      console.warn('Maximum trusted devices reached');
      return false;
    }
    
    return true;
  }
  
  async rememberCurrentDevice() {
    const canTrust = await this.manageTrustedDevices();
    
    if (canTrust) {
      await rememberDevice();
      return true;
    }
    
    return false;
  }
}

Error Handling

import { fetchDevices, forgetDevice, AuthError } from "@aws-amplify/auth";

try {
  const { devices } = await fetchDevices();
} catch (error) {
  if (error instanceof AuthError) {
    switch (error.name) {
      case 'NotAuthorizedException':
        console.log('User not signed in');
        break;
      case 'ResourceNotFoundException':
        console.log('User pool not found');
        break;
      case 'InvalidParameterException':
        console.log('Invalid request parameters');
        break;
      default:
        console.log('Failed to fetch devices:', error.message);
    }
  }
}

try {
  await forgetDevice({ device: { id: 'invalid-device-id' } });
} catch (error) {
  if (error instanceof AuthError) {
    switch (error.name) {
      case 'ResourceNotFoundException':
        console.log('Device not found');
        break;
      case 'InvalidParameterException':
        console.log('Invalid device ID');
        break;
      default:
        console.log('Failed to forget device:', error.message);
    }
  }
}

Integration with MFA

Device remembering works in conjunction with MFA:

  • New Device: Requires MFA + option to remember
  • Remembered Device: Skips MFA challenge
  • Forgotten Device: Requires MFA again
  • Device Limit: Configurable per User Pool

This provides a balance between security and user experience, allowing trusted devices to bypass MFA while maintaining security for unknown devices.

docs

authentication-lifecycle.md

device-management.md

index.md

multi-factor-authentication.md

oauth-social-authentication.md

password-management.md

server-side-apis.md

session-management.md

user-management.md

webauthn-credentials.md

tile.json