From 9727a185dddc4ea82ab009532c7f81c434f143b7 Mon Sep 17 00:00:00 2001 From: Danny Roosevelt Date: Thu, 26 Sep 2024 22:02:28 -0700 Subject: [PATCH 1/2] Adding intial info about Connect Link --- docs-v2/pages/connect/index.mdx | 14 ++----- docs-v2/pages/connect/quickstart.mdx | 60 +++++++++++++++------------- 2 files changed, 36 insertions(+), 38 deletions(-) diff --git a/docs-v2/pages/connect/index.mdx b/docs-v2/pages/connect/index.mdx index e738f3e4262ab..64027dbfac042 100644 --- a/docs-v2/pages/connect/index.mdx +++ b/docs-v2/pages/connect/index.mdx @@ -8,10 +8,7 @@ import VideoPlayer from "@/components/VideoPlayer"; **Pipedream Connect is currently in preview, and we're looking for feedback!** -In the preview phase, - -- **Connect is free to use for any workspace**. [Pricing will come later](#plans-and-pricing), likely at a per-user or per-account charge. -- **The API will change without notice, which may cause breaking changes**. We'll do our best to communicate these changes. +**During the preview phase, Connect is free to use for any workspace. The API may change without notice, which may cause breaking changes**. We'll do our best to communicate these changes. Please reach out at `connect@pipedream.com` or our [Slack community](https://pipedream.com/support) to let us know how you're using it, what's not working, and what else you'd like to see. @@ -27,7 +24,7 @@ Connect lets your users authorize access to any API, directly in your app. You c You have full, code-level control over how these integrations work. You handle the product, Pipedream takes care of the auth. Connect provides: -1. A [Client SDK](https://github.com/PipedreamHQ/pipedream/tree/master/packages/sdk) to initiate authorization or accept API keys on behalf of your users, for any of the [{process.env.PUBLIC_APPS}+ APIs](https://pipedream.com/apps) available on Pipedream +1. A [Client SDK](https://github.com/PipedreamHQ/pipedream/tree/master/packages/sdk) or [Connect Link](/connect/quickstart#use-connect-link) to initiate authorization or accept API keys on behalf of your users, for any of the [{process.env.PUBLIC_APPS}+ APIs](https://pipedream.com/apps) available on Pipedream 2. A [REST API](/connect/api) to retrieve credentials for your end users — OAuth access tokens, API keys, and other credentials stored for them 3. The Pipedream platform and its [workflow builder](/workflows), [serverless runtime](/), and thousands of no-code [triggers](/workflows/triggers) and [actions](/workflows/actions) @@ -54,8 +51,6 @@ Watch [the demo](https://www.youtube.com/embed/xhUagMsogkQ) or visit [the quicks During the preview phase, **Connect is free to use for any workspace**. -After the preview phase, Pipedream is likely to charge on the number of end users who have active accounts in your workspace's projects. Any pricing changes will be clearly communicated, and you can delete unused end user accounts at any time. - Please let us know if you have any feedback on the value of Connect and how you'd like to see it priced. ## Security @@ -76,9 +71,8 @@ All credentials and tokens are sent to Pipedream securely over HTTPS, and encryp ## Product roadmap for Connect - Address bugs and feedback during the preview phase -- Simplify the developer experience and SDK integration -- Invoke Pipedream workflows on behalf of end users -- Support hosted UIs for connecting accounts — native support for mobile environments that can't execute JavaScript or load iframes. +- Use Pipedream OAuth clients while in development, to make it easier to get started +- Invoke Pipedream workflows on behalf of your end users - Improve error handling for Connect developers and end users - And more! diff --git a/docs-v2/pages/connect/quickstart.mdx b/docs-v2/pages/connect/quickstart.mdx index 85761d457f543..f16db27d2e479 100644 --- a/docs-v2/pages/connect/quickstart.mdx +++ b/docs-v2/pages/connect/quickstart.mdx @@ -59,7 +59,7 @@ You'll need these when configuring the SDK and making API requests. You'll need to do two things to integrate Pipedream Connect into your app: 1. [Connect to the Pipedream API from your server](#connect-to-the-pipedream-api-from-your-server-and-create-a-token). This lets you make secure calls to the Pipedream API to initiate the account connection flow and retrieve account credentials. If you're running a JavaScript framework like Node.js on the server, you can use the Pipedream SDK. -2. [Add the Pipedream SDK to your frontend](#connect-your-account-from-the-frontend). This lets you start the account connection flow for your end users. +2. [Add the Pipedream SDK to your frontend](#connect-your-account-from-the-frontend) or deliver a URL to your users to start the account connection flow. We'll walk through these steps below, using [an example Next.js app](https://github.com/PipedreamHQ/pipedream-connect-examples/tree/master/next-app/). To follow along, clone [the repo](https://github.com/PipedreamHQ/pipedream-connect-examples/) and follow the instructions in [the app's `README`](https://github.com/PipedreamHQ/pipedream-connect-examples/tree/master/next-app/). That will run the app on `localhost:3000`. @@ -86,8 +86,8 @@ If you're building your own app, you'll need to provide these values to the envi You need to secure specific operations, for example: -- You need to initiate the account connection flow for your end users. In Pipedream Connect, **you exchange your project keys for a short-lived token that allows a specific user to connect a specific app**, and return that token to your frontend. -- If you expose your Pipedream project keys directly to the frontend, anyone could initiate the account connection flow for any user, and you'd be charged for those accounts. +- You need to initiate the account connection flow for your end users. In Pipedream Connect, **you exchange your project keys for a short-lived token that allows a specific user to connect a specific app**, and return either that token or the `connect_link_url` to your frontend. +- If you expose your Pipedream project keys directly to the frontend, anyone could initiate the account connection flow for any user. - You need to retrieve account credentials for your end users. Again, this should happen securely on your server, not in the frontend, to protect your users' data. @@ -165,8 +165,6 @@ const client = new Client({ }); const connectTokenOpts = { - app_slug: "YOUR_APP_SLUG", // The app's name slug - oauth_app_id: "o_abc123", // The OAuth app ID, if you're connecting an OAuth app — keep this in config / a DB, pass here external_id: "USER_ID" // The end user's ID in your system } @@ -217,8 +215,6 @@ client = Client({ }) connect_token_opts = { - 'app_slug': "YOUR_APP_SLUG", - 'oauth_app_id': "o_abc123", 'external_id': "USER_ID" } @@ -262,7 +258,7 @@ public class Client { conn.setRequestProperty("Content-Type", "application/json"); conn.setDoOutput(true); - String jsonInputString = String.format("{\"app_slug\":\"%s\",\"oauth_app_id\":\"%s\",\"external_id\":\"%s\"}", appSlug, oauthClientId, externalId); + String jsonInputString = String.format("{\"external_id\":\"%s\"}", externalId); try (OutputStream os = conn.getOutputStream()) { byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8); @@ -276,7 +272,7 @@ public class Client { Client client = new Client("YOUR_SECRET_KEY", "YOUR_PUBLIC_KEY"); // Expose this code as an API endpoint in your server to fetch the token from the frontend - String response = client.connectTokenCreate("YOUR_APP_SLUG", "o_abc123", "USER_ID"); + String response = client.connectTokenCreate("USER_ID"); } } @@ -313,7 +309,7 @@ public class Client { client.DefaultRequestHeaders.Add("Authorization", auth); client.DefaultRequestHeaders.Add("Content-Type", "application/json"); - var content = new StringContent($"{{\"app_slug\":\"{appSlug}\",\"oauth_app_id\":\"{oauthClientId}\",\"external_id\":\"{externalId}\"}}", Encoding.UTF8, "application/json"); + var content = new StringContent($"{{\"external_id\":\"{externalId}\"}}", Encoding.UTF8, "application/json"); var response = await client.PostAsync($"{baseURL}/v1/connect/tokens", content); return await response.Content.ReadAsStringAsync(); @@ -324,7 +320,7 @@ public class Client { var client = new Client("YOUR_SECRET_KEY", "YOUR_PUBLIC_KEY"); // Expose this code as an API endpoint in your server to fetch the token from the frontend - string response = await client.ConnectTokenCreate("YOUR_APP_SLUG", "o_abc123", "USER_ID"); + string response = await client.ConnectTokenCreate("USER_ID"); } } @@ -364,13 +360,11 @@ func (c *Client) authorizationHeader() string { return fmt.Sprintf("Basic %s", encoded) } -func (c *Client) ConnectTokenCreate(appSlug, oauthClientId, externalId string) (map[string]interface{}, error) { +func (c *Client) ConnectTokenCreate(externalId string) (map[string]interface{}, error) { auth := c.authorizationHeader() url := fmt.Sprintf("%s/v1/connect/tokens", c.BaseURL) opts := map[string]string{ - "app_slug": appSlug, - "oauth_app_id": oauthClientId, "external_id": externalId, } @@ -405,7 +399,7 @@ func main() { client := NewClient("YOUR_SECRET_KEY", "YOUR_PUBLIC_KEY") // Expose this code as an API endpoint in your server to fetch the token from the frontend - response, err := client.ConnectTokenCreate("YOUR_APP_SLUG", "o_abc123", "USER_ID") + response, err := client.ConnectTokenCreate("USER_ID") if err != nil { fmt.Println("Error:", err) return @@ -441,8 +435,6 @@ class Client { $url = "$this->baseURL/v1/connect/tokens"; $data = json_encode([ - 'app_slug' => $appSlug, - 'oauth_app_id' => $oauthClientId, 'external_id' => $externalId ]); @@ -468,8 +460,6 @@ class Client { $client = new Client('YOUR_SECRET_KEY', 'YOUR_PUBLIC_KEY'); $connectTokenOpts = [ - 'app_slug' => "YOUR_APP_SLUG", - 'oauth_app_id' => "o_abc123", 'external_id' => "USER_ID" ]; @@ -499,12 +489,12 @@ class Client "Basic #{encoded}" end - def connect_token_create(app_slug, oauth_app_id, external_id) + def connect_token_create(external_id) uri = URI("#{@base_url}/v1/connect/tokens") req = Net::HTTP::Post.new(uri) req['Authorization'] = authorization_header req['Content-Type'] = 'application/json' - req.body = { app_slug: app_slug, oauth_app_id: oauth_app_id, external_id: external_id }.to_json + req.body = { external_id: external_id }.to_json res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(req) @@ -517,33 +507,34 @@ end client = Client.new('YOUR_SECRET_KEY', 'YOUR_PUBLIC_KEY') connect_token_opts = { - app_slug: "YOUR_APP_SLUG", - oauth_app_id: "o_abc123", external_id: "USER_ID" } # Expose this code as an API endpoint in your server to fetch the token from the frontend -response = client.connect_token_create(connect_token_opts[:app_slug], connect_token_opts[:oauth_app_id], connect_token_opts[:external_id]) +response = client.connect_token_create(connect_token_opts[:external_id]) ``` -In our Next.js app, we call the `serverConnectTokenCreate` method from the frontend to retrieve a token **for a specific user, and a specific app**. +In our Next.js app, we call the `serverConnectTokenCreate` method from the frontend to retrieve a token **for a specific user**. ```typescript import { serverConnectTokenCreate } from "./server" const { token, expires_at } = await serverConnectTokenCreate({ - app_slug: appSlug, // The app's name slug, passed from the frontend - oauth_app_id: oauthAppId, // The OAuth app ID, if you're connecting an OAuth app — keep this in config / a DB, pass here external_id: externalUserId // The end user's ID in your system }); ``` If you're using a different server / API framework, you'll need to make secure calls to that API to create a new token for your users. For example, you might validate a user's session, then call the Pipedream API to create a new token for that user. -### Connect your account from the frontend +### Connect your account +To actually connect an account, you have two options: +1. [Use the Pipedream SDK](#use-the-pipedream-sdk-in-your-frontend) in your frontend +2. [Use Connect Link](#use-connect-link) to deliver a hosted URL to your user + +#### Use the Pipedream SDK in your frontend First, install the [Pipedream SDK](https://www.npmjs.com/package/@pipedream/sdk) in your frontend: ```bash @@ -583,6 +574,19 @@ export default function Home() { Press that button to connect an account for the app you configured. +#### Use Connect Link +- Avoid any frontend implementation +- If you aren't able to execute JavaScript or open an iFrame in your frontend, you can use the `connect_link_url` that's returned from the `connectTokenCreate` method to deliver a URL to your users. +- Before returning the URL to your user, you'll need to include the `app` on the URL. For example, see below. +- Users can open this URL in a browser window to connect their account. + +``` +https://pipedream.com/_static/connect.html?token={token}&connectLink=true&app={appSlug} +``` + +**To test this code, check out this workflow:** +[https://pipedream.com/new?h=tch_6Lf9Dn](https://pipedream.com/new?h=tch_6Lf9Dn) + ### Retrieve the credentials from the backend Once the user connects an account, you can retrieve their credentials from your backend with your project keys. From 74e93c292d6c8359f762c3e4e21511b10605eaeb Mon Sep 17 00:00:00 2001 From: Danny Roosevelt Date: Thu, 26 Sep 2024 22:15:05 -0700 Subject: [PATCH 2/2] Update quickstart.mdx --- docs-v2/pages/connect/quickstart.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs-v2/pages/connect/quickstart.mdx b/docs-v2/pages/connect/quickstart.mdx index f16db27d2e479..70b093dc6f6b6 100644 --- a/docs-v2/pages/connect/quickstart.mdx +++ b/docs-v2/pages/connect/quickstart.mdx @@ -541,7 +541,7 @@ First, install the [Pipedream SDK](https://www.npmjs.com/package/@pipedream/sdk) npm i --save @pipedream/sdk ``` -When the user connects an account in your product, [fetch a token from your backend](#connect-to-the-pipedream-api-from-your-server-and-create-a-token) and call `connectAccount`. This opens a Pipedream iframe that guides the user through the account connection. +When the user connects an account in your product, [fetch a token from your backend](#connect-to-the-pipedream-api-from-your-server-and-create-a-token) and call `connectAccount`. This opens a Pipedream iFrame that guides the user through the account connection. In our example, `app/page.tsx` calls the `connectAccount` method from the Pipedream SDK when the user clicks the **Connect your account** button. @@ -585,7 +585,7 @@ https://pipedream.com/_static/connect.html?token={token}&connectLink=true&app={a ``` **To test this code, check out this workflow:** -[https://pipedream.com/new?h=tch_6Lf9Dn](https://pipedream.com/new?h=tch_6Lf9Dn) +[https://pipedream.com/new?h=tch_EvfbvQ](https://pipedream.com/new?h=tch_EvfbvQ) ### Retrieve the credentials from the backend