Skip to content

Commit 290ef45

Browse files
committed
Merge pull request #1 from cbdr/flow-strategies
Added flows to the plugin
2 parents 89aa6eb + 32437f6 commit 290ef45

7 files changed

Lines changed: 248 additions & 106 deletions

File tree

README.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,22 @@ This is a PHP Guzzle3 plugin for dealing with CB OAuth2.
99
use CareerBuilder\OAuth2\OAuth2Plugin;
1010
use CareerBuilder\OAuth2\TokenFactory;
1111
use CareerBuilder\OAuth2\NullTokenStorage;
12+
use CareerBuilder\OAuth2\Flows\ClientCredentials;
1213

1314
// create Guzzle client as you normally do
1415

1516
$client = new Client('https://api.careerbuilder.com');
1617

1718
// register the OAuth2Plugin
1819

19-
$config = array(
20-
'base_url' => 'https://www.careerbuilder.com',
21-
'client_id' => '',
22-
'client_secret' => '',
23-
'shared_secret' => ''
24-
)
25-
$client->addSubscriber(new OAuth2Plugin(new TokenFactory($config), new NullTokenStorage()));
20+
$configs = array(
21+
'client_id' => '9c8e37f7',
22+
'client_secret' => 'shhh',
23+
'shared_secret' => 'wBXuP4ohmPTlI5/x088ZlStg/Q1O/9Nmz3IAPYtUlTPUW0sHj0e4cYNrvccIdBghVgSxkWus1F5X6YykBC48cg==',
24+
'base_url' => 'https://wwwtest.careerbuilder.com'
25+
);
26+
27+
$client->addSubscriber(new OAuth2Plugin(new ClientCredentials($configs), new NullTokenStorage()));
2628

2729
// do whatever you normally do with Guzzle
2830

