53

Full Error

RequestException in CurlFactory.php line 187: cURL error 60: SSL certificate problem: unable to get local issuer certificate (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)

Scenario

Before anyone points me to these two laracasts answers: https://laracasts.com/discuss/channels/general-discussion/curl-error-60-ssl-certificate-problem-unable-to-get-local-issuer-certificate

https://laracasts.com/discuss/channels/general-discussion/curl-error-60-ssl-certificate-problem-unable-to-get-local-issuer-certificate/replies/52954

I've already looked at them and that's why I'm here.

The problem I have is that now I have the cacert.pem file BUT it doesn't make sense where to put it, the answers indicate to place the file in my xampp directory and change my php.ini file but I'm not using xampp for anything, I'm using Laravel's artisan server to run my project.

If xampp is not in use, where should I place this file? Moreover, why would an accepted answer be to place it in my xampp directory? I dont understand.

My Exact Question

Where do I place the cacert.pem file to stop this error in laravel 5.4?

guyaloni
  • 4,972
  • 5
  • 52
  • 92
Yasmin French
  • 1,154
  • 3
  • 12
  • 25
  • 1
    Don't use the laravel built-in web server to try to resolve this. It's an exercise in futility since you're also going to need to re-resolve the issue on the webserver you'll be using on production. Just install apache or something and install the certificate based on the requirements of apache. – apokryfos Feb 07 '17 at 16:27
  • 1
    @apokryfos I figured the problem out – Yasmin French Feb 07 '17 at 16:30
  • 2
    Then do post the solution. It may help someone somewhere. – apokryfos Feb 07 '17 at 16:31
  • 2
    You can use `withOptions` method to turn verification off: `$res = Http::withOptions(['verify' => false])->get('ur-api-endpoint');` – Shahroq Oct 25 '22 at 13:27

17 Answers17

190

Do not ever modify files in the vendor/ folder. Ever. They can and will be overwritten on the next composer update you run.

Here is my Solution for WampServer

I am using PHP 7.1.9 for my WampServer, so change 7.1.9 in the example below to the version number you are currently using.

  1. Download this file: http://curl.haxx.se/ca/cacert.pem
  2. Place this file in the C:\wamp64\bin\php\php7.1.9 folder
  3. Open php.iniand find this line:

;curl.cainfo

Change it to:

curl.cainfo = "C:\wamp64\bin\php\php7.1.9\cacert.pem"

Make sure you remove the semicolon at the beginning of the line.

Save changes to php.ini, restart WampServer, and you're good to go!

kjdion84
  • 9,552
  • 8
  • 60
  • 87
  • 3
    It works, and I also think, that this is so important: DON'T TOUCH the ```vendor/``` folder. – laze Mar 31 '18 at 00:42
  • 1
    This feels like the right way to fix the problem, but somehow it does not work. I have php 7.1.11 – Agil May 28 '18 at 18:20
  • Worked for me. Thanks – Prateek Nov 25 '18 at 18:18
  • And just to be extra clear: it works for IIS setups as well (not only Wamp). The focus is really enabling the certificate. – Daniel Dec 11 '18 at 17:46
  • 4
    Note that there are several versions of `php.ini` in the Wamp environment. This solution may lead to use the version stored within the current php version directory. Actually, it may not be the one loaded by Wamp. Sounds better to use Wamp Menu > PHP > php.ini. which may lead to the version within the Apache directory, that is actually loaded. – Yako Jan 29 '19 at 18:39
  • 2
    This worked. Can you briefly explain/describe what is going on here? Thank you. – Sem Jan 30 '19 at 06:41
  • uOowww man!! thanks thanks very much! this another solution --> `$client = $client ?: new Client(['verify' => false]);` not work!!! – Fábio Zangirolami Jun 18 '20 at 23:05
  • i have done all the mentioned steps but now it is showing this error AWS HTTP error: cURL error 77: error setting certificate verify locations – Nadeem Ijaz Oct 01 '20 at 10:27
  • The cacert.pem link is broken. I think that the correct one is curl.se/ca/cacert.pem – Srdjan Pazin Oct 13 '21 at 08:24
  • The given solution worked for me. correct cacert.pem link is https://curl.se/ca/cacert.pem – B-shan Nov 08 '21 at 10:16
  • 1
    In my case i use Wamp Server 3.2.6. You need to do the same but in phpForApache.ini. unless it won't work. – Thusitha Wickramasinghe Jan 25 '22 at 15:02
  • Thanks, this still worked for me on Laravel 8.x and in the year 2022 while using PHP 7.4.0. LOL – Vic Iyke Aug 29 '22 at 22:27
31

A quick solution but insecure (not recommended).

Using cURL:

Set CURLOPT_SSL_VERIYPEER to false

Using Guzzle: Set verify to false, for example

