Skip to content

Commit 8702a8a

Browse files
author
Sean Harvey
committed
Switch access token signing from RSA SHA-256 to ECDSA SHA-512
1 parent 09d5344 commit 8702a8a

File tree

6 files changed

+46
-26
lines changed

6 files changed

+46
-26
lines changed

README.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,20 @@ Install the add-on with Composer:
2323
composer require iansimpson/ss-oauth2-server
2424
```
2525

26-
Next, generate a private/public key pair:
26+
Next, generate an ECSDA private/public key pair:
27+
28+
```
29+
vendor/mdanter/ecc/bin/phpecc genkey --curve nist-p521 --out pem
30+
```
31+
32+
Copy the output into `private.key` and `public.key` files respectively. Then fix permissions:
2733

2834
```
29-
openssl genrsa -out private.key 1024
30-
openssl rsa -in private.key -pubout -out public.key
3135
chmod 600 private.key
3236
chmod 600 public.key
3337
```
3438

35-
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;'`).
39+
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;'`).
3640

3741
```
3842
IanSimpson\OauthServerController:

code/Entities/AccessTokenEntity.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
namespace IanSimpson\Entities;
88

9+
use Lcobucci\JWT\Builder;
10+
use Lcobucci\JWT\Signer\Key;
11+
use Lcobucci\JWT\Signer\Ecdsa\Sha512;
12+
use League\OAuth2\Server\CryptKey;
913
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
1014
use League\OAuth2\Server\Entities\ClientEntityInterface;
1115
use League\OAuth2\Server\Entities\ScopeEntityInterface;
@@ -43,6 +47,25 @@ class AccessTokenEntity extends \DataObject implements AccessTokenEntityInterfac
4347
'ScopeEntities' => 'IanSimpson\Entities\ScopeEntity',
4448
);
4549

50+
/**
51+
* @param CryptKey $privateKey
52+
*
53+
* @return string
54+
*/
55+
public function convertToJWT(CryptKey $privateKey)
56+
{
57+
return (new Builder())
58+
->setAudience($this->getClient()->getIdentifier())
59+
->setId($this->getIdentifier(), true)
60+
->setIssuedAt(time())
61+
->setNotBefore(time())
62+
->setExpiration($this->getExpiryDateTime()->getTimestamp())
63+
->setSubject($this->getUserIdentifier())
64+
->set('scopes', $this->getScopes())
65+
->sign(new Sha512(), new Key($privateKey->getKeyPath(), $privateKey->getPassPhrase()))
66+
->getToken();
67+
}
68+
4669
public function getIdentifier()
4770
{
4871
return $this->Code;

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"silverstripe/cms": "~3.1",
1616
"silverstripe/framework": "~3.1",
1717
"league/oauth2-server": "^6.1",
18+
"mdanter/ecc": "~0.3.0",
1819
"guzzlehttp/psr7": "*"
1920
}
2021
}

tests/OauthServerControllerTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
use Lcobucci\JWT\Builder;
1515
use Lcobucci\JWT\Parser;
1616
use Lcobucci\JWT\Signer\Key;
17-
use Lcobucci\JWT\Signer\Rsa\Sha256;
17+
use Lcobucci\JWT\Signer\Ecdsa\Sha512;
1818
use League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator;
1919
use League\OAuth2\Server\CryptKey;
2020
use League\OAuth2\Server\CryptTrait;
@@ -153,7 +153,7 @@ public function testAuthenticateRequest()
153153
->setExpiration(strtotime($at->Expiry))
154154
->setSubject($m->ID)
155155
->set('scopes', [])
156-
->sign(new Sha256(), new Key(file_get_contents(__DIR__ . '/test.key')))
156+
->sign(new Sha512(), new Key(file_get_contents(__DIR__ . '/test.key')))
157157
->getToken();
158158

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

176176
private function tokenGetClaims($jwt)

tests/test.crt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
-----BEGIN PUBLIC KEY-----
2-
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCf77SildvvZuEtRyAMWrFpZDTs
3-
+xv0ssQ7xeDxds1Uo6HLQGfwNnNAkqAkjua1uLZSNU6qp1w2zwC368syuWekW474
4-
u4V5zm+1n2A9ct8yyNydLgQVq0g7j3b+entmqTpZDqUHgNUi1XRyqqUa1AV++1et
5-
Z5bOJjjvyyPmrT+BqwIDAQAB
2+
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAxkZsteUznOV3Ipwmg4L3lHYYC8Yw
3+
HcKiwjijdutRPHYYsryT+FkzDHPzn0j9Yuxvi6MJfZWCvl/xR3mMi8jrozgBk6lP
4+
ReSN4NNyCUFUsolCVlGb34pHQSf87jGTQ2c5CLJ5bLScJHRSOoOO/CeQ60jOm4Oz
5+
yDWP1WztYA+VVXjlX/M=
66
-----END PUBLIC KEY-----

tests/test.key

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,7 @@
1-
-----BEGIN RSA PRIVATE KEY-----
2-
MIICWwIBAAKBgQCf77SildvvZuEtRyAMWrFpZDTs+xv0ssQ7xeDxds1Uo6HLQGfw
3-
NnNAkqAkjua1uLZSNU6qp1w2zwC368syuWekW474u4V5zm+1n2A9ct8yyNydLgQV
4-
q0g7j3b+entmqTpZDqUHgNUi1XRyqqUa1AV++1etZ5bOJjjvyyPmrT+BqwIDAQAB
5-
AoGAOFxppI349nGj0qfo5FGliYVVnVmUbXP98S53acA69aPAZXbp6d3WWaASLS/q
6-
n4lbPrcoZL0bovjpwOaoMdTib5ty/cO2pfo10hby7p0vLZrsPMLLuWvYP2RlqcIZ
7-
vkmzDSZPBGZkd9ieFevdH3/vihD5VuV93leUvP/1ob8ak2kCQQDLA43dOl8crk9R
8-
fvc6gcnj73P2D2+gR7r0kpG90P9xz6w4cA3uitsQnLgvCEMqLwmWrg6BIimJ+feS
9-
eKMfU26VAkEAya3pF69j+f8SQHp4EQnx1Tig+g24PNebxDFtl9Y9GdmlLzFR94zG
10-
Ru7SqLcynMHlgj42PaZtD2dM2yQLpXZfPwJAbNgF+mNuVRE7o4UABhVJ6fQa5wTV
11-
o0hx+uiOTQe9vQZL3qJtRcSauOhdc5HpeLdpW6kMS73GKZykWJpnUsdHlQJAIZrA
12-
xBmNZxKBUA0YBH7LtOOCryeqEzk50y8JO8uO0sfZJkvphH4Ia7lPkJ016bjFLTaA
13-
gzU/5tknjTwsVJ2ssQJAZssVuJ21QK9e2kHgZzNP/oJTcb/t2PsSUO5c5BHwe4UV
14-
yghSCWzz3MWo3rWYEMiBRVmkezPHt0izurNhh8Sg9A==
15-
-----END RSA PRIVATE KEY-----
1+
-----BEGIN EC PRIVATE KEY-----
2+
MIHcAgEBBEK7lWrkCwd1ZA+pUCOFL80CerhY0iY+vlKenUR75aBH4E6cy6LFV1Zq
3+
SE7zC0fo1yLm73XhIFF+IdpU5awYmXmUOzOgBwYFK4EEACOhgYkDgYYABADGRmy1
4+
5TOc5XcinCaDgveUdhgLxjAdwqLCOKN261E8dhiyvJP4WTMMc/OfSP1i7G+Lowl9
5+
lYK+X/FHeYyLyOujOAGTqU9F5I3g03IJQVSyiUJWUZvfikdBJ/zuMZNDZzkIsnls
6+
tJwkdFI6g478J5DrSM6bg7PINY/VbO1gD5VVeOVf8w==
7+
-----END EC PRIVATE KEY-----

0 commit comments

Comments
 (0)