Skip to content

Commit

Permalink
Clients can be marked as trusted for automatic authorization.
Browse files Browse the repository at this point in the history
Signed-off-by: Jason Lewis <[email protected]>
  • Loading branch information
jasonlewis committed Apr 10, 2014
1 parent 6965f4b commit 2d19428
Show file tree
Hide file tree
Showing 14 changed files with 107 additions and 58 deletions.
1 change: 1 addition & 0 deletions changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### 0.1.4

- Fixed bug where refresh token entity JSON was inserted into `oauth_token_scopes` table instead of the actual token.
- Clients can be marked as trusted for automatic authorization.

### 0.1.3 (April 10th, 2014)

Expand Down
11 changes: 9 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ CREATE TABLE IF NOT EXISTS `oauth_clients` (
`id` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
`secret` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
`name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`trusted` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Expand Down Expand Up @@ -132,6 +133,12 @@ $storage->get('client')->create('id', 'secret', 'name', [
]);
```

A client can be set as "trusted", meaning you can perform a quick check before authorizing and if the client is marked as "trusted" then it will be automatically authorized. The fifth parameter must be set to `true` to mark the client as "trusted".

```php
$storage->get('client')->create('id', 'secret', 'name', [['uri' => 'http://example.com/code', 'default' => true]], true);
```

You can also delete a client. This will also delete an associated endpoints.

```php
Expand Down Expand Up @@ -210,7 +217,7 @@ else
exit;
}

if (isset($_POST['submit']))
if (isset($_POST['submit']) or $payload['client']->isTrusted())
{
$response = $server->handleAuthorizationRequest($payload['client_id'], $_SESSION['user_id'], $payload['redirect_uri'], $payload['scopes']);

Expand Down Expand Up @@ -255,7 +262,7 @@ http://localhost/example-server/authorize
&redirect_uri=http%3A%2F%2Flocalhost%2Fexample-client%2Fauth%2Fcode
```

If the Authorization Server detects that the user is not logged in they will be redirected to the login page and requested to login. Once logged in the user should be redirected back where they are prompted to authorize the client. If the user authorizes the client the Authorization Server will issue an authorization code which is sent back as part of the query string on the redirect URI that was provided.
If the Authorization Server detects that the user is not logged in they will be redirected to the login page and requested to login. Once logged in the user should be redirected back where they are prompted to authorize the client unless the client has been marked as "trusted". If the user authorizes the client the Authorization Server will issue an authorization code which is sent back as part of the query string on the redirect URI that was provided.

> Remember that if a redirection URI is provided it must match a redirection URI that was registered for the client. When no redirection URI is provided the default redirection URI is used.
Expand Down
14 changes: 13 additions & 1 deletion src/Entity/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,27 @@ class Client extends Entity {
* @param string $id
* @param string $secret
* @param string $name
* @param bool $trusted
* @param string $redirectUri
* @return void
*/
public function __construct($id, $secret, $name, $redirectUri = null)
public function __construct($id, $secret, $name, $trusted, $redirectUri = null)
{
$this->id = $id;
$this->secret = $secret;
$this->name = $name;
$this->trusted = $trusted;
$this->redirectUri = $redirectUri;
}

/**
* Check if a client is trusted.
*
* @return bool
*/
public function isTrusted()
{
return $this->trusted == true;
}

}
7 changes: 4 additions & 3 deletions src/Storage/ClientInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ public function get($id, $secret = null, $redirectUri = null);
*
* Example MySQL query to create client:
*
* INSERT INTO oauth_clients (id, secret, name)
* VALUES (:id, :secret, :name)
* INSERT INTO oauth_clients (id, secret, name, trusted)
* VALUES (:id, :secret, :name, :trusted)
*
* Example MySQL query to create associated redirection URIs:
*
Expand All @@ -61,9 +61,10 @@ public function get($id, $secret = null, $redirectUri = null);
* @param string $secret
* @param string $name
* @param array $redirectUris
* @param bool $trusted
* @return \Dingo\OAuth2\Entity\Client
*/
public function create($id, $secret, $name, array $redirectUris);
public function create($id, $secret, $name, array $redirectUris, $trusted = false);

/**
* Delete a client and associated redirection URIs.
Expand Down
19 changes: 12 additions & 7 deletions src/Storage/MySql/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ public function get($id, $secret = null, $redirectUri = null)
}
}

return $this->cache[$client['id']] = new ClientEntity($client['id'], $client['secret'], $client['name'], $client['redirect_uri']);
$client = new ClientEntity($client['id'], $client['secret'], $client['name'], (bool) $client['trusted'], $client['redirect_uri']);

return $this->cache[$client->getId()] = $client;
}

/**
Expand All @@ -106,16 +108,19 @@ public function get($id, $secret = null, $redirectUri = null)
* @param string $secret
* @param string $name
* @param array $redirectUris
* @param bool $trusted
* @return \Dingo\OAuth2\Entity\Client|bool
*/
public function create($id, $secret, $name, array $redirectUris)
public function create($id, $secret, $name, array $redirectUris, $trusted = false)
{
$query = $this->connection->prepare(sprintf('INSERT INTO %1$s (id, secret, name) VALUES (:id, :secret, :name)', $this->tables['clients']));
$query = $this->connection->prepare(sprintf('INSERT INTO %1$s (id, secret, name, trusted)
VALUES (:id, :secret, :name, :trusted)', $this->tables['clients']));

$bindings = [
':id' => $id,
':secret' => $secret,
':name' => $name
':id' => $id,
':secret' => $secret,
':name' => $name,
':trusted' => (int) $trusted
];

$query->execute($bindings);
Expand All @@ -141,7 +146,7 @@ public function create($id, $secret, $name, array $redirectUris)
]);
}

return new ClientEntity($id, $secret, $name, $redirectUri);
return new ClientEntity($id, $secret, $name, (bool) $trusted, $redirectUri);
}

