Identity propagation
By default, an Ocean integration executes integration actions using its own credentials. Every pipeline run or pull request it creates appears in the third-party tool as the integration's service account.
With identity propagation, an integration action runs as the user who triggered the workflow, using that user's own credentials in the third-party tool. The tool's audit logs show the real user, and the action is limited to that user's permissions.
Identity propagation is currently supported by the Azure DevOps Trigger a pipeline action, in self-hosted Azure DevOps integrations.
How it works
- Trigger - A user runs a workflow from a self-service trigger. The workflow's integration action node has identity propagation enabled.
- Sign - Port attaches a short-lived identity token to the action run, signed by Port. The token identifies the user and the specific run.
- Verify - The integration verifies the token against Port's public signing keys, and confirms that it belongs to the run it received.
- Look up - The integration looks up the user's access token for the third-party tool in a vault that you own.
- Authorize (first run only) - If no token is stored for the user, the run pauses and waits for the user to sign in. The user signs in to the third-party tool through the integration's OAuth broker, the integration stores the new token in the vault, and the run resumes automatically.
- Execute - The integration executes the action using the user's token.
Stored tokens are refreshed automatically when they expire. If a token cannot be refreshed, for example because the user revoked access, the run pauses and asks the user to sign in again.
User tokens are stored only in your vault and never pass through Port.
What it looks like in code
An executor supports identity propagation by asking Ocean for the user's token before calling the third-party API. The following snippet is adapted from the Azure DevOps trigger_pipeline executor:
from port_ocean.identity_propagation.token_exchanger import resolve_user_token
class TriggerPipelineExecutor(AbstractExecutor):
ACTION_NAME = "trigger_pipeline"
async def execute(self, run: IntegrationRun) -> None:
# Returns None when the run does not use identity propagation.
# Verifies the identity token, reads the user's token from the vault, and
# refreshes it if needed. Pauses the run if the user has to sign in.
user_token = await resolve_user_token(run)
client = self._client_for_token(user_token) if user_token else self.client
pipeline_run = await client.run_pipeline(project_id, pipeline_id, options)
The integration also registers its OAuth provider on startup. The Azure DevOps registry points Ocean's OAuth broker to Microsoft Entra ID:
from port_ocean.identity_propagation.oauth_broker.providers import ProviderDefaults
def register_oauth_provider() -> None:
settings = ocean.config.identity_propagation.oauth.azure_devops
if settings is None:
return
ocean.register_oauth_provider(
defaults=ProviderDefaults(
authorize_url="https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/authorize",
token_url="https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token",
# offline_access makes Entra ID issue a refresh token
scopes=f"{ADO_RESOURCE_ID}/user_impersonation offline_access",
),
settings=settings,
)
Prerequisites
- Self-service trigger - Identity propagation requires a user to act as, so it is available only in workflows with a self-service trigger. Port rejects workflows that combine it with event or schedule triggers.
- Public base URL - The integration's
OCEAN__BASE_URLmust be reachable from your users' browsers, since the sign-in flow redirects them to it. On startup, the integration registers its OAuth broker with Port at<OCEAN__BASE_URL>/v1/oauth-broker/authorize. - OAuth app - An OAuth application registered in the third-party tool, with the redirect URI set to
<OCEAN__BASE_URL>/v1/oauth-broker/callback. For Azure DevOps, register an application in Microsoft Entra ID. - Vault - An AWS Secrets Manager instance that the integration can access, with the
secretsmanager:GetSecretValue,secretsmanager:CreateSecret, andsecretsmanager:PutSecretValuepermissions.
Enable identity propagation in a workflow
Set enableIdentityPropagation to true in the configuration of the integration action node, in the workflow's JSON:
{
"identifier": "trigger_pipeline",
"title": "Trigger pipeline",
"config": {
"type": "INTEGRATION_ACTION",
"installationId": "my-azure-devops-integration",
"integrationProvider": "azure-devops",
"integrationInvocationType": "trigger_pipeline",
"enableIdentityPropagation": true,
"integrationActionExecutionProperties": {
"...": "..."
}
}
}
Configuration
Identity propagation is configured on the integration using the following environment variables.
| Variable | Description | Default |
|---|---|---|
OCEAN__IDENTITY_PROPAGATION__ENABLED | Whether to enable identity propagation. | false |
OCEAN__IDENTITY_PROPAGATION__VAULT__TYPE | The vault used to store user tokens. | aws_secrets_manager |
OCEAN__IDENTITY_PROPAGATION__VAULT__AWS_REGION | The AWS region of the vault. AWS credentials are read from the standard AWS credential chain. | - |
OCEAN__IDENTITY_PROPAGATION__VAULT__SECRET_PREFIX | The prefix of the secrets that hold user tokens. Each secret is named <prefix>/<org_id>/<user_id>/<integration_type>. | port/tokens |
OCEAN__IDENTITY_PROPAGATION__OAUTH__STATE_SIGNING_SECRET | The secret used to sign the sign-in flow's state. When not set, a key is derived from the integration's Port client secret. | - |
OCEAN__PORT__APP_URL | The URL of Port's app, used to redirect users back to the workflow run after signing in. When not set, it is derived from the Port API URL. | - |
For Azure DevOps, configure the OAuth application with the following variables:
| Variable | Description | Default |
|---|---|---|
OCEAN__IDENTITY_PROPAGATION__OAUTH__AZURE_DEVOPS__CLIENT_ID | The client ID of the Entra ID application. | - |
OCEAN__IDENTITY_PROPAGATION__OAUTH__AZURE_DEVOPS__CLIENT_SECRET | The client secret of the Entra ID application. | - |
OCEAN__IDENTITY_PROPAGATION__OAUTH__AZURE_DEVOPS__TENANT_ID | Your Entra ID tenant ID. | - |
OCEAN__IDENTITY_PROPAGATION__OAUTH__AZURE_DEVOPS__SCOPES | The OAuth scopes to request. The default includes offline_access, so users do not need to sign in again every hour. | Azure DevOps user_impersonation and offline_access |
Enabling enableIdentityPropagation on an action that does not support it has no effect, and the action runs with the integration's own credentials.