# Authentication

## Forge Modal

To streamline authentication, we've created an SDK that auto generates a popup window to allow your users to quickly auth their accounts. Authentication, of course, is required for every app you link to Alloy Forge.

Because we integrate with hundreds of different apps, every authentication is unique. Some apps use the OAuth standard which involves redirecting a user to a single sign on page (i.e. Google Sheets) and then back to your application while others use API keys.  Luckily, Alloy Forge takes the headache out of authentication via our easy to use modal. As you'll see in this section, using the Forge modal is easy and painless – just import our SDK and pass the short term authentication token. Let's take a closer look.

### Forge SDK

First things first, let's import the Forge SDK into your frontend. Note that the SDK is a frontend library and is available via a vanilla JS script. You can import our SDK here:

```
https://cdn.runalloy.com/scripts/alloy.js
```

You can see an example of the modal below.

![](/files/AxzpwPQmiiPEVKS6Fq3Z)

Once you've imported the SDK, to invoke the workflow we can call the `openModalWorkflow()` method. This method will invoke the Alloy Forge popup (also known as the modal) on any page you call this on.

This method takes a handful of required inputs: the short term **User Token** and the **workflowId** from the L[ist Workflows](https://gregg.gitbook.io/alloy-developer/reference/api-reference/workflows#list-workflows) endpoint. It returns a `childWorkflowId` which should be saved to your database. We'll use this identifier later on to activate the workflow. For more information on how this workflow operates behind the scenes, please read the [Child Workflows](https://gregg.gitbook.io/alloy-developer/forge-concepts#parent-and-child-workflows) tutorial.

```
Alloy.openWorkflowModal(
    <ENTER-TOKEN-HERE>,
    <WORKFLOW-ID-HERE>,
    (childWorkflowId) => { /* Save this childWorkflowId in your db */ },
    { alwaysShowCredentials: true, allowInstantWorkflowCreation: true }
);
```

{% hint style="warning" %}
Make sure you store the `childWorkflowId` value in your database for future use later on. Alloy Forge will not re-surface this identifier so you'll only have one time to save this.
{% endhint %}

### Redirection URL

Once you've instantiated the Forge Modal, you're almost all set. However, it's important to consider the different types of authentication the various apps we integrate utilize. The simplest type, API Key, will just render an input field asking the user to copy/paste their API Key into Forge.

![](/files/X1icSfA5I26HGl3Pu5Ud)

Of course, this is fine and all, but what not every app uses API Key. Some apps, like Shopify, Mailchimp, Google Sheets, etc use OAuth. In fact, many times OAuth is the preferred authentication method for end users because it doesn't require they copy/paste API Keys and reduces the chance for user error.

![](/files/fq7ZzZxWxLMEJee0upNi)

Fortunately, we've made it easy to handle redirect URLs. Note that when a user authenticates an OAuth supported app, they're first taken away from your app and then routed to the third party to confirm their intent to authorize. But once they've authorized, we need to send them back to your app. To configure this, navigate over to the Forge Settings page and at the bottom, find the **Redirect URLs** section. From there, add your URL and hit **save**. And that's it!

![](/files/0TVExILxqwFZU4OvkrFh)

## Hiding the Modal

Sometimes, it's not always appropriate to show the Forge modal. Let's take an example: you've asked your customer to authenticate their Shopify account already and want to allow them to enable another workflow. However, you don't need to show the modal flow since they've already authenticated before. Showing the modal again would only serve to confuse them.

Luckily, we've baked logic into the forge modal to make it easy to detect when conditions like this are met. The `openModalWorkflow` method definition is defined below.

```
 openWorkflowModal: (
      token,
      workflowId,
      callback,
      { alwaysShowCredentials, allowInstantWorkflowCreation }
 )
```

As you can see, this method's fourth argument allows you to customize when and how to show the modal. For instance, let's assume the user has already authenticated their credential as in our example above but we want to show them the second page of the modal (the configuration page). We could simply pass `{ false, false }` values.  Let's visualize this in an example below.

If `alwaysShowCredentials` is true, then the modal will always show the credentials page. However, if `allowInstantWorkflowCreation` is true, the Forge Modal will automatically check two things:&#x20;

1. Does the user have all the required credentials for the workflow in question?
2. Does the workflow require any user customization (as defined by the **Show Fields to Merchants** option)

If both #1 and #2 are false, then setting `allowInstantWorkflowCreation` to true will hide the workflow modal. However, if either of the conditions above is true, the modal will show.

## Manually Adding Credentials

Sometimes, there are edge cases where you already have a user's authentication key. That's why we've added an endpoint add credentials programmatically. Note that in almost all use cases, adding a credential via the Forge Modal is the best route (and when adding credentials programmatically for apps that use OAuth, things get even more complicated)

### Credential Metadata API

First things first, in order to create a credential via the API, you'll need to hit our **Credential Metadata API** which returns a description of the credential. Notice in the example below, the `type` returned. If the `type` is `apiKey` then it's easy to add a credential. However, if the `type` is `oauth` then you'll need to register an OAuth app with the provider in question and give Forge your client Id and secret.

To specify a custom client Id and secret, navigate to the Forge Settings > Secrets Manager and find the app you want. You can read more about specifying custom app Ids [here](/alloy-developer/custom-oauth-apps.md).

{% hint style="danger" %}
If you do not specify a custom client id and secret but intend to use the manual credential endpoint, then any OAuth apps will be invalid because Alloy Forge uses default Alloy client Id and secrets which will cause a mismatch.
{% endhint %}

![](/files/F4zpXBZRYAID9GjMpGKo)

## Credential Metadata

<mark style="color:blue;">`GET`</mark> `https://api.runalloy.com/forge/2021-12/credentials/availableServices`

This endpoint returns a basic structure of what data must be inputted when adding a credential manually.&#x20;

The `type` value indicates if the credential uses OAuth or API key.  The `requiredParameters` contains a `name` field(s) which describes the necessary credentials you must supply when invoking the Create Credential endpoint.

#### Query Parameters

| Name                                     | Type   | Description                              |
| ---------------------------------------- | ------ | ---------------------------------------- |
| userId<mark style="color:red;">\*</mark> | String | The `id` of the currently logged in user |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
    "data": [
        {
            "name": "acuitySchedulingApi",
            "displayName": "Acuity",
            "icon": "https://cdn.runalloy.com/icons/acuityScheduling.png",
            "type": "apiKey",
            "requiredParameters": [
                {
                    "name": "apiKey",
                    "displayName": "API Key"
                },
                {
                    "name": "userId",
                    "displayName": "User Id"
                }
            ]
        },
        {
            "name": "aircallApi",
            "displayName": "Aircall",
            "icon": "https://cdn.runalloy.com/icons/aircall.png",
            "type": "oauth",
            "requiredParameters": []
        },
        {
            "name": "airtableApi",
            "displayName": "Airtable API",
            "icon": "https://cdn.runalloy.com/icons/airtable.png",
            "type": "apiKey",
            "requiredParameters": [
                {
                    "name": "apiKey",
                    "displayName": "API Key",
                    "description": "You can retrieve your key in the API section of this page: https://airtable.com/account"
                }
            ]
        },
        {
            "name": "asanaApi",
            "displayName": "Asana",
            "icon": "https://cdn.runalloy.com/icons/asana.png",
            "type": "oauth",
            "requiredParameters": []
        },
        {
            "name": "attentiveApi",
            "displayName": "Attentive Legacy",
            "icon": "https://cdn.runalloy.com/icons/attentive.png",
            "type": "apiKey",
            "requiredParameters": [
                {
                    "name": "apiKey",
                    "displayName": "API Key"
                }
            ]
        },
        {
            "name": "attentiveNewApi",
            "displayName": "Attentive",
            "icon": "https://cdn.runalloy.com/icons/attentive.png",
            "type": "oauth",
            "requiredParameters": []
        },
        {
            "name": "aws",
            "displayName": "AWS",
            "icon": "https://cdn.runalloy.com/icons/undefined",
            "type": "apiKey",
            "requiredParameters": [
                {
                    "name": "region",
                    "displayName": "Region"
                },
                {
                    "name": "accessKeyId",
                    "displayName": "Access Key Id"
                },
                {
                    "name": "secretAccessKey",
                    "displayName": "Secret Access Key"
                }
            ]
        },
        {
            "name": "bigcommerceApi",
            "displayName": "BigCommerce",
            "icon": "https://cdn.runalloy.com/icons/bigcommerce.png",
            "type": "oauth",
            "requiredParameters": [
                {
                    "name": "storeHash",
                    "displayName": "Store Hash",
                    "description": "Enter your store hash. If your store domain is store-xyz.mybigcommerce.com, the store hash would be xyz."
                }
            ]
        }
    ]
}
```

{% endtab %}
{% endtabs %}

### Create a Credential

To add a credential via the API, you need to invoke the below endpoint.

## Create a Credential

<mark style="color:green;">`POST`</mark> `https://api.runalloy.com/forge/2021-12/credentials/userCredentials`