/**
Expand Down
10 changes: 6 additions & 4 deletions src/Storage/Redis/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public function get($id, $secret = null, $redirectUri = null)
});
}

return new ClientEntity($id, $client['secret'], $client['name'], $client['redirect_uri']);
return new ClientEntity($id, $client['secret'], $client['name'], (bool) $client['trusted'], $client['redirect_uri']);
}

/**
Expand All @@ -84,13 +84,15 @@ public function get($id, $secret = null, $redirectUri = null)
* @param string $secret
* @param string $name
* @param array $redirectUris
* @param bool $trusted
* @return \Dingo\OAuth2\Entity\Client|bool
*/
public function create($id, $secret, $name, array $redirectUris)
public function create($id, $secret, $name, array $redirectUris, $trusted = false)
{
$payload = [
'secret' => $secret,
'name' => $name
'name' => $name,
'trusted' => (bool) $trusted
];

$this->setValue($id, $this->tables['clients'], $payload);
Expand All @@ -116,7 +118,7 @@ public function create($id, $secret, $name, array $redirectUris)
]);
}

return new ClientEntity($id, $secret, $name, $redirectUri);
return new ClientEntity($id, $secret, $name, (bool) $trusted, $redirectUri);
}

/**
Expand Down
10 changes: 5 additions & 5 deletions tests/GrantAuthorizationCodeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public function testHandlingAuthorizationRequestFiresAuthorizedCallback()
]));

$storage->shouldReceive('get')->with('client')->andReturn(m::mock([
'get' => new ClientEntity('test', 'test', 'test', 'test')
'get' => new ClientEntity('test', 'test', 'test', false, 'test')
]));

$grant->handleAuthorizationRequest('test', 1, 'test', []);
Expand Down Expand Up @@ -188,7 +188,7 @@ public function testExecutingGrantFlowThrowsExceptionWhenClientsDoNotMatch()
$grant->setRequest($request) and $grant->setStorage($storage = $this->getStorageMock());

$storage->shouldReceive('get')->with('client')->andReturn(m::mock([
'get' => new ClientEntity('foo', 'foo', 'foo')
'get' => new ClientEntity('foo', 'foo', 'foo', false)
]));

$storage->shouldReceive('get')->with('authorization')->andReturn(m::mock([
Expand Down Expand Up @@ -217,7 +217,7 @@ public function testExecutingGrantFlowThrowsExceptionWhenRedirectionUrisDoNotMat
$grant->setRequest($request) and $grant->setStorage($storage = $this->getStorageMock());

$storage->shouldReceive('get')->with('client')->andReturn(m::mock([
'get' => new ClientEntity('test', 'test', 'test')
'get' => new ClientEntity('test', 'test', 'test', false)
]));

$storage->shouldReceive('get')->with('authorization')->andReturn(m::mock([
Expand Down Expand Up @@ -246,7 +246,7 @@ public function testExecutingGrantFlowThrowsExceptionWhenAuthorizationCodeHasExp
$grant->setRequest($request) and $grant->setStorage($storage = $this->getStorageMock());

$storage->shouldReceive('get')->with('client')->andReturn(m::mock([
'get' => new ClientEntity('test', 'test', 'test')
'get' => new ClientEntity('test', 'test', 'test', false)
]));

$storage->shouldReceive('get')->with('authorization')->andReturn(m::mock([
Expand All @@ -271,7 +271,7 @@ public function testExecutingGrantFlowSucceedsAndReturnsTokenEntity()
$grant->setRequest($request) and $grant->setStorage($storage = $this->getStorageMock());

$storage->shouldReceive('get')->with('client')->andReturn(m::mock([
'get' => new ClientEntity('test', 'test', 'test')
'get' => new ClientEntity('test', 'test', 'test', false)
]));

$storage->shouldReceive('get')->with('authorization')->andReturn(m::mock([
Expand Down
2 changes: 1 addition & 1 deletion tests/GrantClientCredentialsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function testExecutingGrantFlowSucceedsAndReturnsValidToken()
$validator->shouldReceive('validate')->once()->andReturn(['test' => true]);

$storage->shouldReceive('get')->with('client')->andReturn(m::mock([
'get' => new ClientEntity('test', 'test', 'test')
'get' => new ClientEntity('test', 'test', 'test', false)
]));

$storage->shouldReceive('get')->with('token')->andReturn(m::mock([
Expand Down
10 changes: 6 additions & 4 deletions tests/GrantGrantTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ public function testValidatingConfidentialClientGetIdAndSecretFromAuthorizationH
$grant->setRequest($request) and $grant->setStorage($storage = $this->getStorageMock());

$storage->shouldReceive('get')->once()->with('client')->andReturn($client = m::mock('Dingo\OAuth2\Storage\ClientInterface'));
$client->shouldReceive('get')->once()->with('test', 'test', null)->andReturn(new ClientEntity('test', 'test', 'test'));
$client->shouldReceive('get')->once()->with('test', 'test', null)->andReturn(new ClientEntity('test', 'test', 'test', false));

$this->assertEquals([
'id' => 'test',
'secret' => 'test',
'name' => 'test',
'redirect_uri' => null
'redirect_uri' => null,
'trusted' => false
], $grant->execute()->getAttributes());
}

Expand All @@ -43,13 +44,14 @@ public function testValidatingConfidentialClientGetIdAndSecretFromUri()
$grant->setRequest($request) and $grant->setStorage($storage = $this->getStorageMock());

$storage->shouldReceive('get')->once()->with('client')->andReturn($client = m::mock('Dingo\OAuth2\Storage\ClientInterface'));
$client->shouldReceive('get')->once()->with('test', 'test', null)->andReturn(new ClientEntity('test', 'test', 'test'));
$client->shouldReceive('get')->once()->with('test', 'test', null)->andReturn(new ClientEntity('test', 'test', 'test', false));

$this->assertEquals([
'id' => 'test',
'secret' => 'test',
'name' => 'test',
'redirect_uri' => null
'redirect_uri' => null,
'trusted' => false
], $grant->execute()->getAttributes());
}

Expand Down
2 changes: 1 addition & 1 deletion tests/GrantPasswordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public function testExecutingGrantFlowSucceedsAndReturnsValidToken()
});

$storage->shouldReceive('get')->with('client')->andReturn(m::mock([
'get' => new ClientEntity('test', 'test', 'test')
'get' => new ClientEntity('test', 'test', 'test', false)
]));

$storage->shouldReceive('get')->with('token')->andReturn(m::mock([
Expand Down
2 changes: 1 addition & 1 deletion tests/GrantRefreshTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public function testExecutingGrantFlowSucceedsAndReturnsValidToken()
$validator->shouldReceive('validate')->once()->andReturn(['test' => true]);

$storage->shouldReceive('get')->with('client')->andReturn(m::mock([
'get' => new ClientEntity('test', 'test', 'test')
'get' => new ClientEntity('test', 'test', 'test', false)
]));

$storage->shouldReceive('get')->with('token')->andReturn(m::mock([
Expand Down
4 changes: 2 additions & 2 deletions tests/ServerAuthorizationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ public function testMakeRedirectUriWithoutRedirectUriInRequestAndNoDefaultRedire
{
$storage = $this->getStorageMock();
$storage->shouldReceive('get')->once()->with('client')->andReturn(m::mock([
'get' => new ClientEntity('test', 'test', 'test')
'get' => new ClientEntity('test', 'test', 'test', false)
]));

$authorization = new Authorization($storage, Request::create('test', 'GET', ['response_type' => 'code']));
Expand All @@ -191,7 +191,7 @@ public function testMakeRedirectUriWithoutRedirectUriInRequestUsesDefaultRedirec
{
$storage = $this->getStorageMock();
$storage->shouldReceive('get')->once()->with('client')->andReturn(m::mock([
'get' => new ClientEntity('test', 'test', 'test', 'foo.com/bar')
'get' => new ClientEntity('test', 'test', 'test', false, 'foo.com/bar')
]));

$authorization = new Authorization($storage, Request::create('test', 'GET', ['response_type' => 'code']));
Expand Down
Loading

0 comments on commit 2d19428

Please sign in to comment.