FaxSMS loses log in regularly

This shows all day long. There is not time interval to it that is consistent. Some times we can go all day with this happening then next thing you know. We are login in every 15 mins (it feels like). There are no error messages in the php_error logs.

The error is being thrown here.

public function getPending()
{
    $dateFrom = $this->getRequest('datefrom');
    $dateTo = $this->getRequest('dateto');

    if ($this->authenticate() !== 1) {
        $e = xlt('Error: Authentication Service Denies Access. Not logged in. 6');
        if ($this->authenticate() === 2) {
            $e = xlt('Error: Application account credentials is not setup. Setup in Actions->Account Credentials.');
        }
        $ee = array('error' => $e);
        return json_encode($ee);
    }

I numbered the error messages so I could find which one was throwing the error.
I checked the database and there are credentials in the database.

The token is expiring and not refreshing on its own according to the notes in the Auth.php.
How can I get the system to do the refresh? @adunsulag

Where does the token live? Is it a session token?

The answer to this question is that the token is stored in the session token.

[Fri May 21 16:56:23.663003 2021] [php7:notice] [pid 245289] [client 70.184.171.187:62576] RC Authentication requested, referer: https://ehr.com/interface/main/tabs/main.php?token_main=DkYfUbEjw8HZsRtrMaoCPnDkRUDNgqFCMSSDcBe7
[Fri May 21 16:56:23.663549 2021] [php7:notice] [pid 245289] [client 70.184.171.187:62576] This token eq , referer: https://ehr.com/interface/main/tabs/main.php?token_main=DkYfUbEjw8HZsRtrMaoCPnDkRUDNgqFCMSSDcBe7
[Fri May 21 16:56:24.305810 2021] [php7:notice] [pid 245246] [client 70.184.171.187:62577] Ringcentral info, referer: https://ehr.com/interface/modules/custom_modules/oe-module-faxsms/messageUI.php
[Fri May 21 16:56:24.305835 2021] [php7:notice] [pid 245246] [client 70.184.171.187:62577] RC Authentication requested, referer: https://ehr.com/interface/modules/custom_modules/oe-module-faxsms/messageUI.php
[Fri May 21 16:56:24.306036 2021] [php7:notice] [pid 245246] [client 70.184.171.187:62577] This token eq , referer: https://ehr.com/interface/modules/custom_modules/oe-module-faxsms/messageUI.php
[Fri May 21 16:56:24.306351 2021] [php7:notice] [pid 245246] [client 70.184.171.187:62577] RC Authentication requested, referer: https://ehr.com/interface/modules/custom_modules/oe-module-faxsms/messageUI.php
[Fri May 21 16:56:24.306403 2021] [php7:notice] [pid 245246] [client 70.184.171.187:62577] This token eq , referer: https://ehr.com/interface/modules/custom_modules/oe-module-faxsms/messageUI.php

I set logging in the RCFaxClient.php file

public function authenticate($action_flg = '')
{
    error_log("RC Authentication requested");
    // did construct happen or setup...
    if (empty($this->credentials['username'])) {
        $this->credentials = $this->getCredentials();
        if (empty($this->credentials['username'])) {
            return 2;
        }
    }
    $this->rcsdk = new SDK($this->credentials['appKey'], $this->credentials['appSecret'], $this->serverUrl, 'OpenEMR', '1.0.0');
    $this->platform = $this->rcsdk->platform();
    $authback = $this->cacheDir . DIRECTORY_SEPARATOR . 'platform.json';
    $cachedAuth = array();
    // May use stored auth tokens that may not have expired
    // from last api use. Refresh tokens life is 7 days.
    // Access tokens are 1 hour. sic.. give me a break.
    if (file_exists($authback)) {
        // stored tokens may be expired but, will try em anyway.
        // anything but a ridiculous log in!
        $cachedAuth = file_get_contents($authback);
        $cachedAuth = json_decode($this->crypto->decryptStandard($cachedAuth), true);
        // delete will update with current auth.
        unlink($authback);
    }

    $logged_in = 0;
    // set token data(for eventual request)i.e an action request
    // sendFax, will do an auth check first using this
    // token data array. Session storage token is very
    // unreliable and hardly ever accepted. Still, we try...
    $session_token = $this->getSession('sessionAccessToken');
    error_log("This token eq ", $session_token);
    if (!empty($cachedAuth["refresh_token"])) {
        error_log('session refresh token was empty here');
        // probably new openemr session or user!
        $this->platform->auth()->setData($cachedAuth);
    } elseif (isset($session_token)) {
        $this->platform->auth()->setData((array)json_decode($session_token));
    }
    // verified logged status
    if ($this->platform->loggedIn()) {
        $logged_in = 1;
        error_log("Logged into RC");
        try {
            $this->platform->refresh();
            error_log('Session refresh happend here');
        } catch (\Exception $e) {
            // Give up! Clear old auth stuff afterwards a user
            // most likely will get a OAuth login dialog
            // on return, one would hope!
            unset($_SESSION['sessionAccessToken']);
            error_log('Session was unset');
            $logged_in = 0;
            return $logged_in;
        }
    }
1 Like

maybe a PR is in order then? thanks @juggernautsei

The refresh token is stored as encrypted json at
sites/default/documents/logs_and_misc/_cache/platform.json
This is the important code for refresh

$logged_in = 0;
        // set token data(for eventual request)i.e an action request
        // sendFax, will do an auth check first using this
        // token data array. Session storage token is very
        // unreliable and hardly ever accepted. Still, we try...
        $session_token = $this->getSession('sessionAccessToken');
        if (!empty($cachedAuth["refresh_token"])) {
            // probably new openemr session or user!
            $this->platform->auth()->setData($cachedAuth);
        } elseif (isset($session_token)) {
            $this->platform->auth()->setData((array)json_decode($session_token));
        }

session stored refresh is only a backup and found to be unreliable. Platform.json is encrypted.
Refresh TTL is 1hr.

1 Like

We are missing that file. We are running multi-site. I but in an error_log to log the directory that the system is trying to write to.

The JSON file is not being written to that directory.

The game is a foot!!
Added another error_log at

    $file = $this->cacheDir . DIRECTORY_SEPARATOR . 'platform.json';
    error_log("Site Directory for token", $file);
    // Save authentication data

    $content = $this->crypto->encryptStandard(json_encode($platform->auth()->data(), JSON_PRETTY_PRINT));
    file_put_contents($file, $content);

To find out where the system is trying to write the file to.
The system is not creating the token at all. Still researching to figure out why.

rc_log.txt (8.3 KB)

public function __construct()
    {
        $this->crypto = new CryptoGen();
        $this->baseDir = $GLOBALS['temporary_files_dir'];
        $this->uriDir = $GLOBALS['OE_SITE_WEBROOT'];
        $this->cacheDir = $GLOBALS['OE_SITE_DIR'] . '/documents/logs_and_misc/_cache';
        $this->credentials = $this->getCredentials();
        $this->portalUrl = !$this->credentials['production'] ? "https://service.devtest.ringcentral.com/" : "https://service.ringcentral.com/";
        $this->serverUrl = !$this->credentials['production'] ? "https://platform.devtest.ringcentral.com" : "https://platform.ringcentral.com";
        $this->redirectUrl = $this->credentials['redirect_url'];
        parent::__construct();
    }

yes, @sjpadgett I found that but the code is not writing a file to that directory. That is the mystery to solve.

After line 146 in the code I put in an error log

  error_log("RC Authentication requested", time());

This was to record when the authentication request was fired off. It gets fired and logs the event below.

 RC Authentication requested, referer: https://ehr.medbossconsulting.com/interface/modules/custom_modules/oe-module-faxsms/messageUI.php

Then I wanted to see the token that was created. So after the $session token is populated.

    $session_token = $this->getSession('sessionAccessToken');

This is what is recorded. These are two different session token requests.

   This token eq , referer: https://ehr.medbossconsulting.com/interface/modules/custom_modules/oe-module-faxsms/messageUI.php
   This token eq , referer: https://ehr.medbossconsulting.com/interface/main/tabs/main.php?token_main=7IXDbSPfL7dNlIw21mOZdH5eYPgnCbkYxrJtJ46l

The function below never gets called according to my IDE (PHPStorm). @sjpadgett can you verify that for me please.

       public function processTokenCode(): bool

I used the patch rc_fax_patch_v6.zip. Where should this function be called?

That method isn’t used and is for future events.
FORGET the session_token as it’s not primary source for refresh token, platform.json is…
Read the authenticate() method more closely.

    1. check and get platform.json file
    1. decrypt then delete existing platform.json. (will receive new refresh on auth)
    1. If we don’t have a platform.json refresh then fallback to the session token!
        if (!empty($cachedAuth["refresh_token"])) {
            // probably new openemr session or user!
            $this->platform->auth()->setData($cachedAuth);
        } elseif (isset($session_token)) {
            $this->platform->auth()->setData((array)json_decode($session_token));
        }
    1. Check with RC to see if we already have a login session. If so refresh access token and get new refresh. If not fail for login.
    1. store new refresh in file and session.

On multisite and using only one RC account ensure you have recorded a oauth redirect url for each multisite in RC account settings and each site has it’s redirect set in Actions->Account Credentials

This is not happening, “then fall back to the session token!” in my opinion. Yes, we have the site set in the OAuth Redirect URI.

@sjpadgett
Does the office topography matter?

image

I want to eliminate my thinking along these lines. The login to ring central happens in one of the Florida offices. Is the session token stored on the server or the local machine? What I have observed is that the main office in Florida will log into Ring Central. The moment the Virginia office tries to access the module. They get a error message saying that they are not logged in which I can see because the Virginia office did not log in. The Florida office logged into Ring Central and the session token is stored on the local machine that did the original log.

test_directory.php (351 Bytes)

I ran this test and the test was successful.

Good point Sherwin! I can say that on a per login only one access/refresh token is given. So if the same token is not used by another remote then a new login to reissue would be required. Since each site stores it’s token in their site directory well, all bets are off.

Check with RC or in your account config maybe try to assign an extension to each remote site. You may need to assign a new number to each site.

Fax module treats each site as a separate account.

UPDATE:
@sjpadgett
I changed the system to not delete the platform.json file.

    if (file_exists($authback)) {
        // stored tokens may be expired but, will try em anyway.
        // anything but a ridiculous log in!
        error_log("Trying to delete the json file", time());
        $cachedAuth = file_get_contents($authback);
        $cachedAuth = json_decode($this->crypto->decryptStandard($cachedAuth), true);
        // delete will update with current auth.
        //unlink($authback);
    }

Our issue went away. Do you have a theory as to why?

1 Like

My guess, everyone is using the same token! Have you verified each site directory for multisite has a token?
Also if each site doesn’t have a separate login then that means all sites can see each others faxing work product. Could be a HIPPA violation…

@sjpadgett they are all on the same site. Only one of the multi site is using the RC. No HIPAA violation here. All the different locations are one office not different practices.

1 Like

okay. beats me what’s going on. doesn’t hurt to remove the delete. I just find it odd.
Put up a PR on fax/sms repo and i’ll bring in.

1 Like