#### Query Parameters

| Name                                     | Type   | Description                                               |
| ---------------------------------------- | ------ | --------------------------------------------------------- |
| userId<mark style="color:red;">\*</mark> | String | The `id` of the user you want to create a credential for. |

#### Request Body

| Name                                   | Type   | Description                                                                                                              |
| -------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------ |
| type<mark style="color:red;">\*</mark> | String | The name of the credential you're adding. This corresponds with the `name` of the credential from the metadata endpoint. |
| data<mark style="color:red;">\*</mark> | object | An object of key-value pairs conforming to the metadata endpoint containing the credentials for a specific credential.   |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
    "success": true
}
```

{% endtab %}
{% endtabs %}

This endpoint can be a bit confusing so let's take a look at an example. Assuming we're trying to add a BigCommerce credential, we would look for BigCommerce in the metadata endpoint and it returns something like this:

```
{
    "type":"bigcommerceApi",
    "data":{
        "storeHash": "Your Store Hash Value",
        "accessToken": "Your BigCommerce Access Token"
    }
}
```

So in order to create a credential for BigCommerce, we'd supply a payload to the create credential endpoint with something like:

```
{
  "type": "bigcommerceApi",
  "data": {
      "storeHash": "m7sn35Ds",
      "accessToken": "a4289c19-94dd-49c6-a20d-b167c00b3afb"
    }
}
```

### List User Credentials

This endpoint will return an array of credentials already created for the specified user.&#x20;

## List User Credentials

<mark style="color:blue;">`GET`</mark> `https://api.runalloy.com/forge/2021-12/credentials/userCredentials`

#### Query Parameters

| Name                                     | Type   | Description                                            |
| ---------------------------------------- | ------ | ------------------------------------------------------ |
| userId<mark style="color:red;">\*</mark> | String | The `id` of the user you want to list credentials for. |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
    "data": [
       {
            "name": "driftApi",
            "createdAt": "2020-03-25T15:48:18.318Z",
            "updatedAt": "2020-03-25T15:48:18.318Z"
        },
        {
            "name": "asanaApi",
            "createdAt": "2020-03-30T18:21:26.659Z",
            "updatedAt": "2020-03-30T18:21:26.659Z"
        },
        {
            "name": "airtableApi",
            "createdAt": "2020-04-01T20:37:54.960Z",
            "updatedAt": "2020-04-01T20:37:54.960Z"
        }
    ]
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gregg.gitbook.io/alloy-developer/reference/api-reference/authentication.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
