Skip to content

Instantly share code, notes, and snippets.

@Spomky
Last active January 31, 2018 10:12
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Spomky/08e9b5b596ab3b9c9c3a to your computer and use it in GitHub Desktop.
Save Spomky/08e9b5b596ab3b9c9c3a to your computer and use it in GitHub Desktop.
Secured Resource Owner Password Credentials Grant Type (proof of concept)
<?php
// src/Acme/ApiBundle/OAuth/SROCGrantType.php
namespace Acme\ApiBundle\OAuth;
use FOS\OAuthServerBundle\Storage\GrantExtensionInterface;
use OAuth2\Model\IOAuth2Client;
/**
*/
class ClientInterface extends IOAuth2Client
{
/**
* @return string
*/
public function getSharedSecret();
/**
* @return string
*/
public function getEncryptionAlgorithm();
}
services:
acme.api.oauth.sropc_grant_yype:
class: Acme\ApiBundle\OAuth\SROPCGrantType
arguments:
- @security.password_encoder
- @user_manager
tags:
- { name: fos_oauth_server.grant_extension, uri: 'http://acme.com/grants/sropc' }
<?php
// src/Acme/ApiBundle/OAuth/SROCGrantType.php
namespace Acme\ApiBundle\OAuth;
use FOS\OAuthServerBundle\Storage\GrantExtensionInterface;
use OAuth2\Model\IOAuth2Client;
use Acme\ApiBundle\OAuth\ClientInterface;
/**
*/
class SROPCGrantType implements GrantExtensionInterface
{
private $encoder;
private $user_manager;
public function __construct($encoder, $user_manager)
{
$this->encoder = $encoder;
$this->user_manager = $user_manager;
}
/*
* {@inheritdoc}
*/
public function checkGrantExtension(IOAuth2Client $client, array $inputData, array $authHeaders)
{
// Check that the client implements ClientInterface
if (!$client instanceof ClientInterface) {
return false;
}
// Check that the input data is correct
if (!isset($inputData['username']) || !isset($inputData['encrypted_secret'])) {
return false;
}
$iv = isset($inputData['iv'])$inputData['iv']?:'';
$user = $this->user_manager->findOneByUsername($inputData['username']);
if (null === $user) {
return false;
}
$plaintext_password = openssl_decrypt($inputData['encrypted_secret'], $client->getEncryptionAlgorithm(), $client->getSharedSecret(), 0, $iv);
if (true === $this->encoder->isPasswordValid($user->getPassword(), $password, $user->getSalt())) {
return array(
'data' => $user,
);
}
return false;
}
}
When the client is created, a random shared secret is issued (e.g. '0123456789').
Let say that the encryption algorithm is 'aes-128-cbc' for all clients.
Get the username ($username) and password ($password) as usually.
Create an IV (optional): $iv = openssl_random_pseudo_bytes(16);
Encrypt the password: $encrypted_password = openssl_encrypt($username, 'aes-128-cbc', '0123456789', 0, $iv);
Now create a token request using our new grant type:
$ curl -XGET "http://acme.com/oauth/v2/token?grant_type=http%3A%2F%2Facme.com%2Fgrants%2Fsropc&client_id=1_1&client_secret=secret&username=$username&encrypted_secret=$encrypted_password&iv=$iv"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment