Credential Storage

How TheCompanyApp stores and protects user credentials (UserPass entity).

UserPass Entity

Purpose: Store user login credentials for each company.

Attributes:

  • companyID: UUID - Company this credential belongs to

  • userName: String - User's email or username

  • userPassword: String - User's password (see encryption below)

  • createdAt: Date - When credential was created

Relationships: None (isolated entity).

Privacy Architecture

Private Database Only

Core Data Configuration:

<!-- TheCompanyApp.xcdatamodel -->
<configuration name="Default" usedWithCloudKit="YES">
    <memberEntity name="UserPass"/>
    <!-- ... all other entities ... -->
</configuration>

<configuration name="Shared" usedWithCloudKit="YES">
    <!-- UserPass intentionally EXCLUDED -->
    <memberEntity name="Companies"/>
    <memberEntity name="InventoryItem"/>
    <!-- ... other shared entities ... -->
</configuration>

Result:

  • UserPass syncs to CloudKit Private Database (user's iCloud)

  • UserPass never syncs to Shared Database

  • Share participants cannot see owner's UserPass

  • Owner cannot see participants' UserPass

Per-User Credentials

Scenario: Alice owns Company A, shares it with Bob.

Alice's Device:

Bob's Device (after accepting share):

Isolation:

  • Alice's Private Database has only Alice's UserPass

  • Bob's Private Database has only Bob's UserPass

  • They both access Company A (via Shared Database), but each has their own login

Password Storage

Current Implementation: Plain text in Core Data (encrypted at rest by iOS).

iOS Data Protection:

  • SQLite file encrypted when device locked

  • Requires device passcode or biometric unlock

  • Decrypted when device unlocked

Limitation: Password readable in memory when app running.

Best Practice Enhancement

Recommended: Use Keychain for password storage.

Example Implementation:

Usage:

Benefits:

  • Password stored in Keychain (separate from SQLite)

  • Keychain can require biometric re-auth

  • More secure against memory dumps

Trade-off: Keychain doesn't sync via CloudKit (iCloud Keychain is different). User must re-enter password on each device.

Password Hashing

Current: Not implemented (plain text storage).

Recommended: Hash passwords before storage.

Example:

Usage:

Login Verification:

Limitation: Hashing prevents password recovery (forgot password = must reset).

Multi-Factor Authentication (MFA)

Current: Not implemented.

Future Enhancement:

  • Add mfaSecret: String? to UserPass

  • Implement TOTP (Time-based One-Time Password)

  • Use library like SwiftOTP

Example:

Credential Expiration

Current: Credentials never expire.

Future Enhancement:

  • Add expiresAt: Date? to UserPass

  • Force password reset every 90 days

  • Notify user before expiration

Implementation:

Fetching Credentials

Secure Fetch:

Never Fetch All Passwords:

Fetch only the credential needed for current login.

Deletion

When Deleting Company:

Result: Credential permanently deleted from Private Database.


Related: Security Model, Data Isolation, Login Flow

Last updated