@@ -31,4 +33,4 @@ $request->getQuery()->set('query', 'Atlanta');
3133
$response = $request->send();
3234
```
3335

34-
See more in [usage.php](https://github.com/cbdr/php-oauth/blob/master/usage.php).
36+
See more in [usage.php](usage.php).
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace CareerBuilder\OAuth2\Flows;
4+
5+
use Guzzle\Http\ClientInterface;
6+
use Psr\Log\LoggerInterface;
7+
8+
/**
9+
* Builds the body for the Client Credentials flow using JWT-Bearer
10+
* assertions for client authentication.
11+
*
12+
* @package CareerBuilder\OAuth2\Flows
13+
*/
14+
class ClientCredentials extends Flow
15+
{
16+
/**
17+
* @param array $configs
18+
* @param ClientInterface $client
19+
* @param LoggerInterface $logger
20+
*/
21+
public function __construct(array $configs, ClientInterface $client = null, LoggerInterface $logger = null)
22+
{
23+
parent::__construct($configs, $client, $logger);
24+
}
25+
26+
/**
27+
* Build the body for the token request
28+
*/
29+
public function buildBody()
30+
{
31+
$this->body['grant_type'] = 'client_credentials';
32+
$this->body['client_assertion_type'] = 'urn:params:oauth:client-assertion-type:jwt-bearer';
33+
$this->body['client_assertion'] = $this->getJWT($this->getClientCredentialsClaims());
34+
}
35+
36+
/**
37+
* Get the array of JWT claims for the flow
38+
*/
39+
private function getClientCredentialsClaims()
40+
{
41+
return array(
42+
'iss' => $this->clientId,
43+
'sub' => $this->clientId,
44+
'aud' => 'http://www.careerbuilder.com/share/oauth2/token.aspx',
45+
'exp' => time() + 30
46+
);
47+
}
48+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<?php
2+
3+
namespace CareerBuilder\OAuth2\Flows;
4+
5+
use CareerBuilder\OAuth2\AccessToken;
6+
use Guzzle\Http\ClientInterface;
7+
use Guzzle\Http\Client;
8+
use Guzzle\Plugin\Log\LogPlugin;
9+
use Guzzle\Log\PsrLogAdapter;
10+
use JWT;
11+
use Psr\Log\LoggerInterface;
12+
use Psr\Log\NullLogger;
13+
14+
/**
15+
* Base class for all oAuth 2 flows.
16+
*
17+
* @package CareerBuilder\OAuth2\Flows
18+
*/
19+
abstract class Flow
20+
{
21+
/** @var ClientInterface */
22+
protected $client;
23+
/** @var LoggerInterface */
24+
protected $logger;
25+
/** @var string */
26+
protected $clientId;
27+
/** @var string */
28+
protected $clientSecret;
29+
/** @var string */
30+
protected $sharedSecret;
31+
/** @var array */
32+
protected $headers;
33+
/** @var array */
34+
protected $body;
35+
36+
/**
37+
* @param array $configs
38+
* @param ClientInterface $client
39+
* @param LoggerInterface $logger
40+
*/
41+
protected function __construct(array $configs, ClientInterface $client = null, LoggerInterface $logger = null)
42+
{
43+
$this->setCredentials($configs);
44+
$this->setDefaults();
45+
46+
47+
if (isset($configs['auth_in_header']) && $configs['auth_in_header']) {
48+
$this->headers['Authorization'] = $this->getAuthHeader();
49+
}
50+
51+
$this->logger = $logger ?: new NullLogger();
52+
$this->client = $client ?: new Client();
53+
$this->client->setBaseUrl($configs['base_url']);
54+
$this->client->addSubscriber(new LogPlugin(new PsrLogAdapter($this->logger)));
55+
}
56+
57+
/**
58+
* @param array $configs
59+
*/
60+
private function setCredentials(array $configs)
61+
{
62+
$this->clientId = $configs['client_id'];
63+
$this->clientSecret = $configs['client_secret'];
64+
$this->sharedSecret = $configs['shared_secret'];
65+
}
66+
67+
/**
68+
* Set default headers and body
69+
*/
70+
private function setDefaults()
71+
{
72+
$this->headers = array('Content-Type' => 'application/x-www-form-urlencoded');
73+
$this->body = array(
74+
'client_id' => $this->clientId,
75+
'client_secret' => $this->clientSecret
76+
);
77+
}
78+
79+
/**
80+
* Build the authorization header for client information in header
81+
*/
82+
private function getAuthHeader()
83+
{
84+
$unencodedParams = "{$this->clientId}:{$this->clientSecret}";
85+
$encodedParams = base64_encode($unencodedParams);
86+
87+
return "Basic {$encodedParams}";
88+
}
89+
90+
/**
91+
* @param AccessToken $token
92+
* @return AcccessToken
93+
*/
94+
public function getToken(AccessToken $token = null)
95+
{
96+
if ($token && $token->getRefreshToken()) {
97+
$this->body['grant_type'] = 'refresh_token';
98+
$this->body['refresh_token'] = $token->getRefreshToken();
99+
} else {
100+
$this->buildBody();
101+
}
102+
103+
$request = $this->client->post('/share/oauth2/token.aspx', $this->headers, $this->body);
104+
$response = $request->send();
105+
$data = $response->json();
106+
107+
$refreshToken = isset($data['refresh_token']) ?: '';
108+
109+
return new AccessToken($data['access_token'], $refreshToken, $data['expires_in']);
110+
}
111+
112+
protected abstract function buildBody();
113+
114+
/**
115+
* Encode the claims into a JWT and sign using the HS512 algorithm
116+
*/
117+
protected function getJWT($claims)
118+
{
119+
return JWT::encode($claims, $this->sharedSecret, 'HS512');
120+
}
121+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
namespace CareerBuilder\OAuth2\Flows;
4+
5+
use Guzzle\Http\ClientInterface;
6+
use Psr\Log\LoggerInterface;
7+
8+
/**
9+
* JWT-Bearer Assertion Flow
10+
*
11+
* @package CareerBuilder\OAuth2\Flows
12+
*/
13+
class JWTBearerAssertion extends Flow
14+
{
15+
/** @var string */
16+
private $email;
17+
/** @var string */
18+
private $accountId;
19+
20+
/**
21+
* @param array $configs
22+
* @param ClientInterface $client
23+
* @param LoggerInterface $logger
24+
*/
25+
public function __construct(array $configs, ClientInterface $client = null, LoggerInterface $logger = null)
26+
{
27+
parent::__construct($configs, $client, $logger);
28+
$this->email = $configs['email'];
29+
$this->accountId = $configs['account_id'];
30+
}
31+
32+
/**
33+
* Build token request body for the flow
34+
*/
35+
protected function buildBody()
36+
{
37+
$this->body['grant_type'] = 'urn:ietf:params:oauth:grant-type:jwt-bearer';
38+
$this->body['assertion'] = $this->getJWT($this->getJWTBearerClaims());
39+
}
40+
41+
/**
42+
* Get the clains for the flow
43+
*/
44+
private function getJWTBearerClaims()
45+
{
46+
return array(
47+
'iss' => $this->clientId,
48+
'sub' => "{$this->email}:{$this->accountId}",
49+
'aud' => 'www.careerbuilder.com/share/oauth2'
50+
'exp' => time() + 30
51+
);
52+
}
53+
}

src/CareerBuilder/OAuth2/OAuth2Plugin.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace CareerBuilder\OAuth2;
44

5+
use CareerBuilder\OAuth2\Flows\Flow;
56
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
67
use Guzzle\Common\Event;
78
use Psr\Log\LoggerInterface;
@@ -14,21 +15,21 @@ class OAuth2Plugin implements EventSubscriberInterface
1415
private $token;
1516

1617
/**
17-
* @var TokenFactory
18+
* @var Flow
1819
*/
19-
private $tokenFactory;
20+
private $flow;
2021

2122
/**
2223
* @var TokenStorageInterface
2324
*/
2425
private $tokenStorage;
2526

2627
/**
27-
* @param TokenFactory $tokenFactory
28+
* @param Flow $flow
2829
*/
29-
public function __construct(TokenFactory $tokenFactory, TokenStorageInterface $tokenStorage)
30+
public function __construct(Flow $flow, TokenStorageInterface $tokenStorage)
3031
{
31-
$this->tokenFactory = $tokenFactory;
32+
$this->flow = $flow;
3233
$this->tokenStorage = $tokenStorage;
3334
}
3435

@@ -46,7 +47,7 @@ public function onBeforeSend(Event $event)
4647
$this->token = $this->tokenStorage->fetch();
4748
}
4849
if (!$this->token || $this->token->isExpired()) {
49-
$this->token = $this->tokenFactory->getToken();
50+
$this->token = $this->flow->getToken();
5051
$this->tokenStorage->store($this->token);
5152
}
5253
$request = $event['request'];

src/CareerBuilder/OAuth2/TokenFactory.php

Lines changed: 0 additions & 84 deletions
This file was deleted.

0 commit comments

Comments
 (0)