Skip to main content

Overview

Authentication state management is a critical part of using Baileys. The authentication state consists of credentials (creds) and encryption keys that allow you to maintain a persistent session with WhatsApp.

AuthenticationState

The main authentication state interface passed to makeWASocket.
type AuthenticationState = {
  creds: AuthenticationCreds
  keys: SignalKeyStore
}
creds
AuthenticationCreds
required
Authentication credentials containing identity keys, registration info, and account metadata
keys
SignalKeyStore
required
Key store for managing Signal protocol keys (pre-keys, sessions, sender keys, etc.)

AuthenticationCreds

Contains all credential data needed to authenticate with WhatsApp.
type AuthenticationCreds = SignalCreds & {
  readonly noiseKey: KeyPair
  readonly pairingEphemeralKeyPair: KeyPair
  advSecretKey: string
  
  me?: Contact
  account?: proto.IADVSignedDeviceIdentity
  signalIdentities?: SignalIdentity[]
  myAppStateKeyId?: string
  firstUnuploadedPreKeyId: number
  nextPreKeyId: number
  
  lastAccountSyncTimestamp?: number
  platform?: string
  
  processedHistoryMessages: MinimalMessage[]
  accountSyncCounter: number
  accountSettings: AccountSettings
  registered: boolean
  pairingCode: string | undefined
  lastPropHash: string | undefined
  routingInfo: Buffer | undefined
  additionalData?: any | undefined
}

Core identity fields

noiseKey
KeyPair
required
Noise protocol key pair for secure channel establishment
type KeyPair = { 
  public: Uint8Array
  private: Uint8Array 
}
pairingEphemeralKeyPair
KeyPair
required
Ephemeral key pair used during pairing process
advSecretKey
string
required
Secret key for Account Device Verification (ADV)
signedIdentityKey
KeyPair
required
Signed identity key pair (inherited from SignalCreds)
signedPreKey
SignedKeyPair
required
Signed pre-key for initial key exchange (inherited from SignalCreds)
type SignedKeyPair = {
  keyPair: KeyPair
  signature: Uint8Array
  keyId: number
  timestampS?: number
}
registrationId
number
required
Unique registration ID for this device (inherited from SignalCreds)

Account information

me
Contact
Information about the authenticated user
type Contact = {
  id: string
  name?: string
  notify?: string
  verifiedName?: string
  imgUrl?: string
  status?: string
}
account
proto.IADVSignedDeviceIdentity
Signed device identity for account verification
registered
boolean
required
Whether the device is registered with WhatsApp
platform
string
Platform identifier (e.g., ‘web’, ‘desktop’)

Pre-key management

firstUnuploadedPreKeyId
number
required
ID of the first pre-key that hasn’t been uploaded to WhatsApp servers
nextPreKeyId
number
required
Next pre-key ID to generate

Signal protocol

signalIdentities
SignalIdentity[]
List of trusted Signal identities
type SignalIdentity = {
  identifier: ProtocolAddress
  identifierKey: Uint8Array
}

type ProtocolAddress = {
  name: string // JID
  deviceId: number
}

Sync and history

processedHistoryMessages
MinimalMessage[]
required
List of history messages that have been processed
accountSyncCounter
number
required
Number of times history and app state have been synced
lastAccountSyncTimestamp
number
Timestamp of the last account sync

Account settings

accountSettings
AccountSettings
required
User account settings
type AccountSettings = {
  unarchiveChats: boolean
  defaultDisappearingMode?: Pick<
    proto.IConversation, 
    'ephemeralExpiration' | 'ephemeralSettingTimestamp'
  >
}

App state

myAppStateKeyId
string
ID of the current app state sync key

Pairing

pairingCode
string | undefined
required
Current pairing code if in pairing mode

Internal fields

lastPropHash
string | undefined
required
Hash of the last received props
routingInfo
Buffer | undefined
required
Routing information for message delivery
additionalData
any | undefined
Additional data for custom extensions

SignalKeyStore

Interface for storing and retrieving Signal protocol keys.
type SignalKeyStore = {
  get<T extends keyof SignalDataTypeMap>(
    type: T, 
    ids: string[]
  ): Awaitable<{ [id: string]: SignalDataTypeMap[T] }>
  
  set(data: SignalDataSet): Awaitable<void>
  
  clear?(): Awaitable<void>
}
get
function
required
Retrieve keys of a specific type by their IDs
// Example usage
const sessions = await keys.get('session', ['jid_1', 'jid_2'])
set
function
required
Store or update keys in the key store
// Example usage
await keys.set({
  'pre-key': {
    '1': { public: ..., private: ... },
    '2': { public: ..., private: ... }
  },
  'session': {
    'jid_deviceId': sessionData
  }
})
clear
() => Awaitable<void>
Optional method to clear all data from the key store

