Skip to main content

When to Build a Custom UI

For most use cases, we recommend using the Auth SDK. It’s quick to implement and automatically handles MFA and other edge cases. Build a custom authentication UI only when you:
  • Need full UI control - Your design requires a specific authentication experience that doesn’t fit the SDK’s UI
  • Have existing auth flows - You want to integrate Deck into an existing authentication system

Prerequisites

Integration Guide

1

Set up environment variables

Configure your Deck API credentials as environment variables. These are required to generate SDK tokens and must never be exposed in frontend code. Both keys are available in your Dashboard..env
DECK_CLIENT_ID=your_client_id_here
DECK_CLIENT_SECRET=your_secret_here
2

Build Credential Collection Form

Create a form to collect user credentials. Most sources require username and password, but requirements vary by provider.
function CredentialForm({ onSubmit, isLoading }) {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    onSubmit({ username, password });
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>Username or Email</label>
        <input
          type="text"
          value={username}
          onChange={(e) => setUsername(e.target.value)}
          required
        />
      </div>
      <div>
        <label>Password</label>
        <input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          required
        />
      </div>
      <button type="submit" disabled={isLoading}>
        {isLoading ? 'Connecting...' : 'Connect Account'}
      </button>
    </form>
  );
}
3

Run the EnsureConnection Job

When the user submits credentials, call the EnsureConnection job from your server-side code. You will need to pass both the user’s credentials as well as the source you want to connect to. This job runs asynchronously and returns results via webhook.
Connections stay open for 1 hour.
curl --request POST \
  --url https://sandbox.deck.co/api/v1/jobs/submit \
  --header 'x-deck-client-id: <your-client-id>' \
  --header 'x-deck-secret: <your-secret>' \
  --header 'Content-Type: application/json' \
  --data '{
    "job_code": "EnsureConnection",
    "input": {
      "source_guid": "<source-guid>",
      "username": "<username>",
      "password": "<password>"
    }
  }'
Available parameters on EnsureConnection
source_guid
string
required
The unique identifier of the source you want to connect to. See the Sources guide for more information.
username
string
required
Your user’s username or email for the source they’re connecting to. In Sandbox, any value can be used as authentication is simulated.
password
string
required
Your user’s password for the source they’re connecting to. In Sandbox, any value can be used as authentication is simulated.
external_id
string
Customer identifier from your system. Link a Deck connection to your customer ID to look up connections by your external identifier in the Dashboard.
webhook_url
string
Custom webhook URL to receive events for this connection. Overrides the default webhook URL configured in your Dashboard.
target_url
string
Target URL for the connection. Used to specify a specific endpoint or page to navigate to during authentication. For example YouTube may be your source, and the Target URL would be a specific video.
account_id
string
Used when a set of credentials has multiple accounts attached to it and you want to target a specific account.
4

Handle MFA Challenges (If Required)

If the source or user’s preferences requires MFA, your webhook will receive an MFA challenge. Display the appropriate UI to collect the MFA answer and submit it.Collect MFA Answer from User:
function MfaForm({ message, onSubmit, isLoading }) {
  const [answer, setAnswer] = useState('');

  return (
    <form onSubmit={(e) => {
      e.preventDefault();
      onSubmit(answer);
    }}>
      <label>{message}</label>
      <input
        type="text"
        value={answer}
        onChange={(e) => setAnswer(e.target.value)}
        placeholder="Enter code"
        required
      />
      <button type="submit" disabled={isLoading}>
        Verify
      </button>
    </form>
  );
}
Submit MFA Answer:
curl --location 'https://sandbox.deck.co/api/v1/jobs/mfa/answer' \
  --header 'x-deck-client-id: <api-key>' \
  --header 'x-deck-secret: <api-key>' \
  --header 'Content-Type: application/json' \
  --data '{
    "job_guid": "b3ab44de-f722-4685-ab3a-b27b369e859b",
    "answer": "123456"
  }'
5

Receive Access Token via Webhook

Once authentication is successful, your webhook receives the access token.Success Webhook Payload:
{
  "job_guid": "b3ab44de-f722-4685-ab3a-b27b369e859b",
  "output": {
    "access_token": "access-sandbox-xyz789..."
  },
  "webhook_type": "Job",
  "webhook_code": "EnsureConnection",
  "environment": "Sandbox"
}
6

Use Access Tokens to Run Jobs

Use the access token to run jobs on behalf of the user. Jobs can read data (e.g., fetch documents, invoices) or write data (e.g., submit orders, update records).Job results are also delivered via webhook. See the Jobs guide for more information.