---
title: Automated-login credential packaging and restoration
summary: Encrypts or restores the credential payload used by automated login flows.
status: draft
owner: <owner>
last_reviewed: 2026-07-30
library: SAIF.Framework.Security
reference_type: package
operation_id: OP-009
trigger: Caller invokes `getEncryptedCredentials()` or `setDecryptedCredentials()`
---

# Automated-login credential packaging and restoration

This is a pair of complementary operations rather than one: `getEncryptedCredentials()` packages a logged-in user's credentials into an encrypted token that a caller can persist for unattended reuse (for example, a scheduled job that logs in without user interaction), and `setDecryptedCredentials()` reverses that transformation to repopulate the login fields from a previously stored token.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-009 |
| **Trigger** | Caller invokes `getEncryptedCredentials()` or `setDecryptedCredentials()` |
| **Inputs** | User ID, private password field, encrypted payload, optional separator override |
| **Outputs** | Encrypted credential string or restored user/password fields |
| **Primary components** | `clsSAIFLoginInfo.getEncryptedCredentials`, `clsSAIFLoginInfo.setDecryptedCredentials`, `DPAPI.Encrypt`, `DPAPI.Decrypt` |
| **Entry point** | `SAIF.Framework.Security\clsSAIFLoginInfo.vb` |

## Steps

1. `getEncryptedCredentials()` assembles the outbound payload as `UserID + separator + password + separator`, then encrypts it with `DPAPI.Encrypt(MachineKey, credentials, ENTROPY_VALUE, "")`, using the library's fixed `ENTROPY_VALUE` constant rather than a per-request value.
2. `setDecryptedCredentials()` first clears `UserID` and `DecryptedPwd`, then selects either the default tab separator or a caller-supplied override for parsing the incoming payload.
   - If `EncryptedLogin` is empty: the method stops after clearing the fields, leaving them blank rather than attempting a decrypt.
3. When encrypted input is present, the method decrypts it with `DPAPI.Decrypt(EncryptedLogin, ENTROPY_VALUE, "")`, splits the result on the chosen separator, and restores `UserID` and the private password field only when the split produces exactly two non-empty parts.
   - If the decrypted payload is malformed or yields an unexpected number of parts: the method silently ignores it and leaves the fields blank, without raising an error.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Credential helper called]) --> Mode{Encrypt or decrypt?}
	Mode -->|Encrypt| Build[Build payload and encrypt]
	Mode -->|Decrypt| Clear[Clear current fields]
	Clear --> Present{Encrypted input present?}
	Present -->|No| EndBlank([Leave fields blank])
	Present -->|Yes| Decrypt[Decrypt and split payload]
	Decrypt --> Parts{Exactly two parts?}
	Parts -->|Yes| Restore[Restore user and password]
	Parts -->|No| EndBlank
	Build --> EndEnc([Return encrypted payload])
	Restore --> EndOk([Fields restored])
```

## Failure and edge-case behavior

- Encryption always uses the same hard-coded `ENTROPY_VALUE` constant rather than a value derived from the request, so the encrypted payload's security depends entirely on `DPAPI.Encrypt`'s machine-key scoping.
- An empty encrypted input leaves the target fields blank instead of raising an error.
- An unexpected decrypted payload shape (not exactly two parts) is ignored silently rather than surfaced to the caller.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [Security and authorization](../security-authorization.md)

## Sources
- `SAIF.Framework.Security\clsSAIFLoginInfo.vb`
- `SAIF.Framework.Security\DAPIEncrypt.vb`
