# Auth-only dialog

It is possible to allow your users to complete the authentication step using an auth-only dialog, instead of the Configuration Wizard.

## Overview

It is possible to allow your users to complete the authentication step using an auth-only dialog, instead of the Configuration Wizard.
This is useful for integrations that do not require End Users to carry out any personalization beyond authenticating with services.
You can see an example of this being put to use in our demo app with `onCreateAuth` at <https://github.com/trayio/embedded-edition-sample-app/blob/master/src/components/Instance.js>

## Note on whitelabelling

### Whitelabelling the url

Note that you can use an **iFrame** to present this if you wish to 'whitelabel' and hide the `https://embedded.tray.io` url. If you wish to do this your domain will need to be added to our whitelist. Please contact support to arrange this.
You can also whitelabel the url using a custom domain as explained in our [page on whitelabelling public urls](https://tray.ai/documentation/platform/embedded/advanced-features/whitelabelling/public-urls)

### Whitelabelling the dialog CSS

Please see our guide to [whitelabelling auth-only dialog CSS](https://tray.ai/documentation/platform/embedded/advanced-features/whitelabelling/config-wizard) for instructions.

## Using auth-only dialog

In order to use an auth-only dialog you will need to:

1. When editing your Solution, pick up the **External ID** for the authentication from the **Configuration** section:
   ![set-external-id](https://tray.ai/documentation/images/platform/embedded/key-concepts/auth-only-dialog/fd0bc8dd-2e5f4f24_authOnlyDialog.png)
2. Use the [Create Solution Instance](https://tray.ai/documentation/developer/embedded-apis/solution-instances#graphql-create-solution-instance) mutation to generate a **solutionInstanceId** for the End User (this requires an access token for your End User as per [Create User Token](https://tray.ai/documentation/developer/embedded-apis/users#graphql-create-user-token))

### createSolutionInstance API mutation

```graphql
mutation {
 createSolutionInstance(input: \{
   solutionId: "e2ed06d9-xxxx-xxxx-xxxx-218ae63a30b6",
   instanceName: "Webhook demo"
 \}) {
  solutionInstance {
   id
   name
   enabled
   created
  }
 }
}
```

The result will return the id of the Solution Instance:

```json
{
 "data": {
  "createSolutionInstance": {
   "solutionInstance": {
    "id": "9e2e9b86-xxxx-xxxx-xxxx-72e84e266d4d",
    "name": "Webhook demo",
    "enabled": false,
    "created": "2020-10-02T13:06:41.605Z",
    "solution": \{
     "id": "91c0f56f-xxxx-xxxx-xxxx-184686978ea5",
     "title": "Webhook demo",
     "description": ""
    \},
    "authValues": [],
    "configValues": [],
    "workflows": {
     "edges": [
      {
       "node": \{
        "id": "e79e7a66-xxxx-xxxx-xxxx-16b67f870718",
        "sourceWorkflowId": "804c5f50-9e7d-4b50-858b-9338c507ff45",
        "sourceWorkflowName": "Webhook demo",
        "triggerUrl": "https://0ed9f5b2-xxxx-xxxx-xxxx-44ab9507e4ae.trayapp.io"
       \}
      }
     ]
    },
    "solutionVersionFlags": \{
     "hasNewerVersion": false,
     "requiresUserInputToUpdateVersion": false,
     "requiresSystemInputToUpdateVersion": false
    \}
   }
  }
 }
}
```

3. When the End User clicks the relevant button in your app UI, the auth-only dialog is then initiated with a url which contains the **externalAuthId** and **solutionInstanceId** obtained in steps 1 and 2:
   `https://embedded.tray.io/external/auth/create/{embeddedId}/{solutionInstanceId}/{externalAuthId}?code={authorizationCode}`

> **Info:** Please note the auth dialog URL could be different for you if you are in a different region.
> If you are in the EU region, the auth dialog URL for you would be:
> `https://embedded.eu1.tray.io/external/auth/create/{embeddedId}/{solutionInstanceId}/{externalAuthId}?code={authorizationCode}`
> If you are in the APAC region, the auth dialog URL for you would be:
> `https://embedded.ap1.tray.io/external/auth/create/{embeddedId}/{solutionInstanceId}/{externalAuthId}?code={authorizationCode}`

Remember that **embeddedId** is set in the Profile section of the dashboard, as explained [here](https://tray.ai/documentation/platform/embedded/advanced-features/whitelabelling/introduction).
**authorizationCode** is the one-time use code that must be generated as per [Create Config Wizard Authorization Code](https://tray.ai/documentation/developer/embedded-apis/users#graphql-create-config-wizard-auth-code)

### generateAuthorizationCode API mutation

```graphql
mutation {
 generateAuthorizationCode(input: {userId: "fbb96559-xxxx-xxxx-xxxx-5552c2d2fca4"}) {
  authorizationCode
  clientMutationId
 }
}
```

This will return **a one-time use code** which can be used to create **Auth only dialog URL**:

```json
{
 "data": {
  "generateAuthorizationCode": \{
   "authorizationCode": "b8aab26cxxxxxxxxxxxxxxxxxxxx776c7bba7977",
   "clientMutationId": null
  \}
 }
}
```

An example url would then be:
`https://embedded.tray.io/external/auth/create/acme/8b4fc48f-9fcd-43dw-ufu1-1b7a788983c6/external_slack_authentication?code=37d1a4fa990fb412efuh232310ad44ddbc5caed5d`
The End User will then be presented with an authentication dialog for the service being authenticated
with.

> **Info:** You can remove the Tray domain and [whitelabel](https://tray.io/documentation/tray-uac/embedded-integrations/css-and-whitelabelling/intro/) the Config Wizard url. If you have done so then `embedded.tray.io` will be replaced with e.g. `acme.integration-configuration.com`

4. Final step is to use the [Update Solution Instance](https://tray.ai/documentation/developer/embedded-apis/solution-instances#graphql-update-solution-instance) mutation to update the **solutionInstanceId** with authValues for the End User (this requires an access token for your End User as per [Create User Token](https://tray.ai/documentation/developer/embedded-apis/users#graphql-create-user-token))

### updateSolutionInstance API mutation

Use the [updateSolutionInstance](https://tray.ai/documentation/developer/embedded-apis/solution-instances#graphql-update-solution-instance) mutation to set `enabled` to 'true'

```js
mutation {
  updateSolutionInstance(
    input: {
      solutionInstanceId: "9e2e9b86-xxxx-xxxx-xxxx-72e84e266d4d"
      instanceName: "Webhook demo"
      authValues: [
        {
          externalId: "external_slack_authenticaion"
          value: "45ec3104-xxxx-xxxx-xxxx-25e810c0c0e8"
        }
      ]
      enabled: true
    }
  ) {
    solutionInstance {
      id
      name
      enabled
      created
      authValues {
        externalId
        authId
      }
    }
  }
}
```

The returned data will confirm that the Solution Instance contains the authValues:

```json
{
 "data": {
  "updateSolutionInstance": {
   "solutionInstance": {
    "id": "9e2e9b86-xxxx-xxxx-xxxx-72e84e266d4d",
    "name": "Webhook demo",
    "enabled": true,
    "created": "2020-10-02T13:06:41.605Z",
    "authValues": [
     \{
      "externalId": "external_slack_authentication",
      "authId": "45ec3104-xxxx-xxxx-xxxx-25e810c0c0e8"
     \}
    ]
   }
  }
 }
}
```

## Auth-only dialog events

The auth-dialog popup [posts some events](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) to the global window object that can be captured by your user facing application to take further actions.
You can attach a [message event listener](https://developer.mozilla.org/en-US/docs/Web/API/Window/message_event) to the window where user's click on create auth button.
`window.addEventListener("message", onmessage);`
By doing this, you will be able to capture the messages sent by the auth popup window.
The three events you would want to capture from the window are:

* `tray.authPopup.error`
  This event is fired when the auth dialog runs into unexpected errors (ex. mismatched service environment ID and service ID)
* `tray.authpopup.close`
  This event is fired when the auth dialog is closed by the user abruptly
* `tray.authpopup.finish`
  This event is fired when the user provides the auth details and the popup window closes by itself. This event would contain the authId of the newly created auth. Here's how this event's data would look.

```json
\{
  "type": "tray.authpopup.finish",
  "authType": "oauth",
  "authId": "1209xxxx-xxxx-xxxx-xxxx-xxxxxx8d3779"
\}
```

Here is a sample code on how you could structure your `authWindow` function:

```js
export const openAuthWindow = (url) => {
  // Must open window from user interaction code otherwise it is likely
  // to be blocked by a popup blocker:
  const authWindow = window.open(
    undefined,
    "_blank",
    "width=500,height=500,scrollbars=no"
  );
  const onmessage = (e) => {
    console.log("message", e.data.type, e.data);
    if (e.data.type.toLowerCase() === "tray.authpopup.error") {
      // Handle popup error message
      alert(Error: ${e.data.error});
      authWindow.close();
    }
    if (
      e.data.type.toLowerCase() === "tray.authpopup.close" ||
      e.data.type.toLowerCase() === "tray.authpopup.finish"
    ) \{
      authWindow.close();
    \}
  };
  window.addEventListener("message", onmessage);

  // Check if popup window has been closed
  const CHECK_TIMEOUT = 1000;
  const checkClosedWindow = () => {
    if (authWindow.closed) \{
      window.removeEventListener("message", onmessage);
    \} else \{
      setTimeout(checkClosedWindow, CHECK_TIMEOUT);
    \}
  };

  checkClosedWindow();
  authWindow.location = url;
};

const authDialogURL = https://${AUTH_DIALOG_URL}/external/auth/create/${PARTNER_NAME}?code=${json.data?.generateAuthorizationCode?.authorizationCode}&serviceId=${serviceId.current}&serviceEnvironmentId=${selectedServiceEnvironment.id}&scopes[]=${scopes};

openAuthWindow(authDialogURL);
```

You can also check the code of the [embedded demo app](https://github.com/trayio/embedded-demo-app) to see how it's implemented there.
