PHPackages                             mfrost503/snaggle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. mfrost503/snaggle

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

mfrost503/snaggle
=================

An OAuth 1.0 Client Library

1.0.1(10y ago)37103[1 issues](https://github.com/mfrost503/Snaggle/issues)1MITPHPPHP &gt;=5.4.0

Since Oct 17Pushed 10y ago1 watchersCompare

[ Source](https://github.com/mfrost503/Snaggle)[ Packagist](https://packagist.org/packages/mfrost503/snaggle)[ Docs](https://github.com/mfrost503/Snaggle)[ RSS](/packages/mfrost503-snaggle/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (2)Versions (9)Used By (1)

Snaggle
-------

[](#snaggle)

[![Build Status](https://camo.githubusercontent.com/7ee3cfeb37d3ec68c417fe748c42aa56d39237474b5557912e3f23dadfd95cd0/68747470733a2f2f7472617669732d63692e6f72672f6d66726f73743530332f536e6167676c652e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/mfrost503/Snaggle)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/dfd5f8e4bbd308e42356c64128ec373b9fcbfcb8fe2d3ceb5927d736e2dce2cc/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6d66726f73743530332f536e6167676c652f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/mfrost503/Snaggle/?branch=master)[![Build Status](https://camo.githubusercontent.com/d7b4f26d2c1644ea7fe99ccdb586e09994f8847ccb7add310451843f8037b6b5/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6d66726f73743530332f536e6167676c652f6261646765732f6275696c642e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/mfrost503/Snaggle/build-status/master)

Snaggle is an OAuth 1 Client Library that can be used to generate signatures and the appropriate OAuth 1 Headers. While OAuth 2.0 is suggested for building a new API, there are still plenty of popular services that use OAuth 1.0.

Installation
------------

[](#installation)

Snaggle should be installed via composer:

```
"require": {
    "mfrost503/snaggle": "1.0.0"
}

```

### OAuth 1.0 Client Examples

[](#oauth-10-client-examples)

OAuth 1.0 requires the use of Access and Consumer tokens, being able to create a valid signature will unlock the content of an OAuth 1.0 APi.

```
use Snaggle\OAuth1\Client\Credentials\AccessCredentials;
use Snaggle\OAuth1\Client\Credentials\ConsumerCredentials;
use Snaggle\OAuth1\Client\Signatures\HmacSha1;
use Snaggle\OAuth1\Client\Signatures\Plaintext;
use Snaggle\OAuth1\Client\Header\Header;

// first we need to represent our tokens, these should be stored securely
$consumer = new ConsumerCredentials('CONSUMER_KEY', 'CONSUMER_SECRET');

$access = new AccessCredentials('ACCESS_TOKEN', 'ACCESS_SECRET');

$signature = new HmacSha1($consumer, $access)
    ->setResourceURL('https://api.example.com/v1/users')
    ->setHttpMethod('get');

$header = new Header();
$header->setSignature($signature);
$header->createAuthorizationHeader();
```

There's also a plaintext signature type (which should only be used when there is no other way and over https), it implements the signature interface and uses the signature parent, so it's use is the same as HmacSha1, only the instantiation differs

```
$signature = new Plaintext($consumer, $access);
```

This line can be used interchangeably with the signature instantiation in the previous example.

Signatures
----------

[](#signatures)

This library has an implementation of HMAC-SHA1 and Plaintext signatures, these signatures are used to communicate the identity of the resource owner making the request. Services can have different requirements for how a signature is built, the signatures in this library are built to the OAuth 1.0 spec.

### HMAC-SHA1

[](#hmac-sha1)

HMAC-SHA1 is the more secure of the two signature types in this library and is the most commonly used. This signature involves the creation of a base string and composite key that are encapsulate and hash the information required to identify with an OAuth 1.0 service.

### Plaintext

[](#plaintext)

Plaintext signatures should only be used over https, because they aren't secure. Services like Twitter don't allow you to use the Plaintext signature, but they can be very handy if you are working with an internal API and the complexity of a signature doesn't provide a real strong security benefit.

HTTP Client
-----------

[](#http-client)

Snaggle does not come with an HTTP client included in the library, the reason for that is there are HTTP Clients that are very well done, but everyone's needs and access to these tools maybe different. Those clients do a great job at the job they're meant to do, which is make HTTP requests. Snaggle's role in this process is to provide the headers that are required to make OAuth 1 requests work properly and handing those off to whatever client you choose to use.

There are a couple different cases when it comes to providing headers to clients. For example, when setting a header in cURL you'll have to send the `'Authorization: '` prefix, but with Guzzle you'll just want the content of the headers. Snaggle gives you the option to generate the headers with or without the prefix. Below is an example of each using Guzzle and cURL:

### Guzzle

[](#guzzle)

In Guzzle, we don't want the prefix so the ` $header->creationAuthorizationHeader()` has a parameter ` $includePrefix` that is set to false by default. So here's how you'd use it with a client that doesn't need the header prefix.

```
$header = new Header();
$header->setSignature($signature);
$authorizationHeader = $header->createAuthorizationHeader();

$client = new Client();
$client->get('https://api.example.com/v1/users', [
	'headers' => ['Authorization' => $authorizationHeader]
]);
```

### cURL

[](#curl)

cURL will require the prefix when adding the header to the request. In order to do this, we'll just need to pass the parameter `true` to the ` $header->createAuthorizationHeader();`

```
$header = new Header();
$header->setSignature($signature);
$authorizationHeader = $header->createAuthorizationHeader(true);

$ch = curl_init('https://api.example.com/v1/users');
curl_setopt($ch, CURLOPT_HTTPHEADER, [$authorizationHeader]);
```

By using this approach, we can decouple the generation of the OAuth 1 Headers from the HTTP Client that will eventually be used to send the requests.

Making token requests
---------------------

[](#making-token-requests)

One of the more challenging aspects to understand is the token exchange, which is necessary for communicating with a resource server. Essentially there are a number different times where some back and forth communication needs to happen. Here's an example of how you could use this library to retrieve an access token from Twitter.

```
use \Snaggle\Client\Credentials\ConsumerCredentials;
use \Snaggle\Client\Credentials\AccessCredentials;
use \Snaggle\Client\Signatures\HmacSha1;
use \Snaggle\Client\Header\Header;
use \GuzzleHttp\Client;

$consumer = new ConsumerCredentials('CONSUMER KEY', 'CONSUMER_SECRET');
$access = new AccessCredentials();
if (!isset($_GET['oauth_token']) && !isset($_GET['oauth_verifier'])) {

    $signature = new HmacSha1($consumer, $access);
    $signature->setResourceURL('https://api.twitter.com/oauth/request_token')
              ->setHttpMethod('post');

    $headers = new Header();
    $headers->setSignature($signature);
    $auth = $headers->createAuthorizationHeader();

    $client = new Client();
    $response = $client->post('https://api.twitter.com/oauth/request_token', [
        'headers' => ['Authorization' => $auth]
    ]);

    $res = $response->getBody();
    parse_str($res);
    header('Location: https://api.twitter.com/oauth/authorize?oauth_token=' . $oauth_token);

} else if(isset($_GET['oauth_token']) && isset($_GET['oauth_verifier'])) {
    $access = new AccessCredentials($_GET['oauth_token']);
    $signature = new HmacSha1($consumer, $access);
    $signature->setHttpMethod('post')
              ->setResourceURL('https://api.twitter.com/oauth/access_token');

    $headers = new Header();
    $headers->setSignature($signature);
    $auth = $headers->createAuthorizationHeader();

    $client = new Client();
    $response = $client->post('https://api.twitter.com/oauth/access_token', [
        'headers' => ['Authorization' => $auth],
        'body' => ['oauth_verifier' => $_GET['oauth_verifier']]
    ]);

    $res = $response->getBody();

    // parse_str will create variables called $oauth_token and $oauth_token_secret
    parse_str($res);
    $token = $oauth_token;
    $secret = $oauth_token_secret;
	// You will need to persist these values at this point
}
```

Notes
-----

[](#notes)

OAuth 1.0 can be a little bit difficult to wrap your head around when you first look at it, the aim of this library to encapsulate a lot of that confusion and provide a simple interface for making OAuth 1.0 calls. The OAuth 1.0 RFC was the standard that was kept in mind when building this library, though I feel that I should point out, not every service that calls itself an OAuth 1.0 service follows this standard.

This library works best with APIs that make an attempt to closely adhere to the Signature standards in the OAuth 1.0 specification, which unfortunately means that this may not work with every API that calls itself an OAuth 1.0. That doesn't mean that we've given up on those completely, it just means that as we become aware of them we'll have to analyze whether or not it's in the best interest of this project to accommodate various divergences from the OAuth 1.0 standard. Pull Requests are always welcome.

###  Health Score

30

—

LowBetter than 64% of packages

Maintenance13

Infrequent updates — may be unmaintained

Popularity20

Limited adoption so far

Community15

Small or concentrated contributor base

Maturity63

Established project with proven stability

 Bus Factor1

Top contributor holds 73.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~55 days

Recently: every ~68 days

Total

6

Last Release

3956d ago

Major Versions

0.3.0 → 1.0.02015-02-14

### Community

Maintainers

![](https://www.gravatar.com/avatar/588f92f3d9bcb0e13dadd74d2ce3b8b64a149bac57dac0be356d3f56f9381ade?d=identicon)[mfrost503](/maintainers/mfrost503)

---

Top Contributors

[![mfrost503](https://avatars.githubusercontent.com/u/660067?v=4)](https://github.com/mfrost503 "mfrost503 (88 commits)")[![localheinz](https://avatars.githubusercontent.com/u/605483?v=4)](https://github.com/localheinz "localheinz (31 commits)")[![jasonrhodes](https://avatars.githubusercontent.com/u/159370?v=4)](https://github.com/jasonrhodes "jasonrhodes (1 commits)")

---

Tags

clientoauth1Authorization Header

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/mfrost503-snaggle/health.svg)

```
[![Health](https://phpackages.com/badges/mfrost503-snaggle/health.svg)](https://phpackages.com/packages/mfrost503-snaggle)
```

###  Alternatives

[hwi/oauth-bundle

Support for authenticating users using both OAuth1.0a and OAuth2 in Symfony.

2.4k21.5M69](/packages/hwi-oauth-bundle)[league/oauth1-client

OAuth 1.0 Client Library

99898.8M106](/packages/league-oauth1-client)[league/oauth2-google

Google OAuth 2.0 Client Provider for The PHP League OAuth2-Client

42121.2M118](/packages/league-oauth2-google)[league/oauth2-facebook

Facebook OAuth 2.0 Client Provider for The PHP League OAuth2-Client

32013.0M66](/packages/league-oauth2-facebook)[thenetworg/oauth2-azure

Azure Active Directory OAuth 2.0 Client Provider for The PHP League OAuth2-Client

2509.6M48](/packages/thenetworg-oauth2-azure)[stevenmaguire/oauth2-keycloak

Keycloak OAuth 2.0 Client Provider for The PHP League OAuth2-Client

2275.9M27](/packages/stevenmaguire-oauth2-keycloak)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