$client->request('GET', 'https://somewebsite.com', ['verify' => false]);
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Jeffrey
  • 1,998
  • 1
  • 25
  • 22
  • 8
    thanks this is working for me laravel 7+ ```$res = \Http::withOptions(['verify' => false])->get("http://somewebsite.com"); ``` – Subramanya Rao Jan 02 '21 at 08:09
16

You can use GuzzleHttp\Client:

$client = new Client(['verify' => false]);

Simas Joneliunas
  • 2,890
  • 20
  • 28
  • 35
Farrux Choriyev
  • 179
  • 1
  • 5
9
  • Solution suggested by some users to make changes to \vendor\guzzlehttp\guzzle\src\Client.php file is the worst advice, as manual changes made to vendor folder are overwritten if you run composer update command.
  • Solution suggested by Jeffrey is a dirty, shorthand fix but not recommended in production applications.
  • Solution suggested by kjdion84 is perfect if you have access to php.ini file on web server. That is, to update curl.cainfo="<absolute_path_here>\cacert.pem" in php.ini file.
  • In case you are using Shared Hosting, it may not be possible to edit php.ini file.

When you don't have access to php.ini file (e.g. Shared Hosting)

  1. Download this file: http://curl.haxx.se/ca/cacert.pem or https://curl.se/docs/caextract.html
  2. Place this file in the root folder of your Laravel project.
  3. Add verify key to GuzzleHttp\Client constructor with its value as path to cacert.pem file.
  4. Now depending on whether you are using core PHP or Laravel framework pick a solution from below.

Solution 1: Using PHP 5.5+ and GuzzleHttp 6.0+

// https://example.com/v1/current.json?key1=value1&key2=value2

$http = new \GuzzleHttp\Client([
    'base_uri' => 'https://example.com',
    'verify' => base_path('cacert.pem'),
]);

$response = $http->get('v1/current.json', [
    'query' => [
        'key1' => 'value1',
        'key2' => 'value2',
    ]
]);

$response = json_decode($response->getBody()->getContents(), true);

Solution 2: Using Laravel 5.7+ and GuzzleHttp 6.0+

use Illuminate\Support\Facades\Http;

// https://example.com/v1/current.json?key1=value1&key2=value2

$http = new \GuzzleHttp\Client([
    'base_uri' => 'https://example.com',
    'verify' => base_path('cacert.pem'),
]);

$response = Http::setClient($http)->get('v1/current.json', [
    'query' => [
        'key1' => 'value1',
        'key2' => 'value2',
    ]
]);

$response = json_decode($response->getBody()->getContents(), true);
Hamza Rashid
  • 1,329
  • 15
  • 22
7

This was stressfull to figure out but here is the exact answer for people using laravel and have this problem.

My exact application versions are...

Laravel: 5.4

Guzzlehttp: 6.2

Laravel Socialite: 3.0

Download a fresh copy of this curl certificate from this link: https://gist.github.com/VersatilityWerks/5719158/download

Save the file in this path starting from the base root of your laravel application vendor/guzzlehttp/guzzle/src/cacert.pem

next in that same directory open up RequestOptions.php and scroll down to the constant called CERT and change it to this const CERT = 'cacert.pem'; and this should fix it all.

EDIT

As people are pointing out you should never edit the vendor folder, this was just a quick fix for an application I was building in my spare time. It wasn't anything majorly important like an application for my company or anything, use this method at your own risk! Please check out the other answers if you need something more concrete.

Yasmin French
  • 1,154
  • 3
  • 12
  • 25
  • It didn't seem to work for me. What php version did you use and what localhost wamp(64/32) or xamp? – Vasilis Greece Sep 05 '17 at 19:21
  • 1
    My xampp at the time was the latest php7 version, I can't remember exactly which one i used sorry – Yasmin French Sep 11 '17 at 08:05
  • +1 thanks a lot, I tried all the other solutions but this was the only one that worked.. just jump into the vendor/guzzlehttp/guzzle/src folder and do a "wget http://curl.haxx.se/ca/cacert.pem" to get a fresh copy – maximus 69 Jan 24 '18 at 12:35
  • But I heard a loooot of times that I should not mess around vendor – Agil May 29 '18 at 17:24
  • @Nikonah then don't, i should mention this was just a quick fix that worked for me. not sure of any alternatives – Yasmin French May 30 '18 at 11:08
3

