Skip to content

Commit fad9552

Browse files
committed
Merge pull request #38 from php-http/auto_basic_auth
Add auto BasicAuth credential detection based on URL
2 parents a814fba + 12125f4 commit fad9552

File tree

10 files changed

+169
-29
lines changed

10 files changed

+169
-29
lines changed

spec/Authentication/AuthenticationBehavior.php

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
3+
namespace spec\Http\Message\Authentication;
4+
5+
use PhpSpec\ObjectBehavior;
6+
use Prophecy\Argument;
7+
use Psr\Http\Message\RequestInterface;
8+
use Psr\Http\Message\UriInterface;
9+
10+
class AutoBasicAuthSpec extends ObjectBehavior
11+
{
12+
function it_is_initializable()
13+
{
14+
$this->shouldHaveType('Http\Message\Authentication\AutoBasicAuth');
15+
}
16+
17+
function it_is_an_authentication()
18+
{
19+
$this->shouldImplement('Http\Message\Authentication');
20+
}
21+
22+
function it_authenticates_a_request(
23+
RequestInterface $request,
24+
UriInterface $uri,
25+
UriInterface $uriWithoutUserInfo,
26+
RequestInterface $requestWithoutUserInfo,
27+
RequestInterface $authenticatedRequest
28+
) {
29+
$request->getUri()->willReturn($uri);
30+
$uri->getUserInfo()->willReturn('username:password');
31+
$uri->withUserInfo('', null)->willReturn($uriWithoutUserInfo);
32+
$request->withUri($uriWithoutUserInfo)->willReturn($requestWithoutUserInfo);
33+
$requestWithoutUserInfo
34+
->withHeader('Authorization', 'Basic '.base64_encode('username:password'))
35+
->willReturn($authenticatedRequest)
36+
;
37+
38+
$this->authenticate($request)->shouldReturn($authenticatedRequest);
39+
}
40+
41+
function it_authenticates_a_request_without_password(
42+
RequestInterface $request,
43+
UriInterface $uri,
44+
UriInterface $uriWithoutUserInfo,
45+
RequestInterface $requestWithoutUserInfo,
46+
RequestInterface $authenticatedRequest
47+
) {
48+
$request->getUri()->willReturn($uri);
49+
$uri->getUserInfo()->willReturn('username');
50+
$uri->withUserInfo('', null)->willReturn($uriWithoutUserInfo);
51+
$request->withUri($uriWithoutUserInfo)->willReturn($requestWithoutUserInfo);
52+
$requestWithoutUserInfo
53+
->withHeader('Authorization', 'Basic '.base64_encode('username'))
54+
->willReturn($authenticatedRequest)
55+
;
56+
57+
$this->authenticate($request)->shouldReturn($authenticatedRequest);
58+
}
59+
60+
function it_does_not_authenticate_a_request(RequestInterface $request, UriInterface $uri)
61+
{
62+
$request->getUri()->willReturn($uri);
63+
$uri->getUserInfo()->willReturn('');
64+
65+
$this->authenticate($request)->shouldReturn($request);
66+
}
67+
68+
function it_authenticates_a_request_without_user_info_removal(
69+
RequestInterface $request,
70+
UriInterface $uri,
71+
RequestInterface $authenticatedRequest
72+
) {
73+
$this->beConstructedWith(false);
74+
75+
$request->getUri()->willReturn($uri);
76+
$uri->getUserInfo()->willReturn('username:password');
77+
$request
78+
->withHeader('Authorization', 'Basic '.base64_encode('username:password'))
79+
->willReturn($authenticatedRequest)
80+
;
81+
82+
$this->authenticate($request)->shouldReturn($authenticatedRequest);
83+
}
84+
}

spec/Authentication/BasicAuthSpec.php

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

