Create new auths


If you need to prompt your End Users to create new auths from scratch, you can make use of Tray's auth-only dialog:

create-twilio-auth

1 - Generate an auth code for the End User

In order to open the auth collection dialogue so that the user can provide their authentication details, an authorization code needs to be obtained using the Create Auth-dialog authorization code endpoint.

This endpoint requires a master token and the userId created above. The code returned by this endpoint is single-use and expires after 5 minutes:

mutationresponse
Copy
Copied
mutation {
  generateAuthorizationCode(
    input: { userId: "fbb96559-xxxx-xxxx-xxxx-5552c2d2fca4" }
  ) {
    authorizationCode
    clientMutationId
  }
}
Copy
Copied
{
    "data": {
        "generateAuthorizationCode": {
            "authorizationCode": "b8aab26cxxxxxxxxxxxxxxxxxxxx776c7bba7977",
            "clientMutationId": null
        }
    }}

2a - Assemble the auth-only dialog URL

You can now assemble the URL that will be passed to your user to collect authentication details for a particular connector:

https://embedded.tray.io/external/auth/create/{partnerName}?code={authorizationCode}&serviceId={serviceId}&serviceEnvironmentId={serviceEnvironmentId}&scopes[]={scopes}

info

The 'embedded.tray.io' domain can be white-labeled

Please see our page on Custom OAuth apps for more info

You will direct your user to a popup window with this URL.

  • partnerName is the 'Embedded ID' that can be set/viewed in the embedded settings page (seen here)
  • authorizationCode is the single-use authorization code generated in the previous step
  • serviceId was retrieved in the 'Get service version and serviceId' step above
  • serviceEnvironmentId was retrieved in the 'Get serviceEnvironmentId' step above
  • scopes are the OAuth scopes required to ensure that the necessary permissions are set once the OAuth flow is completed:
    • Each scope needs to be passed as an individual parameter, so it should look something like this: &scopes[]=channels:read&scopes[]=channels:write

Available scopes can be identified using the Get service environments endpoint

(Note that this only returns the available scopes and doesn't indicate what scopes are actually required for any particular connector operation. Also note that this may not be a complete list of all available scopes. Please consult 3rd party docs for more information)

Slack example (truncated scopes list)Salesforce example (truncated scopes list)
Copy
Copied
{
    "elements": [
        {
            "id": "35cf89a9-5d49-44b3-ba10-7c78324da260",
            "title": "Production",
            "authenticationType": "oauth2",
            "userDataSchema": {...},
            "credentialsSchema": {...},
            "scopes": [
                {
                    "scope": "chat:write:bot",
                    "description": "Send messages as tray.ai"
                },
                {
                    "scope": "chat:write:user",
                    "description": "Send messages as user"
                },
                {
                    "...": "...",
                    "...": "..."
                }
            ]
        }
    ]
}
Copy
Copied
{
    "elements": [
        {
            "id": "d403c9c6-282b-4b8c-ad02-1655ebccb166",
            "title": "Production",
            "authenticationType": "oauth2",
            "userDataSchema": {...},
            "credentialsSchema": {...},
            "scopes": [
                {
                    "scope": "full",
                    "children": [
                        "id"
                    ],
                    "description": "Allows access to all data accessible by the logged-in user, and encompasses all other scopes (except refresh token)."
                },
                {
                    "scope": "refresh_token",
                    "children": [
                        "id"
                    ],
                    "description": "Allows a refresh token to be returned, allowing for offline access."
                },
                {
                    "scope": "api",
                    "children": [
                        "chatter_api"
                    ],
                    "description": "Allows access to the current, logged-in user's account using APIs, such as REST API and Bulk API. This value also includes chatter_api, which allows access to Chatter REST API resources."
                },
                {
                    "...": "...",
                    "...": "...",
                    "...": "..."
                }
            ]
        }
    ]
}

2b - Example auth-only dialog URL

A valid auth collection URL would look like this:

https://embedded.tray.io/external/auth/create/traydemoaccount?code=5fb286bbxxxxxxxxxxxxxxxx3484c63201f&serviceId=55d1154c-4fd8-4c2c-ba22-041deabfcbfd&serviceEnvironmentId=973b1afa-aa13-42c7-86c3-3964f44c53dd

The service ID and service environment ID correspond to the Twilio connector.

No scopes are required because the Twilio connector uses token-based authentication.

The URL will take your user to a dialogue where they can provide their Twilio credentials:

create-twilio-auth

3 - Retrieving the authId

The auth dialogue sends messages to the window that opened it. You can listen to these events and take action accordingly.

Check out the page on Auth-dialog events.

Here's a snapshot of the success event logged onto the console. You can directly grab the authId from this event and use it in the next steps of the user journey.

tray-authpopup-finish

The other way to get the fresh auths for the user after auth dialouge is finished is to perform the Get User Authentications (user token) endpoint from Users API (GraphQL).

RequestResponse
Copy
Copied
query {
  viewer {
    authentications {
      edges {
        node {
          id
          name
          customFields
          service {
            id
            name
            icon
            title
            version
          }
          serviceEnvironment {
            id
            title
          }
        }
      }
      pageInfo {
        hasNextPage
        hasPreviousPage
      }
    }
  }
}
Copy
Copied
{
  "data": {
    "viewer": {
      "authentications": {
        "edges": [
          {
            "node": {
              "id": "569xxxxxx-xxxxx-xxxx-7e829d2c56d",
              "name": "Roger Ramjet's Slack Account",
              "service": {
                "id": "227312c4-3e5f-4b0d-22a0-5b9630ece00e",
                "name": "slack",
                "icon": "https://s3.amazonaws.com/images.tray.io/artisan/icons/slack.png",
                "title": "Slack",
                "version": "1"
              }
            }
          },
          {
            "node": {
              "id": "0b07xxxxxx-xxxxx-xxxx-b8d4121471c3",
              "name": "Roger Ramjet's Trello Account",
              "service": {
                "id": "72cef4e9-229f-4d7c-97e3-b6cd4d92146f",
                "name": "trello",
                "icon": "https://s3.amazonaws.com/images.tray.io/artisan/icons/trello.png",
                "title": "Trello",
                "version": "1"
              }
            }
          },
          {
            "node": {
              "id": "a29dxxxxxx-xxxxx-xxxx-99901f41c698",
              "name": "Roger Ramjet's Slack Account 2",
              "service": {
                "id": "227312c4-3e5f-4b0d-22a0-5b9630ece00e",
                "name": "slack",
                "icon": "https://s3.amazonaws.com/images.tray.io/artisan/icons/slack.png",
                "title": "Slack",
                "version": "1"
              }
            }
          }
        ]
      }
    }
  }
}