I was sending a request from domain X to Y, my problem was with the certificate used on the domain Y (it wasn't a self-signed cert btw), the domain belonged to me & I had the certificate, so the quick fix was to use the domain Y's certificate on domain X's application:

On domain X:

  • Using Laravel 7 HTTP wrapper:

    \Http::withOptions(['verify' => 'path-to-domain-Y-certificate']);

  • Using guzzle:

    new GuzzleHttp\Client(['verify' => 'path-to-domain-Y-certificate']);

OR you could just contact your SSL provider to resolve the issue.

Note: Storing your domain's certificate in another system isn't a secure method, use this method only if you can ensure your certificate's security.

I haven't found what was wrong with the certificate, no browser seemed to have a problem with it, the only problem was generated on laravel using curl.

Amir Hossein Abdollahi
  • 1,253
  • 2
  • 9
  • 14
2

I had this problem while running Valet and attempting to make an api from one site in valet to another. Note that i'm working in OSX. I found the solution here: https://github.com/laravel/valet/issues/460 In short you have to copy the valet pem to the system CA bundle. Just run this:

cp /usr/local/etc/openssl/cert.pem /usr/local/etc/openssl/cert.pem.bak && cat ~/.config/valet/CA/LaravelValetCASelfSigned.pem >> /usr/local/etc/openssl/cert.pem
omarjebari
  • 4,861
  • 3
  • 34
  • 32
2

This happened to me in development with laravel 8 using the default server started by running:

php artisan serve

The solution for me was similar to other answers that require you to download cacert.pem and edit php.ini file. But since I was not using Wamp, I checked the path in my environment variables to find which php installation windows defaulted to and made the changes there.

crazy_abdul
  • 503
  • 6
  • 12
2

I use laragon server and I faced to the same problem. I downloaded ssl certificate from http://curl.haxx.se/ca/cacert.pem and paste it in C:/laragon/etc/ssl/ (if cacert.pem already exists replace it with new one). restart server and everything is fine

Sharif
  • 31
  • 5
1

We can set path based on this article on Medium.com How to fix cURL error 60: SSL certificate problem

Steps to follow:

  1. Open http://curl.haxx.se/ca/cacert.pem
  2. Copy the entire page and save it as a “cacert.pem”
  3. Open your php.ini file and insert or update the following line. curl.cainfo = " [pathtofile]cacert.pem"
Yagnesh Khamar
  • 184
  • 3
  • 8
1

For php version ^8.1 in wampserver

  1. Download--> https://curl.se/ca/cacert.pem.
  2. Place the cacert.pem file inside C:\wamp64\bin\php\php8.1.0.
  3. Open php.ini and find this line: ;curl.cainfo

Change it to:

curl.cainfo = "C:\wamp64\bin\php\php8.1.0\cacert.pem"

Make sure you remove the semicolon at the beginning of the line.

Save changes to php.ini, restart WampServer64, and you're good to go!

Aswin Blix
  • 109
  • 1
  • 5
0

Another one recently asked for the same problem and it's seems my answer was the solution for him. Here was the post I mention : URL Post

That's what I said :

I'll be fully honest, I don't know anything about Laravel. But I had the same problem, so as many other, on Symfony. And so as you I tried many things without success.

Finally, this solution worked for me : URL solution

It indicates that instead of a certificate problem, it could came from a environnement non-compatibility. I used XAMPP instead of WAMP and it worked.

Community
  • 1
  • 1
Doshibu
  • 156
  • 3
  • 10
0

Solved it on my end by disabling verify completely when on debug setting since in this local scenario security is not an issue at all.

$http = new \GuzzleHttp\Client([
            'base_uri' => config('services.passport.login_endpoint'),
            'verify' => config('app.debug') ? false : true,
            'defaults' => [
                'exceptions' => false,
            ]
        ]);
onewaveadrian
  • 434
  • 1
  • 6
  • 17
0

You need to edit the following file in vendor/guzzlehttp/guzzle/src/Client.php

$defaults = [
    'allow_redirects' => RedirectMiddleware::$defaultSettings,
    'http_errors'     => true,
    'decode_content'  => true,
    'verify'          => false, //  By default this value will be true
    'cookies'         => false
];

May be security issue was there, but it will work.

cokeman19
  • 2,405
  • 1
  • 25
  • 40
0
curl.cainfo = "C:\wamp64\bin\php\php7.1.9\cacert.pem"

I had resolved my problem with wamp.

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
0

The problem in my case was that i was connected to a wifi network that was blocking the api i'm accessing. When i connected to the internet using mobile data the issue resolved.

Tarik Waleed
  • 97
  • 1
  • 8
-3

for Laravel: The 5 steps below will be helpful

  • update version to Guzzlehttp: 5.2
  • find the file under \vendor\guzzlehttp\guzzle\src\Client.php
  • edit default settings to

    protected function getDefaultOptions() { $settings = [ 'allow_redirects' => true, 'exceptions' => true, 'decode_content' => true, 'verify' => getcwd() .'/vendor/guzzlehttp/guzzle/src/cacert.pem' ]; }

  • download latest file cacert.pem from http://curl.haxx.se/ca/cacert.pem and place under /vendor/guzzlehttp/guzzle/src/

Sudheesh Singanamalla
  • 2,283
  • 3
  • 19
  • 36