Use Userfront live mode token for local development
Tags: react, webdev, userfront, javascript
Published: 2022-12-04 11:23:40


Userfront is a secure, full-featured platform for authentication and access control. It is simple for developers to incorporate into the application. [Userfront React Example](https://userfront.com/examples/react). When we develop it locally (localhost), it will always be in test mode. With the test mode accessToken developers are unable to test the live and sso.

## Is there any way to use the live mode token 
The accessToken from the live mode app will typically be copied by the developer and hardcoded in local for use. I'm utilising a way that **auth0** uses in the **getTokenSilently()** method to automate this.

**_1. Create and deploy a Universal login page_**

To make a login page live, we must first create it and deploy it to a server.

```html
// https://yourdomain.com #1

<html>
<head>
    <script id="Userfront-script">
        // Your Userfront script
    </script>
</head>
<body>
    <script>
        loginPageFunction = function () {
            const params = new URLSearchParams(window.location.search);
            const redirectUrl = params.get('redirectUrl')
            if (redirectUrl) {
                localStorage.setItem('redirectUrl', redirectUrl);
            }
            const token = Userfront.tokens.accessToken;
            if (token) {
                const storageRedirectUrl = localStorage.getItem('redirectUrl');
                if (storageRedirectUrl) {
                    localStorage.removeItem('redirectUrl');
                    location.href = storageRedirectUrl;
                } else {
                    var elemDiv = document.createElement('div');
                    elemDiv.id = "Your Userfront logout token";
                    document.body.appendChild(elemDiv);
                }
            } else {
                var elemDiv = document.createElement('div');
                elemDiv.id = "Your Userfront signin token";
                document.body.appendChild(elemDiv);
            }
        }
        document.onreadystatechange = function () {
            if (document.readyState == "complete") {
                loginPageFunction();
            }
        }
    </script>
</body>
</html>
```
then add a functionality to return accessToken to your localhost
```html
// https://yourdomain.com #final

<html>

<head>
    <script id="Userfront-script">
        // Your Userfront script
    </script>
</head>

<body>
    <script>
        loginPageFunction = function () {
            const params = new URLSearchParams(window.location.search);
            const redirectUrl = params.get('redirectUrl')
            if (redirectUrl) {
                localStorage.setItem('redirectUrl', redirectUrl);
            }
            const token = Userfront.tokens.accessToken;
            if (token) {
                const storageRedirectUrl = localStorage.getItem('redirectUrl');
                if (storageRedirectUrl) {
                    localStorage.removeItem('redirectUrl');
                    location.href = storageRedirectUrl;
                } else {
                    var elemDiv = document.createElement('div');
                    elemDiv.id = "Your Userfront logout token";
                    document.body.appendChild(elemDiv);
                }
            } else {
                var elemDiv = document.createElement('div');
                elemDiv.id = "Your Userfront signin token";
                document.body.appendChild(elemDiv);
            }
        }
        middlewareFunction = function () {
            const targetOrigin = 'http://localhost:3100' or your localhost address;
            const token = Userfront.tokens.accessToken;
            if (token && window.location.ancestorOrigins[0] == targetOrigin) {
                let message = {
                    response_type: "success",
                    token: token,
                    type: 'authorization_response',
                };
                window.parent.postMessage(message, targetOrigin);
            } else {
                let message = {
                    response_type: "error",
                    type: 'authorization_response',
                };
                window.parent.postMessage(message, targetOrigin);
            }
        }
        document.onreadystatechange = function () {
            if (document.readyState == "complete") {
                if (window.location == window.parent.location) {
                    loginPageFunction();
                } else {
                    middlewareFunction();
                }

            }
        }
    </script>
</body>
</html>
```

**_2. get accessToken from live domain_**

To access the token, we now need to add a function to our code. In react, I added a service. yet angular and vue also support the same service. Userfront operates normally in live mode; however, it uses an iframe in local mode to obtain an accessToken.

```javascript

// userFrontService.js

import Userfront from '@userfront/react';
const CLEANUP_IFRAME_TIMEOUT_IN_SECONDS = 2;
const DEFAULT_AUTHORIZE_TIMEOUT_IN_SECONDS = 60;
const EVENT_ORIGIN = 'https://yourdomain.com';
const REQUEST_ORIGIN = 'localhost:3100';

class userFrontService {
  getToken = () => {
    if (window.location.host !== REQUEST_ORIGIN) {
      return new Promise((resolve, reject) => {
        const accessToken = Userfront.tokens.accessToken;
        if (accessToken) {
          resolve(accessToken);
        } else {
          reject(accessToken);
        }
      });
    }
    return new Promise((resolve, reject) => {
      var iframe = window.document.createElement('iframe');
      iframe.setAttribute('width', '0');
      iframe.setAttribute('height', '0');
      iframe.style.display = 'none';
      var iframeEventHandler: any;
      const timeoutInSeconds = DEFAULT_AUTHORIZE_TIMEOUT_IN_SECONDS;

      var removeIframe = function() {
        if (window.document.body.contains(iframe)) {
          window.document.body.removeChild(iframe);
          window.removeEventListener('message', iframeEventHandler, false);
        }
      };
      var timeoutSetTimeoutId = setTimeout(function() {
        reject('error');
        removeIframe();
      }, timeoutInSeconds * 1e3);
      iframeEventHandler = function(e) {
        if (e.origin != EVENT_ORIGIN) return;
        if (!e.data || e.data.type !== 'authorization_response') return;
        var eventSource = e.source;
        if (eventSource) {
          eventSource.close();
        }
        e.data.response_type == 'error' ? reject(e.data) : resolve(e.data.token);
        clearTimeout(timeoutSetTimeoutId);
        window.removeEventListener('message', iframeEventHandler, false);
        setTimeout(removeIframe, CLEANUP_IFRAME_TIMEOUT_IN_SECONDS * 1e3);
      };
      window.addEventListener('message', iframeEventHandler, false);
      window.document.body.appendChild(iframe);
      iframe.setAttribute('src', EVENT_ORIGIN);
    });
  };
  login = () => (location.href = `${EVENT_ORIGIN}?redirectUrl=${location.origin}`);
  isDevEnvironment = window.location.host === REQUEST_ORIGIN;
}
export default new userFrontService();

```
To obtain the accessToken by default, we shall utilise **Userfront.tokens.accessToken**. Here, we'll refer to the service as the following

instead of
`const token = Userfront.tokens.accessToken;`

`const token = await userFrontService.getToken();`


**_3. Change your login accordingly_**


```javascript

  const LoginForm = Userfront.build({
    toolId: 'Your login token ',
  });

  return (
        {userFrontService.isDevEnvironment ? (
          <>
            <Button onClick={() => userFrontService.login()}>Login</Button>
          </>
        ) : (
          <LoginForm />
        )}
      </div>
  );
```

Adding https://yourdomain.com to a private network will increase security by limiting access to only developers working for your organization.


**Thank you for reading, and let's connect!**

- [linkedin](https://www.linkedin.com/in/sundarapandiyan-arumugasundaram-06340316a/)

- [github](https://github.com/sundarapandiyan-pa)