Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Switch access token signing from RSA SHA-256 to ECDSA SHA-512 #19

Open
wants to merge 1 commit into
base: ss-3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,20 @@ Install the add-on with Composer:
composer require iansimpson/ss-oauth2-server
```

Next, generate a private/public key pair:
Next, generate an ECSDA private/public key pair:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ECSDA -> ECDSA


```
vendor/mdanter/ecc/bin/phpecc genkey --curve nist-p521 --out pem
```

Copy the output into `private.key` and `public.key` files respectively. Then fix permissions:

```
openssl genrsa -out private.key 1024
openssl rsa -in private.key -pubout -out public.key
chmod 600 private.key
chmod 600 public.key
```

And put these on your web server, somewhere outside the web root. Add the following lines in your `mysite/_config/config.yml`, updating the privateKey and publicKey to point to the key file (relative to the Silverstripe root), and adding an encryption key (which you might generate with `php -r 'echo base64_encode(random_bytes(32)), PHP_EOL;'`).
And put these on your web server, somewhere outside the web root. Add the following lines in your `mysite/_config/config.yml`, updating the privateKey and publicKey to point to the key file (relative to the Silverstripe root), and adding an encryption key (which you might generate with `php -r 'echo base64_encode(random_bytes(64)), PHP_EOL;'`).

```
IanSimpson\OauthServerController:
Expand Down
23 changes: 23 additions & 0 deletions code/Entities/AccessTokenEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

namespace IanSimpson\Entities;

use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Ecdsa\Sha512;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
Expand Down Expand Up @@ -43,6 +47,25 @@ class AccessTokenEntity extends \DataObject implements AccessTokenEntityInterfac
'ScopeEntities' => 'IanSimpson\Entities\ScopeEntity',
);

/**
* @param CryptKey $privateKey
*
* @return string
*/
public function convertToJWT(CryptKey $privateKey)
{
return (new Builder())
->setAudience($this->getClient()->getIdentifier())
->setId($this->getIdentifier(), true)
->setIssuedAt(time())
->setNotBefore(time())
->setExpiration($this->getExpiryDateTime()->getTimestamp())
->setSubject($this->getUserIdentifier())
->set('scopes', $this->getScopes())
->sign(new Sha512(), new Key($privateKey->getKeyPath(), $privateKey->getPassPhrase()))
->getToken();
}

public function getIdentifier()
{
return $this->Code;
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"silverstripe/cms": "~3.1",
"silverstripe/framework": "~3.1",
"league/oauth2-server": "^6.1",
"mdanter/ecc": "~0.3.0",
"guzzlehttp/psr7": "*"
}
}
6 changes: 3 additions & 3 deletions tests/OauthServerControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Rsa\Sha256;
use Lcobucci\JWT\Signer\Ecdsa\Sha512;
use League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\CryptTrait;
Expand Down Expand Up @@ -153,7 +153,7 @@ public function testAuthenticateRequest()
->setExpiration(strtotime($at->Expiry))
->setSubject($m->ID)
->set('scopes', [])
->sign(new Sha256(), new Key(file_get_contents(__DIR__ . '/test.key')))
->sign(new Sha512(), new Key(file_get_contents(__DIR__ . '/test.key')))
->getToken();

$_SERVER['AUTHORIZATION'] = sprintf('Bearer %s', $jwt);
Expand All @@ -170,7 +170,7 @@ private function tokenIsOk($jwt)
{
$pk = new CryptKey(__DIR__ . '/test.crt');
$token = (new Parser())->parse($jwt);
return $token->verify(new Sha256(), $pk->getKeyPath());
return $token->verify(new Sha512(), $pk->getKeyPath());
}

private function tokenGetClaims($jwt)
Expand Down
8 changes: 4 additions & 4 deletions tests/test.crt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCf77SildvvZuEtRyAMWrFpZDTs
+xv0ssQ7xeDxds1Uo6HLQGfwNnNAkqAkjua1uLZSNU6qp1w2zwC368syuWekW474
u4V5zm+1n2A9ct8yyNydLgQVq0g7j3b+entmqTpZDqUHgNUi1XRyqqUa1AV++1et
Z5bOJjjvyyPmrT+BqwIDAQAB
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAxkZsteUznOV3Ipwmg4L3lHYYC8Yw
HcKiwjijdutRPHYYsryT+FkzDHPzn0j9Yuxvi6MJfZWCvl/xR3mMi8jrozgBk6lP
ReSN4NNyCUFUsolCVlGb34pHQSf87jGTQ2c5CLJ5bLScJHRSOoOO/CeQ60jOm4Oz
yDWP1WztYA+VVXjlX/M=
-----END PUBLIC KEY-----
22 changes: 7 additions & 15 deletions tests/test.key
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCf77SildvvZuEtRyAMWrFpZDTs+xv0ssQ7xeDxds1Uo6HLQGfw
NnNAkqAkjua1uLZSNU6qp1w2zwC368syuWekW474u4V5zm+1n2A9ct8yyNydLgQV
q0g7j3b+entmqTpZDqUHgNUi1XRyqqUa1AV++1etZ5bOJjjvyyPmrT+BqwIDAQAB
AoGAOFxppI349nGj0qfo5FGliYVVnVmUbXP98S53acA69aPAZXbp6d3WWaASLS/q
n4lbPrcoZL0bovjpwOaoMdTib5ty/cO2pfo10hby7p0vLZrsPMLLuWvYP2RlqcIZ
vkmzDSZPBGZkd9ieFevdH3/vihD5VuV93leUvP/1ob8ak2kCQQDLA43dOl8crk9R
fvc6gcnj73P2D2+gR7r0kpG90P9xz6w4cA3uitsQnLgvCEMqLwmWrg6BIimJ+feS
eKMfU26VAkEAya3pF69j+f8SQHp4EQnx1Tig+g24PNebxDFtl9Y9GdmlLzFR94zG
Ru7SqLcynMHlgj42PaZtD2dM2yQLpXZfPwJAbNgF+mNuVRE7o4UABhVJ6fQa5wTV
o0hx+uiOTQe9vQZL3qJtRcSauOhdc5HpeLdpW6kMS73GKZykWJpnUsdHlQJAIZrA
xBmNZxKBUA0YBH7LtOOCryeqEzk50y8JO8uO0sfZJkvphH4Ia7lPkJ016bjFLTaA
gzU/5tknjTwsVJ2ssQJAZssVuJ21QK9e2kHgZzNP/oJTcb/t2PsSUO5c5BHwe4UV
yghSCWzz3MWo3rWYEMiBRVmkezPHt0izurNhh8Sg9A==
-----END RSA PRIVATE KEY-----
-----BEGIN EC PRIVATE KEY-----
MIHcAgEBBEK7lWrkCwd1ZA+pUCOFL80CerhY0iY+vlKenUR75aBH4E6cy6LFV1Zq
SE7zC0fo1yLm73XhIFF+IdpU5awYmXmUOzOgBwYFK4EEACOhgYkDgYYABADGRmy1
5TOc5XcinCaDgveUdhgLxjAdwqLCOKN261E8dhiyvJP4WTMMc/OfSP1i7G+Lowl9
lYK+X/FHeYyLyOujOAGTqU9F5I3g03IJQVSyiUJWUZvfikdBJ/zuMZNDZzkIsnls
tJwkdFI6g478J5DrSM6bg7PINY/VbO1gD5VVeOVf8w==
-----END EC PRIVATE KEY-----