88
class BasicAuthSpec extends ObjectBehavior
99
{
10-
use AuthenticationBehavior;
11-
1210
function let()
1311
{
1412
$this->beConstructedWith('john.doe', 'secret');
@@ -19,6 +17,11 @@ function it_is_initializable()
1917
$this->shouldHaveType('Http\Message\Authentication\BasicAuth');
2018
}
2119

20+
function it_is_an_authentication()
21+
{
22+
$this->shouldImplement('Http\Message\Authentication');
23+
}
24+
2225
function it_authenticates_a_request(RequestInterface $request, RequestInterface $newRequest)
2326
{
2427
$request->withHeader('Authorization', 'Basic '.base64_encode('john.doe:secret'))->willReturn($newRequest);

spec/Authentication/BearerSpec.php

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

88
class BearerSpec extends ObjectBehavior
99
{
10-
use AuthenticationBehavior;
11-
1210
function let()
1311
{
1412
$this->beConstructedWith('token');
@@ -19,6 +17,11 @@ function it_is_initializable()
1917
$this->shouldHaveType('Http\Message\Authentication\Bearer');
2018
}
2119

20+
function it_is_an_authentication()
21+
{
22+
$this->shouldImplement('Http\Message\Authentication');
23+
}
24+
2225
function it_authenticates_a_request(RequestInterface $request, RequestInterface $newRequest)
2326
{
2427
$request->withHeader('Authorization', 'Bearer token')->willReturn($newRequest);

spec/Authentication/ChainSpec.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88

99
class ChainSpec extends ObjectBehavior
1010
{
11-
use AuthenticationBehavior;
12-
1311
function it_is_initializable()
1412
{
1513
$this->shouldHaveType('Http\Message\Authentication\Chain');
1614
}
1715

16+
function it_is_an_authentication()
17+
{
18+
$this->shouldImplement('Http\Message\Authentication');
19+
}
20+
1821
function it_throws_an_exception_when_non_authentication_is_passed()
1922
{
2023
$this->beConstructedWith(['authentication']);

spec/Authentication/MatchingSpec.php

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

99
class MatchingSpec extends ObjectBehavior
1010
{
11-
use AuthenticationBehavior;
12-
13-
private $matcher;
14-
1511
function let(Authentication $authentication)
1612
{
17-
$this->matcher = function($request) { return true; };
13+
$matcher = function($request) { return true; };
1814

19-
$this->beConstructedWith($authentication, $this->matcher);
15+
$this->beConstructedWith($authentication, $matcher);
2016
}
2117

2218
function it_is_initializable()
2319
{
2420
$this->shouldHaveType('Http\Message\Authentication\Matching');
2521
}
2622

23+
function it_is_an_authentication()
24+
{
25+
$this->shouldImplement('Http\Message\Authentication');
26+
}
27+
2728
function it_authenticates_a_request(Authentication $authentication, RequestInterface $request, RequestInterface $newRequest)
2829
{
2930
$authentication->authenticate($request)->willReturn($newRequest);

spec/Authentication/QueryParamSpec.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
class QueryParamSpec extends ObjectBehavior
1010
{
11-
use AuthenticationBehavior;
12-
1311
function let()
1412
{
1513
$this->beConstructedWith([
@@ -23,6 +21,11 @@ function it_is_initializable()
2321
$this->shouldHaveType('Http\Message\Authentication\QueryParam');
2422
}
2523

24+
function it_is_an_authentication()
25+
{
26+
$this->shouldImplement('Http\Message\Authentication');
27+
}
28+
2629
function it_authenticates_a_request(
2730
RequestInterface $request,
2831
UriInterface $uri,

spec/Authentication/RequestConditionalSpec.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99

1010
class RequestConditionalSpec extends ObjectBehavior
1111
{
12-
use AuthenticationBehavior;
13-
1412
function let(RequestMatcher $requestMatcher, Authentication $authentication)
1513
{
1614
$this->beConstructedWith($requestMatcher, $authentication);
@@ -21,6 +19,11 @@ function it_is_initializable()
2119
$this->shouldHaveType('Http\Message\Authentication\RequestConditional');
2220
}
2321

22+
function it_is_an_authentication()
23+
{
24+
$this->shouldImplement('Http\Message\Authentication');
25+
}
26+
2427
function it_authenticates_a_request(
2528
Authentication $authentication,
2629
RequestMatcher $requestMatcher,

spec/Authentication/WsseSpec.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
class WsseSpec extends ObjectBehavior
1010
{
11-
use AuthenticationBehavior;
12-
1311
function let()
1412
{
1513
$this->beConstructedWith('john.doe', 'secret');
@@ -20,6 +18,11 @@ function it_is_initializable()
2018
$this->shouldHaveType('Http\Message\Authentication\Wsse');
2119
}
2220

21+
function it_is_an_authentication()
22+
{
23+
$this->shouldImplement('Http\Message\Authentication');
24+
}
25+
2326
function it_authenticates_a_request(
2427
RequestInterface $request,
2528
RequestInterface $newRequest,

src/Authentication/AutoBasicAuth.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace Http\Message\Authentication;
4+
5+
use Http\Message\Authentication;
6+
use Psr\Http\Message\RequestInterface;
7+
8+
/**
9+
* Authenticate a PSR-7 Request using Basic Auth based on credentials in the URI.
10+
*
11+
* @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
12+
*/
13+
final class AutoBasicAuth implements Authentication
14+
{
15+
/**
16+
* Whether user info should be removed from the URI.
17+
*
18+
* @var bool
19+
*/
20+
private $shouldRemoveUserInfo;
21+
22+
/**
23+
* @param bool|true $shouldRremoveUserInfo
24+
*/
25+
public function __construct($shouldRremoveUserInfo = true)
26+
{
27+
$this->shouldRemoveUserInfo = (bool) $shouldRremoveUserInfo;
28+
}
29+
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
public function authenticate(RequestInterface $request)
34+
{
35+
$uri = $request->getUri();
36+
$userInfo = $uri->getUserInfo();
37+
38+
if (!empty($userInfo)) {
39+
if ($this->shouldRemoveUserInfo) {
40+
$request = $request->withUri($uri->withUserInfo(''));
41+
}
42+
43+
$request = $request->withHeader('Authorization', sprintf('Basic %s', base64_encode($userInfo)));
44+
}
45+
46+
return $request;
47+
}
48+
}

0 commit comments

Comments
 (0)