简体   繁体   中英

Laravel Oauth2 client authorizing and redirecting with Guzzle

I'm trying to get access to a rest API using the Authorization Code Flow with Laravel and Guzzle.

They specify the requirements:

GET https://api.restsite.com/oauth2/authorize ?
    client_id = [application id] &
    response_type = code &
    scope = orders inventory &
    redirect_uri = [redirect uri]

In Laravel I achieved it as such:

// Create a client
$client = new Client();

    $request = $client->createRequest(
        'GET', 'https://api.restsite.com/oauth2/authorize',[
            'query' => [
                'client_id' => 'myclientid',
                'response_type' => 'code',
                'scope' => 'inventory',
                'redirect_uri' => 'https://myownsite/uri.php',
            ],
        ]
    );

    // Send the request
    $response = $client->send($request);

If I print_r the $response it will show a login page from their site.

Now, their next instruction is upon successful login it will go to my redirect uri as such:

https://[redirect uri]?code=[authorization code]

With this authorization code I can now make another call by their instructions:

POST https://api.restsite.com/oauth2/token ?
     grant_type = authorization_code &
     code = [authorization code] &
     redirect_uri = [redirect uri]

And finally if all is well the JSON response should look as such:

{
  "access_token": [access token], 
  "token_type": "bearer", 
  "expires_in": 3600
}

Which I can use to access the protected resources at another endpoint.

Now where I'm stuck is in Laravel, after Guzzle makes the first call for the "authorize" endpoint the $response that comes back I wasn't sure what to do with it as I wasn't being automatically redirected anywhere.

So what I temporarily did was added this return view:

return View::make('welcome')->with('response', $response);

That's fine an dandy (looks ugly no css since not actually from their site) but seems to have proper form code when I look at the source.

The current URL is just my project root:

http://myserver:8080/test/public/

However, after I try to login I get redirected to my main root folder of the server:

http://myserver:8080/

I'm not sure how to get it to at least load the redirect URI properly so I can take that URI ?code= parameter and use it to make another call as required.

I hope I didn't loose anyone so far. Thanks in advance!

What I did was instead of using Guzzle to process the authorization initial step from an external site I simply did one of these:

Controller:

return redirect::to('https://api.restsite.com/oauth2/authorize?');

View:

<a href="https://api.restsite.com/oauth2/authorize?">Approve App</a>

I had my redirect uri/callback return to my app to then use Guzzle to post and retrieve the necessary tokens which comes back as a json response so no need for any more external site/redirects.

Finally after all this I can use the actual resource endpoints to query for data.

UPDATE

Upon request I have provided a bit more detail on how the process goes:

View (authtoken.blade.php):

<a href="https://api.restsite.com/oauth2/authorize?client_id=XXX&response_type=code&scope=inventory&redirect_uri=https://myownsite.com/return_uri.php&access_type=offline">Request New Token</a>

return_uri.php ( http://myownsite.com/ )

<?php

ob_start();
$url = 'http://myserver:8080/test/public/authtoken/get';

date_default_timezone_set('America/Los_Angeles');

$authcode = $_GET['code'];

echo 'Authorization code: ' . $authcode;
sleep(15);

$servername = "xx.xxx.xxx.xx";
$username = "user";
$password = "pass";
$dbname = "ca";
$now = date("Y-m-d H:i:s");

if ($authcode) {

    // Create connection
    $conn = new mysqli($servername, $username, $password, $dbname);
    // Check connection
    if ($conn->connect_error) {
        die("Connection failed: " . $conn->connect_error);
    } 

    $sql = "INSERT INTO credentials (id, auth, authDate)
    VALUES ('1','$authcode', '$now') ON DUPLICATE KEY UPDATE auth = values(auth), authDate = values(authDate) ";

    if ($conn->query($sql) === TRUE) {
        echo "Auth code created successfully";
    } else {
        echo "Error: " . $sql . "<br>" . $conn->error;
    }

    $conn->close(); 

    //echo '<br><br><a href="http://myserver:8080/test/public/authtoken/get">go back</a>';

    while (ob_get_status()) 
    {
        ob_end_clean();
    }       

    header( "Location: $url" );

}

?>

Controller

public function authtokenget()
{

    $creds = Credentials::find(1);
    $auth = $creds->auth;

    $client = new Client();

    $client->setDefaultOption('verify', false); 

    $data = 'grant_type=authorization_code&code=$auth&redirect_uri=https://myownsite.com/return_uri.php';
    $data_string = json_encode($data);   
    $datlen = strlen($data_string);

    $request = $client->createRequest(
        'POST', 'https://api.restsite.com/oauth2/token',[
            'headers' => [
                'content-type' => 'application/x-www-form-urlencoded',
                'content-length' => $datlen,
            ],
            'body' => $data_string,
            'auth' => ['xxxxx=', 'xxxxx'],
        ]
    );

    $response = $client->send($request);

}

RECAP

  1. Access the authorize initial endpoint using a link in View.
  2. Have a php return file that's part of the request to grab necessary token/access credentials and store to a database then return to a route.
  3. The route runs a controller function which now grabs the data from the database entry you saved earlier to do as you wish now.

Some days ago I had same problem. Then I read the documentation again and I found that there was an optional parameter "state" that can accept string so I decided to put my route name in state variable and I used it to redirect back to previous route. But it was not proper way I think. So I am also searching for better way. Thank.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM