Pipedream Connect lets your users authenticate third-party apps inside your product. Here is everything you need to know before you ship it.

What Pipedream Connect Is

Pipedream Connect is a component of Pipedream that handles OAuth and API key authentication on behalf of your users. Instead of building OAuth flows for every service your product integrates with, Connect provides a hosted UI where users connect their apps (Slack, Google, Salesforce, 2000+ others), and Pipedream stores and refreshes the tokens. Your workflows use those tokens to act on behalf of the user.

It is a genuinely useful product that saves months of OAuth infrastructure work. It also has specific constraints that are not obvious until you are deep into implementation.

The Basic Architecture

// Your backend: create a Connect token for a user
// This token authorises a specific user to connect an app in your UI
 
const response = await fetch("https://api.pipedream.com/v1/connect/tokens", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PIPEDREAM_API_KEY}`,
    "Content-Type": "application/json",
    "X-PD-Environment": "production",
  },
  body: JSON.stringify({
    external_user_id: "your-user-id-123",  // your app's user ID
    allowed_origins: ["https://yourapp.com"],
  }),
});
 
const { token } = await response.json();
// Send this token to your frontend to initiate the Connect flow
// Your frontend: initiate the Connect UI for the user
import { createClient } from "@pipedream/sdk";
 
const pd = createClient({ environment: "production" });
 
async function connectSlack() {
  const result = await pd.connectAccount({
    app: "slack",
    token: connectToken,   // token from your backend
    onSuccess: ({ id: accountId }) => {
      // Store this accountId in your database -- it references the connected account
      saveAccountId(userId, "slack", accountId);
    },
  });
}
// Your Pipedream workflow: use the connected account on behalf of the user
export default defineComponent({
  props: {
    slack: {
      type: "app",
      app: "slack",
    },
  },
  async run({ steps, $ }) {
    // The connected account is automatically used -- no manual token handling
    const result = await fetch("https://slack.com/api/chat.postMessage", {
      headers: { Authorization: `Bearer ${this.slack.$auth.oauth_access_token}` },
      // ...
    });
  },
});

Key Constraints to Know Before You Build

1. The authentication UI shows Pipedream branding

When users go through the Connect flow to authorise an app, they see Pipedream's UI and brand. For internal tools and developer products this is usually fine. For consumer products or enterprise SaaS with white-label requirements, you need the Enterprise plan for a white-label option, or you need to build your own OAuth proxy.

The OAuth consent screen tells users that Pipedream will have access to process their data. For enterprise contracts with strict data processing addenda, this may require review before you can use Connect.

3. You cannot inspect or modify token storage

Tokens are stored and managed entirely by Pipedream. You cannot export them, move them to your own vault, or inspect them. If you ever leave Pipedream, you cannot migrate stored tokens -- users would need to re-authenticate in any replacement system.

4. Account management is API-only

There is no Pipedream UI for viewing or revoking specific user accounts at scale. You manage connected accounts entirely through the API.

Managing Accounts Programmatically

const PD_API_KEY = process.env.PIPEDREAM_API_KEY;
const baseHeaders = {
  Authorization: `Bearer ${PD_API_KEY}`,
  "X-PD-Environment": "production",
};
 
// List all connected accounts for a user
async function getUserAccounts(externalUserId) {
  const resp = await fetch(
    `https://api.pipedream.com/v1/connect/${externalUserId}/accounts`,
    { headers: baseHeaders }
  );
  return resp.json();  // returns array of connected app accounts
}
 
// Revoke a specific connected account (e.g. when user disconnects)
async function revokeAccount(externalUserId, accountId) {
  await fetch(
    `https://api.pipedream.com/v1/connect/${externalUserId}/accounts/${accountId}`,
    { method: "DELETE", headers: baseHeaders }
  );
}
 
// Revoke ALL accounts for a user (e.g. on account deletion -- GDPR)
async function deleteAllUserAccounts(externalUserId) {
  const { accounts } = await getUserAccounts(externalUserId);
  await Promise.all(accounts.map(acc => revokeAccount(externalUserId, acc.id)));
}
Wire deleteAllUserAccounts into your user deletion flow before launch. GDPR and similar regulations require that connected app tokens be revoked when a user deletes their account. Missing this is a compliance gap.

Handling Token Refresh Failures

OAuth tokens expire. Pipedream handles refresh automatically -- but refresh can fail if the user revokes access from the third-party app's side, or if the third-party API has an outage. Your workflows need to handle this gracefully.

export default defineComponent({
  props: { slack: { type: "app", app: "slack" } },
  async run({ steps, $ }) {
    try {
      const result = await callSlackApi(this.slack.$auth.oauth_access_token);
      return result;
    } catch (error) {
      if (error.status === 401) {
        // Token is invalid or revoked -- notify your app so the user can reconnect
        await notifyUserToReconnect(steps.trigger.event.userId, "slack");
        $.flow.exit("Token revoked -- user notified to reconnect");
      }
      throw error;  // re-throw other errors
    }
  },
});

Quick Reference

  • Create a Connect token per user from your backend -- never expose your API key to the frontend
  • Store the accountId returned by onSuccess in your database -- it is your reference to the connected app
  • Revoke accounts on user deletion -- wire this into your GDPR/data deletion flow
  • Handle 401 errors in workflows by notifying the user to reconnect
  • White-label auth requires Enterprise plan -- plan for this in your pricing model if selling to enterprise
  • You cannot export or migrate stored tokens -- factor this into your vendor lock-in assessment