Hardcoded credentials in RPA flows are a P1 security incident waiting to happen. Learn how to use PAD's sensitive variable type, retrieve secrets from Azure Key Vault through both cloud flow orchestration and direct HTTP calls, and build a credential subflow architecture that survives security audits and secret rotation without touching your flows.

Picture this: your team has built an elegant unattended RPA bot that logs into a legacy ERP system every night, pulls financial data, and populates reports. The flow works perfectly. Then someone runs a quick audit of the desktop flow definition and discovers that the ERP username and password are stored in plaintext inside the flow. The credentials are visible to every environment admin, visible in run history, potentially logged in screenshots during error recovery, and very likely committed to a solutions export sitting in a SharePoint library somewhere. One audit finding later, you have a P1 security incident on your hands.
This is not a hypothetical. It happens regularly in organizations that treat credential management as an afterthought, bolting it on after the automation is already in production. The fix requires understanding exactly how Power Automate Desktop handles sensitive data at each layer — variable storage, the runtime engine, input/output contracts, error logging, and integration with Azure Key Vault — and then designing your flow architecture around those properties from the beginning.
By the end of this lesson, you will understand how sensitive variables actually behave in the PAD runtime, why "mark as sensitive" is necessary but not sufficient, how to retrieve secrets from Azure Key Vault through both cloud-flow orchestration and direct HTTP calls, and how to design a credential architecture that survives security audits, ALM pipeline migrations, and the rotation of secrets without touching a single desktop flow.
What you'll learn:
This lesson assumes you are comfortable with Power Automate Desktop at an advanced level. Specifically, you should already understand:
Before you can protect credentials properly, you need a precise mental model of what "sensitive" means in the PAD runtime — and it is more nuanced than most documentation suggests.
When you declare an input variable or a local variable in PAD and mark it as "Sensitive," you are activating a specific runtime behavior: the value of that variable is stored encrypted in memory and is never written to run logs, action outputs, or the PAD designer's variable preview pane during execution. In the designer, sensitive variable values appear as masked dots in the variables pane. When you view run history in the Power Automate portal, action inputs and outputs that consumed a sensitive variable will show the value as *** rather than the actual content.
This is the right foundation, but you need to understand its exact scope. The sensitive flag protects you in these specific places:
The sensitive flag does not protect you in these places:
Warning
Never set a real credential as the "Default value" of any input variable, sensitive or otherwise. The default value is part of the flow definition and is stored and exported in plaintext. The sensitive flag controls runtime masking, not storage encryption of the definition.
When credentials enter a desktop flow from outside — passed from a cloud flow trigger — they arrive as input variables. When credentials are retrieved inside the desktop flow itself — from a Key Vault HTTP call or a subflow — they typically live as local variables.
The distinction matters for two reasons. First, input variables are part of the flow's public interface; their names, types, and descriptions are visible to anyone who can view the flow's connection in a cloud flow. Second, if an input variable is not marked sensitive, its value will appear in the triggering cloud flow's run history, not just the desktop flow's run history — you now have a credential exposure vector in the cloud flow layer.
The safest pattern is this: any input variable that carries a credential must be marked sensitive in the desktop flow definition, and the cloud flow action that calls the desktop flow must handle the value as a secure string from the moment it is retrieved from Key Vault. We will build this out in detail shortly.
This is the subtlest exposure point and the one that bites the most teams. When you use PAD's error recovery to capture screenshots on failure — which is genuinely useful for debugging — those screenshots capture the screen state at the moment of failure. If your flow failed while a credential was visible on screen (a login dialog, a browser form, a terminal emulator with a visible password field), that screenshot contains the credential in plaintext, saved to wherever your error handling sends it.
The solution is a combination of two things: use sensitive variables correctly so that PAD does not log the value in run metadata, and be thoughtful about which actions capture screenshots in your error handling in desktop flows strategy. Consider disabling screenshot capture specifically for the authentication subflow scope, enabling it only after authentication has completed and credentials are no longer on screen.
Key insight
Treat the authentication phase of your desktop flow as a distinct, protected zone. Wrap it in its own On Block Error handler with screenshot capture disabled, then re-enable error recovery with screenshots for the functional portion of the flow that executes after login.
There are three practical patterns for getting credentials into a desktop flow securely, each with different trade-offs. Understanding when to use each is more valuable than memorizing the mechanics of any one.
This is the most common pattern for unattended flows. A cloud flow retrieves a secret from Azure Key Vault using the Key Vault connector, then passes it to the desktop flow as a sensitive input variable. The desktop flow never touches Key Vault directly; it just consumes what was handed to it.
When to use this:
Security properties:
The desktop flow makes an authenticated HTTP call to the Azure Key Vault REST API, retrieves the secret value, stores it in a sensitive local variable, and uses it. No cloud flow intermediary is involved.
When to use this:
Security properties:
For some applications — particularly web applications that PAD can interact with through the browser — you can store credentials as Power Platform environment variables or connection references and let the platform handle the encryption. This is the least flexible pattern but the easiest to manage.
When to use this:
Security properties:
For the rest of this lesson, we will focus on Patterns 1 and 2, since they cover the hardest and most common real-world scenarios.
Before your cloud flow can retrieve a secret, Key Vault needs to exist with the right access model. In modern Key Vault deployments, use the RBAC authorization model rather than the legacy Access Policies model. This aligns with zero-trust principles and integrates cleanly with Managed Identity.
Create your Key Vault secret with a naming convention that makes rotation and auditing tractable. A good pattern is {environment}-{application}-{credential-type}:
prod-erp-sap-service-account-password
prod-erp-sap-service-account-username
staging-erp-sap-service-account-password
Keeping username and password as separate secrets (rather than a combined JSON blob) gives you independent rotation — you can rotate the password without touching the username entry, which simplifies audit trails.
Assign the Key Vault Secrets User role to the identity that your cloud flow uses to connect. If you are using a Managed Identity for your Power Automate environment (available in premium environments with Azure integration configured), assign the role to that identity. If you are using a service principal, assign it there.
Tip
Never assign Key Vault Secrets Officer or Key Vault Administrator to your automation identity. Secrets User grants the minimum required permission: read the value of a secret. Rotation, deletion, and creation of secrets should require a human identity.
In your cloud flow, add an action from the Azure Key Vault connector. The action you want is Get secret. Configure it with:
https://)When you expand the action settings, look for the option to secure the output. Enable "Secure outputs" on this action. This tells Power Automate's run history engine not to store the action's output in the run log — without this, the secret value would appear in your cloud flow's run history in plaintext.
Warning
Enabling "Secure outputs" on the Key Vault action is not optional — it is the difference between a credential in an encrypted vault and a credential in a run log readable by any environment admin. Make this a hard requirement in your team's flow review checklist.
After retrieving the secret, when you pass it to the Run a flow built with Power Automate Desktop action, the secret value goes into the input variable field. At this point in the cloud flow, also enable Secure inputs on the desktop flow action itself, so the input value is not stored in the cloud flow run history either.
The cloud flow action configuration looks conceptually like this:
Action: Get secret (Azure Key Vault)
Vault name: prod-automation-kv
Secret name: prod-erp-sap-service-account-password
[Secure outputs: ON]
Action: Run a flow built with Power Automate Desktop
Desktop flow: ERP Data Extraction
Run mode: Unattended
Input: SAPPassword = <output from Key Vault action>
[Secure inputs: ON]
In the PAD designer, open the flow's Variables pane and create or edit the input variable for the credential:
SAPPasswordSAP service account password. Retrieved from Key Vault by orchestrating cloud flow.The description matters. It documents the intended source of the value and makes it obvious during code review that a default value would be wrong here.
Do the same for the username. Yes, usernames are often considered less sensitive than passwords, but for compliance-heavy environments (SOX, PCI-DSS, HIPAA), both should be treated as sensitive to avoid username enumeration risks and because audit trails should not reveal which service accounts are used for which systems.
When you use sensitive variables in actions that interact with login forms — whether in a browser, a Windows application, or a legacy terminal — the specific action matters.
For browser-based logins, use the Populate text field on web page action from the web automation actions rather than "Send Keys." Populate text field interacts with the DOM directly and avoids putting the credential through the clipboard or system keyboard buffer.
For Windows application login dialogs, the Populate text field in window action is similarly preferable. It writes directly to the control's text buffer. If you must use Send Keys (some applications require it), ensure the target application is not an application that echoes passwords visibly in other locations (terminals, audit logs).
For legacy mainframe or terminal emulator scenarios — a common RPA target — use the terminal action's credential fields directly rather than simulating keystrokes where possible. If your legacy Windows application automation requires Send Keys into a TN3270 or VT100 session, be aware that many terminal emulators have their own session logging that will capture keystrokes independently of PAD.
# Conceptual flow structure for SAP web login
Set variable: LoginUrl = 'https://erp.contoso.com/login'
# Navigate to login
Open new Chrome tab and go to: %LoginUrl%
# Fill credentials using DOM interaction (not Send Keys)
Populate text field on web page:
Web browser instance: BrowserInstance
UI element: UsernameField (by CSS selector #username)
Text: %SAPUsername%
Populate text field on web page:
Web browser instance: BrowserInstance
UI element: PasswordField (by CSS selector #password)
Text: %SAPPassword%
# Click login
Click link on web page:
UI element: LoginButton
After authentication is complete, consider setting sensitive variables to empty strings explicitly if they are no longer needed:
Set variable: SAPPassword = ''
Set variable: SAPUsername = ''
This limits the window during which live credential values exist in PAD's process memory. It is not a silver bullet — memory forensics can still potentially recover the values — but it is a genuine defense-in-depth measure and demonstrates security hygiene during audits.
When your desktop flow runs attended or in scenarios where a cloud flow orchestrator is not in the picture, you can retrieve secrets directly from Key Vault using PAD's HTTP request action. This pattern requires more setup but gives you complete control over the credential pipeline.
The Azure Key Vault REST API uses OAuth 2.0 bearer tokens. To call it, your desktop flow needs to acquire a token for the https://vault.azure.net audience. There are two practical ways to do this from a PAD desktop flow.
Option A: Managed Identity (preferred for unattended bots)
If your machine is running as an Azure VM (or any Azure-managed compute) and has a system-assigned or user-assigned Managed Identity, you can get a token from the IMDS endpoint without any stored credential whatsoever. The call goes to http://169.254.169.254/metadata/instance (for VMs) or the equivalent for App Service/Container environments.
# Get access token via IMDS (Azure VM Managed Identity)
Invoke web service:
URL: http://169.254.169.254/metadata/token?api-version=2018-02-01&resource=https://vault.azure.net
Method: GET
Headers:
Metadata: true
Store response into: TokenResponse
# Parse the access token from JSON response
Convert JSON to custom object: %TokenResponse%
Set variable: AccessToken = %TokenResponseObject['access_token']%
Mark AccessToken as sensitive in variable properties
Option B: Service Principal Client Credentials (for non-Azure machines)
If your bot machine is on-premises or in a non-Azure environment, you need a service principal. You store the client secret... but where? This is the recursive problem: you need a credential to get a credential. The answer is to use a machine-level secret store.
On Windows, the Windows Credential Manager (accessed via PAD's Credential Manager actions, or via the cmdkey command) can store the service principal's client secret encrypted under the machine's service account identity. Since the service account credential is tied to the Windows authentication of the machine itself, it is effectively protected by the machine's domain membership and the account's Windows credential — not by anything stored in the PAD flow definition.
# Read service principal secret from Windows Credential Manager
Get Windows credential:
Credential name: AzureKVServicePrincipal
Store username into: SPClientId
Store password into: SPClientSecret
# Mark as sensitive immediately
# (PAD marks Get Windows Credential outputs as sensitive automatically)
# Acquire token from Azure AD
Invoke web service:
URL: https://login.microsoftonline.com/{TenantId}/oauth2/v2.0/token
Method: POST
Content type: application/x-www-form-urlencoded
Body: client_id=%SPClientId%&client_secret=%SPClientSecret%&scope=https://vault.azure.net/.default&grant_type=client_credentials
Store response into: TokenResponse
Convert JSON to custom object: %TokenResponse%
Set variable: AccessToken = %TokenResponseObject['access_token']%
Note
PAD's "Get Windows Credential" action retrieves values from Windows Credential Manager with both the username and password outputs automatically marked as sensitive. This is a documented behavior you can rely on — but verify it in your PAD version, as this automatic masking was added in a specific release and older versions may not exhibit it.
Once you have an access token, the Key Vault secret retrieval is a straightforward REST call:
# Retrieve secret from Key Vault
Invoke web service:
URL: https://prod-automation-kv.vault.azure.net/secrets/prod-erp-sap-service-account-password?api-version=7.4
Method: GET
Headers:
Authorization: Bearer %AccessToken%
Store response body into: SecretResponse
Store response status code into: SecretResponseCode
# Validate response
If SecretResponseCode <> 200
Then
Throw error: 'Key Vault secret retrieval failed with status ' + SecretResponseCode
End If
# Parse secret value
Convert JSON to custom object: %SecretResponse%
Set variable: SAPPassword = %SecretResponseObject['value']%
Here is a critical implementation detail: the variable SAPPassword that you set from the parsed JSON is a new local variable. It will not automatically inherit the sensitive flag just because it was populated from a sensitive variable or from a Key Vault response. You must explicitly mark this variable as sensitive in the Variables pane of the PAD designer. If you forget this step, the credential value will appear in run history.
Warning
Variables populated via "Set variable" from any source — including parsing a Key Vault JSON response — are not automatically sensitive. You must manually mark every variable that holds a credential value as sensitive in the PAD Variables pane. This is the most frequently missed step in direct Key Vault integration implementations.
Access tokens have a lifetime — typically 60 minutes for Azure AD tokens targeting Key Vault. For most desktop flows, this is not a concern because the flow completes well within that window. But for long-running flows (multi-hour data processing, flows that process large queues), you need to handle token expiration.
The IMDS and client_credentials responses include an expires_in field (seconds) and an expires_on field (Unix timestamp). Store the expiration time and check it before making Key Vault calls deep in your flow:
# After token acquisition
Set variable: TokenExpiresOn = %TokenResponseObject['expires_on']%
# Later in the flow, before making a sensitive call
Get current date and time into: CurrentTime
Convert CurrentTime to Unix timestamp: CurrentUnixTime
If CurrentUnixTime > (TokenExpiresOn - 300) # 5 minute buffer
Then
# Re-acquire token
Run subflow: AcquireKeyVaultToken
End If
If your organization runs more than a handful of desktop flows, you quickly hit a maintenance problem: the Key Vault integration code is duplicated across every flow that needs credentials. When the Key Vault URL changes, or when the token acquisition logic needs updating, you are editing dozens of flows.
The solution is a dedicated credential retrieval subflow — or ideally a set of them — that encapsulates the Key Vault integration pattern. This aligns with the subflows and reusable logic philosophy and the principle that credential handling should be a solved, tested, centralized concern.
Create a subflow called GetSecret with the following interface:
SecretName (Text, not sensitive — it is the name of the secret, not the value)KeyVaultBaseUrl (Text, not sensitive — it is a configuration value)SecretValue (Text, sensitive — this is the actual credential)The subflow's internal logic:
KVAccessToken and KVTokenExpiresOn)# GetSecret subflow
# Check if we have a valid cached token
Get current date and time into: Now
Convert Now to Unix timestamp: NowUnix
If KVAccessToken = '' OR NowUnix > (KVTokenExpiresOn - 300)
Then
Run subflow: AcquireKVToken
End If
# Call Key Vault
Invoke web service:
URL: %KeyVaultBaseUrl%/secrets/%SecretName%?api-version=7.4
Method: GET
Headers:
Authorization: Bearer %KVAccessToken%
Response body into: RawResponse
Status code into: StatusCode
If StatusCode <> 200
Then
Throw error: 'GetSecret failed for ' + SecretName + ': HTTP ' + StatusCode
End If
Convert JSON to custom object: %RawResponse%
Set variable: SecretValue = %SecretResponseObject['value']%
# SecretValue output variable is marked sensitive in the subflow definition
The calling flow then uses this pattern:
# In main flow - retrieve SAP credentials
Run subflow: GetSecret
Input SecretName: 'prod-erp-sap-service-account-username'
Input KeyVaultBaseUrl: %KVBaseUrl%
Output SecretValue -> SAPUsername
Run subflow: GetSecret
Input SecretName: 'prod-erp-sap-service-account-password'
Input KeyVaultBaseUrl: %KVBaseUrl%
Output SecretValue -> SAPPassword
This architecture means that when Key Vault's API version changes, when you rotate the service principal, or when you add retry logic to handle Key Vault throttling, you update one subflow and every consumer benefits immediately.
Tip
Store KeyVaultBaseUrl as a Power Platform environment variable rather than hardcoding it in each flow. This way, when you promote a solution from staging to production, the URL automatically points to the correct environment's Key Vault. This ties directly into the ALM pipeline and environment variable approach for enterprise-scale deployments.
Security architecture is not complete without threat modeling — systematically identifying every place where credentials can leak and verifying that you have a control in place. Let us walk through the threat model for a typical production credential pipeline.
T1: Flow definition export
T2: Cloud flow run history
T3: Desktop flow run history
T4: Error recovery screenshots
T5: Credential in log file
T6: Token theft from IMDS
T7: Key Vault access log showing unauthorized access patterns
Key insight
Key Vault diagnostic logging is your detective control for everything that cannot be prevented. Enable it for every vault used by automation, route logs to a Log Analytics workspace, and create alerts for anomalous patterns. Secret retrieval should be a predictable, scheduled pattern — any deviation is worth investigating.
T8: Secret value in memory after flow completes
T9: Power Platform connector credential exposure
Credentials must be rotated on schedule and in response to incidents. Your architecture should make rotation a zero-touch operation for desktop flows. The credential subflow pattern achieves this: you update the secret value in Key Vault, and on the next flow run, the subflow retrieves the new value. No flow edits, no redeployments, no environment variable updates.
The one exception is the credential used to access Key Vault itself (the service principal's client secret, if you are using that pattern). Rotating that credential requires updating the Windows Credential Manager entry on the bot machine — a scripted operation that your infrastructure team can run via a deployment script, again without touching any PAD flow.
For organizations with strict rotation schedules (90-day password rotation is common in SOX environments), document the rotation runbook explicitly: which credential store to update (Key Vault secret, Windows Credential Manager entry), which systems need to be tested after rotation, and who is responsible. The automation itself will transparently pick up rotated credentials on its next run.
Desktop flow credential security does not exist in isolation. It is one layer of a broader security model that includes securing Power Automate flows in production — covering connection references, DLP policies, and maker permissions.
The specific intersection points between desktop flow credential security and the broader platform are:
DLP policies and Key Vault connector Data Loss Prevention policies in Power Platform can block the Key Vault connector from being used in certain environments or by certain makers. Ensure your production environment's DLP policy explicitly allows the Key Vault connector for the service accounts that run automation flows. If DLP blocks the connector, your credential retrieval fails silently in ways that are hard to diagnose.
Connection references in solutions When you package your cloud flow (the orchestrator) in a solution, the Key Vault connection should be implemented as a connection reference, not a hardcoded connection. Connection references allow the connection to be swapped at deployment time per environment — your staging cloud flow connects to a staging Key Vault, your production flow connects to production Key Vault, and neither requires the flow definition to be modified. This is exactly the environment variable approach applied to connections.
Environment-level Managed Identity Power Platform premium environments support a tenant-level service principal that can be assigned to an environment. Cloud flows running in that environment can use this managed identity for connector authentication, including Key Vault. This eliminates the per-maker connection credential problem entirely — there is no service account password to rotate for the connector, because authentication happens at the identity platform level.
For more on integrating Azure Key Vault with Power Automate at the platform level — including Managed Identity configuration and the complete zero-trust architecture — see Integrating Power Automate with Azure Key Vault and Managed Identities: Complete Guide to Secrets Management and Zero-Trust Authentication.
In this exercise, you will build a complete credential retrieval flow using the cloud flow orchestration pattern. You will need a Power Automate premium license, an Azure subscription where you can create a Key Vault, and a Power Automate Desktop installation.
In the Azure portal, navigate to Key Vault (create one if needed with the RBAC authorization model enabled). Create two secrets:
exercise-app-username, Value: testuser@contoso.comexercise-app-password, Value: Sup3rS3cr3t!Assign the Key Vault Secrets User role to yourself so you can test retrieval. Later, you would assign it to your automation service principal or Managed Identity.
In Power Automate Desktop, create a new flow called "Exercise - Credential Test." Create the following input variables:
AppUsername — Text, mark as Sensitive, no default valueAppPassword — Text, mark as Sensitive, no default valueAdd these actions to the flow:
# Log that credentials were received (values will be masked in run history)
Write text to console: 'Credentials received. Username length: ' + LENGTH(%AppUsername%)
# Simulate a login action (replace with a real action in practice)
Display message: 'Flow received credentials. Username length: ' + LENGTH(%AppUsername%) + ', Password length: ' + LENGTH(%AppPassword%)
# Immediately clear credentials from memory
Set variable: AppUsername = ''
Set variable: AppPassword = ''
Write text to console: 'Credentials cleared from memory.'
Note that we log the length of the credential, not the value. This is a useful debugging technique — you can confirm that a credential was received (length > 0) without exposing the actual value.
Create an instant cloud flow. Add these actions in sequence:
Azure Key Vault — Get secret: Vault name = your Key Vault, Secret name = exercise-app-username. Enable Secure outputs.
Azure Key Vault — Get secret: Vault name = your Key Vault, Secret name = exercise-app-password. Enable Secure outputs.
Run a flow built with Power Automate Desktop: Select your exercise flow. Set AppUsername = output from step 1 (the value field from Key Vault response). Set AppPassword = output from step 2. Enable Secure inputs.
Run the cloud flow and observe the results:
*** for their outputsAppUsername and AppPassword show as ***As a learning exercise, temporarily create a new local variable in the desktop flow, set its value from AppUsername, and do NOT mark it sensitive. Run the flow and check what appears in run history for that variable. Then mark it sensitive and re-run. This visceral demonstration of what happens when the sensitive flag is absent makes the requirement stick far better than reading about it.
Symptom: Credentials work in testing (developer has values set as defaults in the designer), but in production the credentials need to come from Key Vault. The developer leaves the defaults "just for testing" and they get committed to a solution export.
Fix: Make it a strict rule: sensitive input variables have no default values, ever. Use a separate local test flow or environment variables for development/testing values.
Symptom: Cloud flow run history shows credential values in plaintext in the Key Vault action's output card.
Fix: In the cloud flow action's settings (the three-dot menu on the Key Vault action), expand "Settings" and enable "Secure outputs." This must be done on every Key Vault action, not just once globally.
Symptom: A developer builds a JDBC connection string or API URL with credentials embedded: 'jdbc:sap://erp.contoso.com?user=' + %SAPUsername% + '&password=' + %SAPPassword%. The resulting string is stored in a variable not marked sensitive, and it appears in run history.
Fix: If you must embed credentials in a constructed string, mark the resulting variable sensitive immediately. Better: look for APIs that accept credentials separately from the connection string, or use Windows Credential Manager at the OS level rather than PAD variables.
Symptom: Desktop flows fail intermittently with HTTP 429 errors from Key Vault. This happens when many bot machines are starting simultaneously and all calling Key Vault for credentials.
Fix: Implement the token caching pattern described in the subflow architecture section. The access token should be acquired once and reused for the flow's duration. For the secret value itself, consider acquiring it once at flow start and passing it in memory rather than calling Key Vault before every login action. Key Vault's default throttle limit is 2,000 GET operations per 10 seconds per vault — generous, but reachable in large bot farms.
Tip
For machine groups running 50+ concurrent bots, consider distributing secrets across multiple Key Vaults (e.g., per-region vaults) to avoid throttling. This is an architectural concern that typically only surfaces at scale, but worth knowing before you build a 200-bot fleet against a single vault.
Symptom: The IMDS token acquisition succeeds, but the Key Vault REST API returns HTTP 403 Forbidden.
Fix: The Managed Identity's object ID must have the Key Vault Secrets User role assigned at the scope of the specific Key Vault (or the resource group containing it). Check Azure portal > Key Vault > Access control (IAM) > Role assignments and verify the Managed Identity appears. Common mistake: the role was assigned at subscription scope, which sounds more permissive, but Key Vault with RBAC model requires the role to be assigned at or below the vault's scope level.
Symptom: A subflow's output variable is marked sensitive inside the subflow, but the caller's variable that receives the output is not marked sensitive.
Fix: In PAD, when a subflow returns a value to the calling flow via an output variable, the calling flow's variable that receives the value is a new local variable. The sensitive flag does not propagate across subflow boundaries automatically. You must mark the caller's receiving variable as sensitive explicitly in the calling flow's Variables pane.
Symptom: "Get Windows Credential" action returns an error about not finding the credential entry. The entry exists in your personal Credential Manager but not when the flow runs unattended.
Fix: Windows Credential Manager stores entries per-user profile. When the unattended flow runs under a service account, it has its own Windows profile with its own Credential Manager. The credential entry must be added to the service account's Credential Manager — typically done via a setup script that runs cmdkey /add:AzureKVServicePrincipal /user:%clientId% /pass:%clientSecret% while logged in as the service account, or via a scheduled task that executes during service account login.
Handling credentials securely in desktop flows is not a single feature you enable — it is an architecture discipline spanning variable configuration, cloud flow design, Azure infrastructure, and operational process. The key principles to internalize:
Sensitive variables are necessary but not sufficient. They mask values in run history and the designer, but they do not protect default values in the flow definition, values written to external outputs by your own code, or values that appear on screen during error screenshots.
The credential should never touch the flow definition. Values live in Key Vault. The flow definition contains only the name of the secret and the URL of the vault. This makes the definition safe to export, version-control, and share.
Build your credential retrieval as infrastructure, not inline logic. The GetSecret subflow pattern centralizes Key Vault integration so that rotation, token management, and error handling are solved once and inherited by every consuming flow.
Secure inputs and outputs are mandatory at every layer. Key Vault action outputs, desktop flow inputs, and any intermediate cloud flow actions that handle credential values must all have the secure flags enabled.
Threat model before you ship. Walk every path a credential takes — from Key Vault to vault API call to token to HTTP response to variable to UI field — and verify that each step has an appropriate control.
For your next steps, consider exploring how managing machines and machine groups for scalable unattended automation interacts with credential architecture when you scale to machine groups, where the Managed Identity strategy becomes even more valuable. Also review auditing and governing Power Automate at scale to understand how the CoE Toolkit can help you detect flows in your organization that are not following these credential security patterns — because the hardest part is not building it right the first time, it is finding the flows that were built before you established these standards.