thephpleague / oauth1-client

OAuth 1 Client
MIT License
968 stars 73 forks source link

[Proposal] Allow to send arbitrary requests #20

Closed EliasZ closed 8 years ago

EliasZ commented 9 years ago

As Laravel is using this package underneath Socialite, I thought I might as well keep using it for interacting with an OAuth server (that of Twitter, but more are on the roadmap) after authenticating. So what I did is the following:

However, I get a Authorization Required status response from Twitter. Upon dumping the headers of the internal Guzzle client, all required authorization headers are properly set. My Twitter application has the correct amount of permissions (read & write) to write to the statuses/update resource.

Thanks in advance.

stevenmaguire commented 9 years ago

@EliasZ I would recommend locating a separate library to use when communicating with Twitters API for non-authenticating tasks. While this package does include some basic user account access, you should consider limiting its responsibility to handling the authentication tasks and providing you with the resulting access tokens that will be required for a proper Twitter API client.

EliasZ commented 9 years ago

@stevenmaguire Thanks for your help.

For something which is called an oauth1-client I would have expected a bit more functionality, especially sending arbitrary requests? If I knew a bit more about oauth, I would have done it myself by simply extracting the authorization and header logic required from the abstract Server its fetchUserDetails method. If the building of a Guzzle client with the mandatory authorization headers/parameters is separated from fetchUserDetails, any method can use that client as a stub and additionally define its own HTTP verb, endpoint and parameter(s). It would be a lot more flexible.

But it's okay, I checked out thujohn/twitter (2.0) and it does seem to work out-of-the-box with the tokens earlier retrieved. So I now have two oauth libraries as a dependency; one which can only authorize against a variety of servers and one specifically for the Twitter server which can authorize and do a bit more.

Using authorization from this package "and a bit more" from the other, feels counter intuitive, especially because with some minor (?) modifications this package could also do a bit more. All of this does not only apply to the Twitter server, if the abstract Server has the proper toolset, all providers can easily gain additional functionality other than authorization.

Having said all of that, if I find some spare time I will definitely take a stab at solving this issue myself. If someone else already understands the problem and is capable of solving it, your input is appreciated!

bencorlett commented 9 years ago

This package never was intended to be, and never will be, an API package for every conceivable OAuth provider.

This package is designed for authentication and retrieval of tokens. Do with the tokens what you will, be it store them, use them against an API or you could build a collage of tokens to use as your wallpaper. Point is, this package fills a specific need by design.

For what it's worth, picture something like GitHub'a API. Last I checked (I remember reading about phasing this out), you could provide an OAuth 2 access token or plain HTTP auth to make requests. A GitHub API SDK is a perfect contender to deal with its API. How you get your tokens, or indeed username / password is up to you.

Sent from my iPhone

Please excuse my brevity

On 22 Mar 2015, at 8:32 pm, EliasZ notifications@github.com wrote:

@stevenmaguire Thanks for your help.

For something which is called an oauth1-client I would have expected a bit more functionality, especially sending arbitrary requests? If I knew a bit more about oauth, I would have done it myself by simply extracting the authorization and header logic required from the abstract Server its fetchUserDetails method. If the building of a Guzzle client with the mandatory authorization headers/parameters is separated from fetchUserDetails, any method can use that client as a stub and additionally define its own HTTP verb, endpoint and parameter(s), it would be a lot more flexible.

But it's okay, I checked out thujohn/twitter (2.0) and it does seem to work out-of-the-box with the tokens earlier retrieved. So I now have two oauth libraries as a dependency; one which can only authorize against a variety of servers and one specifically for the Twitter server which can authorize and do a bit more.

Using authorization from this package "and a bit more" from the other, feels counter intuitive, especially because with some minor modifications this package could also do a bit more.

— Reply to this email directly or view it on GitHub.

EliasZ commented 9 years ago

I am not saying this package should feature a full-fledged SDK for every provider, just to make it possible to send arbitrary requests. So other packages can use this client as a base and extend it for platform-specific functionality.

It currently allows to step through the oauth1 authorization process and send a few provider-based hard-coded resource-requests (one of them is fetching user data, others are needed for the authorization process).

Wouldn't it be better to split the common authorization-process and the querying of resources? So there is one element/component which does the oauth1-authorization-process and another component which can send authenticated requests to resources. The latter was what I expected an oauth1-client can do.

If this package is only intended for quickly doing the authorization-dance and have an easy time being used for other oauth1-providers, then this decoupling is not needed and indeed you will then have to use this library and an additional specific package which you can then feed the retrieved tokens and send other platform-specific requests with. That specific package will often also feature an oauth-client and because it is specific, it will already contain functionality for the authorization process.

Does any of this make sense?

bencorlett commented 9 years ago

I get what you're saying. I'd need to talk to the others in the League to see what the direction of the OAuth-2 client is, as I'd like to move the packages along together. @shadowhand, thoughts?

shadowhand commented 9 years ago

This is exactly what #18 made possible. Here's some sample code:

protected function getCredentials(array $token)
{
    $credentials = new TokenCredentials;
    $credentials->setIdentifier($token['identifier']);
    $credentials->setSecret($token['secret']);
    return $credentials;
}

public function post($url, array $body = [])
{
    $credentials = $this->getCredentials($this->getToken());

    $headers  = $this->client->getHeaders($credentials, 'POST', $url, $body);
    $request  = $this->client->createHttpClient()->post($url, $headers, $body)->send();
    $response = $request->getBody();

    return json_decode($response);
}

The rest of the code in the class is specific to our implementation of token storage, but this should be enough to illustrate how you can build a generic "middleware" for API requests.

shadowhand commented 9 years ago

I should also say that oauth2-client has a much more advanced interface for this in v1.0:

$request = $provider->getAuthenticatedRequest($method, $url, $token);
// any modifications you need to make, set POST body, etc
$response = $provider->getResponse($request);

A similar interface could be developed for oauth1-client, but it would require using a PSR-7 compatible HTTP client, which would require a major version bump, as the interfaces would be incompatible.