# External authentication

## Goal

QwykPortals provides a built in landing page where you can direct users and from which they can login. However external applications can handle authentication themselves and redirect an authenticated user to QwykPortals so to provide a more fluent experience. In this guide we'll explain how to set this up.

## What you'll need

1. The hostname of our production server `{SERVER_ADDRESS}`
2. The address at which your portal is hosted. `{PORTAL_ADDRESS}`
3. Your Organization ID and the Site ID you want to authenticate the user for. `{ORGANIZATION_ID}` `{SITE_ID} (both integers, not strings)`
4. The user's email address and password `{EMAIL_ADDRESS}` `{PASSWORD}`
5. A server to handle the API requests on, OR contact Qwyk about setting up Cross-Origin Resource Sharing.

All of these can be obtained by sending a message to <support@qwyk.io> if you don't already have them.

## Workflow

The workflow is relatively simple. We'll obtain an access token from the server by authenticating the user with their credentials. With this access token we can then redirect the user to our QwykPortals site. When we  send the user to a correctly formatted URL and pass a valid token, QwykPortals will take care of authenticating them from the server and establish a session in their browser.

{% hint style="warning" %}
We strongly recommend that you execute all authentication requests from your servers and not on the client-side. Without additional configuration client-side requests will fail until CORS has been setup.
{% endhint %}

### Obtain an `access_token` by sending an login request to the server.

Pass the user's credentials to the Qwyk API server to obtain an access\_token with which the user to redirect.

{% tabs %}
{% tab title="HTTP" %}

```http
POST /api/portals/auth/login HTTP/1.1
Host: https://{SERVER_ADDRESS}
Accept: application/json
Content-Type: application/json

{
  "email": "{EMAIL_ADDRESS}",
  "password": "{PASSWORD}",
  "organization_id": {ORGANIZATION_ID},
  "site_id": {SITE_ID}
}
```

{% endtab %}

{% tab title="Bash" %}

```bash
curl --location --request POST 'https://{SERVER_ADDRESS}/api/portals/auth/login' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data-raw '{
	"email": "{EMAIL_ADDRESS}",
	"password": "{PASSWORD}",
	"organization_id": {ORGANIZATION_ID},
	"site_id": {SITE_ID}
}'
```

{% endtab %}

{% tab title="NodeJs - Request" %}

```javascript
var request = require('request');
var options = {
  'method': 'POST',
  'url': 'https://{SERVER_ADDRESS}/api/portals/auth/login',
  'headers': {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({"email":"{EMAIL_ADDRESS}","organization_id":{ORGANIZATION_ID},"password":"{PASSWORD}","site_id":{SITE_ID}})

};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

```

{% endtab %}

{% tab title="Python - Requests" %}

```python
import requests

url = "https://{SERVER_ADDRESS}/api/portals/auth/login"

payload = {
  "email": "{EMAIL_ADDRESS}",
  "password": "{PASSWORD}",
  "organization_id": {ORGANIZATION_ID},
  "site_id": {SITE_ID}
}

headers = {
  'Accept': 'application/json',
  'Content-Type': 'application/json'
}

response = requests.post(url, headers=headers, json = payload)

print(response.text.encode('utf8'))
```

{% endtab %}
{% endtabs %}

Response:

{% code title="Http 200:" %}

```javascript
{
    "access_token": "[...]",
    "token_type": "bearer",
    "expires_in": 7200
}
```

{% endcode %}

### Redirect the user to the portal with the access\_token as a url query parameter.

With the response from the login request, we can then redirect the user to the Portal. In order to do this we'll format a URL and send the user there. The URL takes the following parameters.

* `token` **(required)**
* `token_type` defaults to `bearer`
* `expires_in` defaults to `7200`
* `destination` defaults to `/my-portal`

Token, token\_type and expires\_in can all be copied from the response body. Destination is the path within the portal where the user will be sent after their session has successfully been established.

A correctly formatted URL follow this schema:

```
https://{PORTAL_ADDRESS}/auth/with-token?token={token}&token_type={token_type}&expires_in={expires_in}&destination={destination}
```

For example:

```
https://mydigitalfreight.next.qwykportals.com/auth/with-token?token=[...]&token_type=bearer&expires_in=7200&destination=/my-portal/quotations
```

If the request is well-formed and the token is valid, QwykPortals will establish their Session and redirect them to the specified destination.

## Additional abilities

**External Redirect:** a home and logout redirect address can be configured in your Hub's Site settings to route the user back to the correct landing page, completely bypassing the built-in public homepage after they click the Home button within the site or when they logout.

**Booking Wizard Integration:** to establish an even more fluent workflow, you can start a quotation or booking workflow similar to from the built in homepage by parsing a `destination` formatted as follows:

```
"/my-portal/booking-wizard/cargo?transportMode=OCEAN&loadType=fcl&origin_type=port&origin_code=NLRTM&origin_locode=NLRTM&origin_name=Rotterdam,%20Netherlands&origin_country=NL&destination_type=port&destination_code=SGSIN&destination_locode=SGSIN&destination_name=Singapore,%20Singapore&destination_country=SG"
```

This will start the wizard at the cargo page with routing and product information prefilled from your own site.


---

# 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://docs.qwykportals.com/developer-guides/guides/external-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.
