Forwarded SSL with the PHP Happyr LinkedIn API client
Solve "[Uncaught Exception] Could not get access token" PHP exception when working with the Happyr LinkedIn API client library.
Sometimes when working with a library you hit a problem that isn't covered in the documentation and you need to roll up your sleeves and get stuck in to find solve the issue. I had to do this recently when working a project.
This project needed to make use of the LinkedIn API - so an API library was needed. Happyr/LinkedIn-API-client appeared to do everything that was needed, and looked easy to use. After a quick Composer install, it wasn't long before I had the oAuth flow working and was able to make successful API calls from my development environment.
Time to push to staging and test there - perfect no problems. Brilliant, everything is working, it must be time to push to production. With everything deployed, it was time to check the integration one last time. Suddenly an exception was being thrown during the oAuth flow:
[Uncaught Exception] Could not get access token. An exception. In production. Damn.
After double, and triple checking API keys were correct, reviewing error logs, reading through the documentation and an obligatory search on StackOverflow, I was baffled. Nothing had changed to the code since testing in the dev and staging environments. Time to check the stack trace and go old school with some
Finally, problem found.
In production, the project is served over SSL from a cluster of NGINX web servers sat behind a load balancer - which is where the SSL is terminated. By default,
Happyr/LinkedIn-API-client doesn't trust forwarded SSL - so the library assumed the site was running on HTTP, not HTTPs. This caused the verifying of the callback URL to fail when being returned to the site from LinkedIn during the oAuth flow.
I went and double checked the documentation, and nope, no mention of issues with forwarded SSL. After looking through the source code, it turns out it's an easy fix.
The library uses an instance of
\Happyr\LinkedIn\Http\UrlGenerator to generate URLs - and this is where the current protocol is detected. So, an instance of
UrlGenerator where forwarded SSL is trusted would be needed. It's as simple as:
$urlGenerator = new \Happyr\LinkedIn\Http\UrlGenerator(); $urlGenerator->setTrustForwarded(true);
But at this stage, the connection handler (
\Happyr\LinkedIn\LinkedIn) doesn't know to use this
UrlGenerator. Solving that is easy to:
$connection = new \Happyr\LinkedIn\LinkedIn(); $connection->setUrlGenerator($urlGenerator);
Bingo! The integration with the LinkedIn API was now working successfully.
Moral of the story? Ensure the staging environment matches your production environment as close as possible - ideally it should be a clone. Also, don't give up on a library because something isn't fully documented.