SignalDataTypeMap

Defines all the different types of data stored in the key store.
type SignalDataTypeMap = {
  'pre-key': KeyPair
  'session': Uint8Array
  'sender-key': Uint8Array
  'sender-key-memory': { [jid: string]: boolean }
  'app-state-sync-key': proto.Message.IAppStateSyncKeyData
  'app-state-sync-version': LTHashState
  'lid-mapping': string
  'device-list': string[]
  'tctoken': { token: Buffer; timestamp?: string }
  'identity-key': Uint8Array
}

SignalDataSet

Type for batch key operations.
type SignalDataSet = {
  [T in keyof SignalDataTypeMap]?: {
    [id: string]: SignalDataTypeMap[T] | null
  }
}
Used when setting multiple keys at once. Setting a key to null deletes it.
// Example: Delete a session and add a pre-key
await keys.set({
  'session': {
    'old_session_id': null // Delete
  },
  'pre-key': {
    '10': { public: ..., private: ... } // Add
  }
})

Creating authentication state

Baileys provides helper functions to create and manage authentication state:

Using multi-file auth state

import { useMultiFileAuthState } from '@whiskeysockets/baileys'

const { state, saveCreds } = await useMultiFileAuthState('auth_info_folder')

const sock = makeWASocket({
  auth: state
})

// Save credentials whenever they're updated
sock.ev.on('creds.update', saveCreds)
This stores authentication data in JSON files in the specified folder:
  • creds.json - Authentication credentials
  • app-state-sync-version-*.json - App state versions
  • app-state-sync-key-*.json - App state sync keys
  • And other key files

Custom auth state implementation

You can implement your own auth state storage (e.g., database-backed):
import { 
  AuthenticationState, 
  SignalDataTypeMap,
  initAuthCreds,
  BufferJSON
} from '@whiskeysockets/baileys'

const useMongoAuthState = async (): Promise<{
  state: AuthenticationState
  saveCreds: () => Promise<void>
}> => {
  // Load creds from database
  let creds = await db.creds.findOne({ _id: 'main' })
  if(!creds) {
    creds = initAuthCreds()
    await db.creds.insertOne({ _id: 'main', ...creds })
  }
  
  return {
    state: {
      creds,
      keys: {
        get: async (type, ids) => {
          const data = {}
          const keys = await db.keys.find({
            type,
            id: { $in: ids }
          })
          
          for(const key of keys) {
            data[key.id] = key.value
          }
          
          return data
        },
        
        set: async (data) => {
          const tasks = []
          
          for(const type in data) {
            for(const id in data[type]) {
              const value = data[type][id]
              
              if(value === null) {
                // Delete key
                tasks.push(
                  db.keys.deleteOne({ type, id })
                )
              } else {
                // Upsert key
                tasks.push(
                  db.keys.updateOne(
                    { type, id },
                    { $set: { value } },
                    { upsert: true }
                  )
                )
              }
            }
          }
          
          await Promise.all(tasks)
        }
      }
    },
    
    saveCreds: async () => {
      await db.creds.updateOne(
        { _id: 'main' },
        { $set: creds }
      )
    }
  }
}

// Usage
const { state, saveCreds } = await useMongoAuthState()
const sock = makeWASocket({ auth: state })
sock.ev.on('creds.update', saveCreds)

Helper types

KeyPair

type KeyPair = { 
  public: Uint8Array
  private: Uint8Array 
}
A standard public/private key pair.

SignedKeyPair

type SignedKeyPair = {
  keyPair: KeyPair
  signature: Uint8Array
  keyId: number
  timestampS?: number
}
A key pair with a signature for verification.

LTHashState

type LTHashState = {
  version: number
  hash: Buffer
  indexValueMap: {
    [indexMacBase64: string]: { 
      valueMac: Uint8Array | Buffer 
    }
  }
}
State for LT (Long-Term) hash verification in app state sync.

Best practices

Always save credentials: Listen to the creds.update event and persist credentials whenever they change. Failing to do so will require re-authentication.
Secure storage: Store authentication data securely. Anyone with access to these credentials can impersonate your WhatsApp session.
Backup keys: Consider backing up your authentication state regularly. Loss of these keys means losing access to the session.
// Good: Save on every update
sock.ev.on('creds.update', saveCreds)

// Bad: Not saving credentials
sock.ev.on('creds.update', () => {
  // credentials not saved - session will be lost on restart!
})

See also

Build docs developers (and LLMs) love