Skip to content

Commit 512a44e

Browse files
authored
Add support for using multiple signature algorithms (#325)
Related to #324
1 parent 5cc585a commit 512a44e

File tree

84 files changed

+2531
-2202
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+2531
-2202
lines changed

config/module_oidc.php.dist

Lines changed: 466 additions & 265 deletions
Large diffs are not rendered by default.

conformance-tests/conformance-rp-initiated-logout-ci.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@
556556
"xpath",
557557
"//*",
558558
10,
559-
"The JWT string is missing the Signature part",
559+
"The algorithm \"none\" is not supported.",
560560
"update-image-placeholder"
561561
]
562562
]
@@ -620,7 +620,7 @@
620620
"xpath",
621621
"//*",
622622
10,
623-
"The token was not issued by the given issuers",
623+
"Issuer claim",
624624
"update-image-placeholder"
625625
]
626626
]

docker/conformance.sql

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,22 @@ INSERT INTO oidc_migration_versions VALUES('20210916153400');
1414
INSERT INTO oidc_migration_versions VALUES('20210916173400');
1515
INSERT INTO oidc_migration_versions VALUES('20240603141400');
1616
INSERT INTO oidc_migration_versions VALUES('20240605145700');
17+
INSERT INTO oidc_migration_versions VALUES('20240820132400');
18+
INSERT INTO oidc_migration_versions VALUES('20240828153300');
19+
INSERT INTO oidc_migration_versions VALUES('20240830153300');
20+
INSERT INTO oidc_migration_versions VALUES('20240902120000');
21+
INSERT INTO oidc_migration_versions VALUES('20240905120000');
22+
INSERT INTO oidc_migration_versions VALUES('20240906120000');
23+
INSERT INTO oidc_migration_versions VALUES('20250818163000');
24+
INSERT INTO oidc_migration_versions VALUES('20250908163000');
25+
INSERT INTO oidc_migration_versions VALUES('20250912163000');
26+
INSERT INTO oidc_migration_versions VALUES('20250913163000');
27+
INSERT INTO oidc_migration_versions VALUES('20250915163000');
28+
INSERT INTO oidc_migration_versions VALUES('20250916163000');
29+
INSERT INTO oidc_migration_versions VALUES('20250917163000');
30+
INSERT INTO oidc_migration_versions VALUES('20251021000001');
31+
INSERT INTO oidc_migration_versions VALUES('20251021000002');
32+
INSERT INTO oidc_migration_versions VALUES('20260109000001');
1733
CREATE TABLE oidc_user (
1834
id VARCHAR(191) PRIMARY KEY NOT NULL,
1935
claims TEXT,
@@ -44,15 +60,16 @@ CREATE TABLE oidc_client (
4460
created_at TIMESTAMP NULL DEFAULT NULL,
4561
expires_at TIMESTAMP NULL DEFAULT NULL,
4662
is_federated BOOLEAN NOT NULL DEFAULT false,
47-
is_generic BOOLEAN NOT NULL DEFAULT false
63+
is_generic BOOLEAN NOT NULL DEFAULT false,
64+
extra_metadata TEXT NULL
4865
);
4966
-- Used 'httpd' host for back-channel logout url (https://httpd:8443/test/a/simplesamlphp-module-oidc/backchannel_logout)
5067
-- since this is the hostname of conformance server while running in container environment
51-
INSERT INTO oidc_client VALUES('_55a99a1d298da921cb27d700d4604352e51171ebc4','_8967dd97d07cc59db7055e84ac00e79005157c1132','Conformance Client 1',replace('Client 1 for Conformance Testing https://openid.net/certification/connect_op_testing/\n','\n',char(10)),'example-userpass','["https:\/\/localhost.emobix.co.uk:8443\/test\/a\/simplesamlphp-module-oidc\/callback","https:\/\/www.certification.openid.net\/test\/a\/simplesamlphp-module-oidc\/callback"]','["openid","profile","email","address","phone","offline_access"]',1,1,NULL,'["https:\/\/localhost.emobix.co.uk:8443\/test\/a\/simplesamlphp-module-oidc\/post_logout_redirect"]','https://httpd:8443/test/a/simplesamlphp-module-oidc/backchannel_logout',NULL,NULL, NULL, NULL, NULL, NULL, 'manual', NULL, NULL, NULL, false, false);
52-
INSERT INTO oidc_client VALUES('_34efb61060172a11d62101bc804db789f8f9100b0e','_91a4607a1c10ba801268929b961b3f6c067ff82d21','Conformance Client 2','','example-userpass','["https:\/\/localhost.emobix.co.uk:8443\/test\/a\/simplesamlphp-module-oidc\/callback","https:\/\/www.certification.openid.net\/test\/a\/simplesamlphp-module-oidc\/callback"]','["openid","profile","email","offline_access"]',1,1,NULL,NULL,NULL,NULL,NULL, NULL, NULL, NULL, NULL, 'manual', NULL, NULL, NULL, false, false);
53-
INSERT INTO oidc_client VALUES('_0afb7d18e54b2de8205a93e38ca119e62ee321d031','_944e73bbeec7850d32b68f1b5c780562c955967e4e','Conformance Client 3','Client for client_secret_post','example-userpass','["https:\/\/localhost.emobix.co.uk:8443\/test\/a\/simplesamlphp-module-oidc\/callback","https:\/\/www.certification.openid.net\/test\/a\/simplesamlphp-module-oidc\/callback"]','["openid","profile","email"]',1,1,NULL,NULL,NULL,NULL,NULL, NULL, NULL, NULL, NULL, 'manual', NULL, NULL, NULL, false, false);
54-
INSERT INTO oidc_client VALUES('_8957eda35234902ba8343c0cdacac040310f17dfca','_322d16999f9da8b5abc9e9c0c08e853f60f4dc4804','RP-Initiated Logout Client','Client for testing RP-Initiated Logout','example-userpass','["https:\/\/localhost.emobix.co.uk:8443\/test\/a\/simplesamlphp-module-oidc\/callback","https:\/\/www.certification.openid.net\/test\/a\/simplesamlphp-module-oidc\/callback"]','["openid","profile","email","address","phone"]',1,1,NULL,'["https:\/\/localhost.emobix.co.uk:8443\/test\/a\/simplesamlphp-module-oidc\/post_logout_redirect"]',NULL,NULL,NULL, NULL, NULL, NULL, NULL, 'manual', NULL, NULL, NULL, false, false);
55-
INSERT INTO oidc_client VALUES('_9fe2f7589ece1b71f5ef75a91847d71bc5125ec2a6','_3c0beb20194179c01d7796c6836f62801e9ed4b368','Back-Channel Logout Client','Client for testing Back-Channel Logout','example-userpass','["https:\/\/localhost.emobix.co.uk:8443\/test\/a\/simplesamlphp-module-oidc\/callback","https:\/\/www.certification.openid.net\/test\/a\/simplesamlphp-module-oidc\/callback"]','["openid","profile","email","address","phone"]',1,1,NULL,'["https:\/\/localhost.emobix.co.uk:8443\/test\/a\/simplesamlphp-module-oidc\/post_logout_redirect"]','https://httpd:8443/test/a/simplesamlphp-module-oidc/backchannel_logout',NULL,NULL, NULL, NULL, NULL, NULL, 'manual', NULL, NULL, NULL, false, false);
68+
INSERT INTO oidc_client VALUES('_55a99a1d298da921cb27d700d4604352e51171ebc4','_8967dd97d07cc59db7055e84ac00e79005157c1132','Conformance Client 1',replace('Client 1 for Conformance Testing https://openid.net/certification/connect_op_testing/\n','\n',char(10)),'example-userpass','["https:\/\/localhost.emobix.co.uk:8443\/test\/a\/simplesamlphp-module-oidc\/callback","https:\/\/www.certification.openid.net\/test\/a\/simplesamlphp-module-oidc\/callback"]','["openid","profile","email","address","phone","offline_access"]',1,1,NULL,'["https:\/\/localhost.emobix.co.uk:8443\/test\/a\/simplesamlphp-module-oidc\/post_logout_redirect"]','https://httpd:8443/test/a/simplesamlphp-module-oidc/backchannel_logout',NULL,NULL, NULL, NULL, NULL, NULL, 'manual', NULL, NULL, NULL, false, false, NULL);
69+
INSERT INTO oidc_client VALUES('_34efb61060172a11d62101bc804db789f8f9100b0e','_91a4607a1c10ba801268929b961b3f6c067ff82d21','Conformance Client 2','','example-userpass','["https:\/\/localhost.emobix.co.uk:8443\/test\/a\/simplesamlphp-module-oidc\/callback","https:\/\/www.certification.openid.net\/test\/a\/simplesamlphp-module-oidc\/callback"]','["openid","profile","email","offline_access"]',1,1,NULL,NULL,NULL,NULL,NULL, NULL, NULL, NULL, NULL, 'manual', NULL, NULL, NULL, false, false, NULL);
70+
INSERT INTO oidc_client VALUES('_0afb7d18e54b2de8205a93e38ca119e62ee321d031','_944e73bbeec7850d32b68f1b5c780562c955967e4e','Conformance Client 3','Client for client_secret_post','example-userpass','["https:\/\/localhost.emobix.co.uk:8443\/test\/a\/simplesamlphp-module-oidc\/callback","https:\/\/www.certification.openid.net\/test\/a\/simplesamlphp-module-oidc\/callback"]','["openid","profile","email"]',1,1,NULL,NULL,NULL,NULL,NULL, NULL, NULL, NULL, NULL, 'manual', NULL, NULL, NULL, false, false, NULL);
71+
INSERT INTO oidc_client VALUES('_8957eda35234902ba8343c0cdacac040310f17dfca','_322d16999f9da8b5abc9e9c0c08e853f60f4dc4804','RP-Initiated Logout Client','Client for testing RP-Initiated Logout','example-userpass','["https:\/\/localhost.emobix.co.uk:8443\/test\/a\/simplesamlphp-module-oidc\/callback","https:\/\/www.certification.openid.net\/test\/a\/simplesamlphp-module-oidc\/callback"]','["openid","profile","email","address","phone"]',1,1,NULL,'["https:\/\/localhost.emobix.co.uk:8443\/test\/a\/simplesamlphp-module-oidc\/post_logout_redirect"]',NULL,NULL,NULL, NULL, NULL, NULL, NULL, 'manual', NULL, NULL, NULL, false, false, NULL);
72+
INSERT INTO oidc_client VALUES('_9fe2f7589ece1b71f5ef75a91847d71bc5125ec2a6','_3c0beb20194179c01d7796c6836f62801e9ed4b368','Back-Channel Logout Client','Client for testing Back-Channel Logout','example-userpass','["https:\/\/localhost.emobix.co.uk:8443\/test\/a\/simplesamlphp-module-oidc\/callback","https:\/\/www.certification.openid.net\/test\/a\/simplesamlphp-module-oidc\/callback"]','["openid","profile","email","address","phone"]',1,1,NULL,'["https:\/\/localhost.emobix.co.uk:8443\/test\/a\/simplesamlphp-module-oidc\/post_logout_redirect"]','https://httpd:8443/test/a/simplesamlphp-module-oidc/backchannel_logout',NULL,NULL, NULL, NULL, NULL, NULL, 'manual', NULL, NULL, NULL, false, false, NULL);
5673
CREATE TABLE oidc_access_token (
5774
id VARCHAR(191) PRIMARY KEY NOT NULL,
5875
scopes TEXT,

docker/ssp/module_oidc.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,15 @@
2121
ModuleConfig::OPTION_TOKEN_REFRESH_TOKEN_TTL => 'P1M',
2222
ModuleConfig::OPTION_TOKEN_ACCESS_TOKEN_TTL => 'PT1H',
2323

24-
ModuleConfig::OPTION_TOKEN_SIGNER => \Lcobucci\JWT\Signer\Rsa\Sha256::class,
24+
ModuleConfig::OPTION_PROTOCOL_SIGNATURE_KEY_PAIRS => [
25+
[
26+
ModuleConfig::KEY_ALGORITHM => \SimpleSAML\OpenID\Algorithms\SignatureAlgorithmEnum::RS256,
27+
ModuleConfig::KEY_PRIVATE_KEY_FILENAME => ModuleConfig::DEFAULT_PKI_PRIVATE_KEY_FILENAME,
28+
ModuleConfig::KEY_PUBLIC_KEY_FILENAME => ModuleConfig::DEFAULT_PKI_CERTIFICATE_FILENAME,
29+
// ModuleConfig::KEY_PRIVATE_KEY_PASSWORD => 'private-key-password', // Optional
30+
// ModuleConfig::KEY_KEY_ID => 'rsa-connect-signing-key-2026', // Optional
31+
],
32+
],
2533

2634
ModuleConfig::OPTION_AUTH_SOURCE => 'example-userpass',
2735

docs/1-oidc.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ Supported flows:
1313

1414
## Note on OpenID Federation (OIDFed)
1515

16-
OpenID Federation support is in draft, as is the
17-
[specification](https://openid.net/specs/openid-federation-1_0). You can
16+
OpenID Federation support is in draft phase. You can
1817
expect breaking changes in future releases related to OIDFed
1918
capabilities. OIDFed can be enabled or disabled in the module
2019
configuration.

docs/2-oidc-installation.md

Lines changed: 88 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ cp modules/oidc/config/module_oidc.php.dist config/module_oidc.php
2222

2323
## 3. Configure the database
2424

25-
The module uses SimpleSAMLphp's database feature to store access and
26-
refresh tokens, user data, and other artifacts. Edit `config/config.php`
25+
The module uses SimpleSAMLphp's database feature to store Access and
26+
Refresh tokens, user data, and other artifacts. Edit `config/config.php`
2727
and ensure at least the following parameters are set:
2828

2929
```php
@@ -34,83 +34,135 @@ and ensure at least the following parameters are set:
3434

3535
Note: SQLite, PostgreSQL, and MySQL are supported.
3636

37-
## 4. Create key pairs
37+
## 4. Create signature key pairs
3838

39-
ID and Access tokens are signed JWTs. Create a public/private RSA key
40-
pair for OIDC protocol operations. If you plan to use OpenID Federation,
41-
create a separate key pair for federation operations.
39+
In order to sign JWS artifacts (ID Tokens, Entity Statements, Verifiable
40+
Credentials, etc.), you must create a public / private key pair for each
41+
signature algorithm that you want to support. You should use different
42+
keys for protocol (Connect), Federation and Verifiable Credential (VCI)
43+
operations. You must have at least one algorithm / key-pair for protocol
44+
(Connect), and for Federation and VCI if you use those features.
4245

43-
### RSA key pair generation
46+
### RSA key pair generation, for `RS256/384/512` and `PS256/384/512` algorithms
4447

45-
Generate private keys without a passphrase:
48+
Generate private keys without a password:
4649

4750
```bash
48-
openssl genrsa -out cert/oidc_module.key 3072
49-
openssl genrsa -out cert/oidc_module_federation.key 3072
51+
openssl genrsa -out cert/oidc_module_connect_rsa_01.key 3072
52+
openssl genrsa -out cert/oidc_module_federation_rsa_01.key 3072
53+
openssl genrsa -out cert/oidc_module_vci_rsa_01.key 3072
5054
```
5155

52-
Generate private keys with a passphrase:
56+
Generate private keys with a password:
5357

5458
```bash
55-
openssl genrsa -passout pass:myPassPhrase -out cert/oidc_module.key 3072
56-
openssl genrsa -passout pass:myPassPhrase -out cert/oidc_module_federation.key 3072
59+
openssl genrsa -passout pass:somePassword -out cert/oidc_module_connect_rsa_01.key 3072
60+
openssl genrsa -passout pass:somePassword -out cert/oidc_module_federation_rsa_01.key 3072
61+
openssl genrsa -passout pass:somePassword -out cert/oidc_module_vci_rsa_01.key 3072
5762
```
5863

5964
Extract public keys:
6065

61-
Without passphrase:
66+
Without password:
6267

6368
```bash
64-
openssl rsa -in cert/oidc_module.key -pubout -out cert/oidc_module.crt
65-
openssl rsa -in cert/oidc_module_federation.key -pubout -out cert/oidc_module_federation.crt
69+
openssl rsa -in cert/oidc_module_connect_rsa_01.key -pubout -out cert/oidc_module_connect_rsa_01.pub
70+
openssl rsa -in cert/oidc_module_federation_rsa_01.key -pubout -out cert/oidc_module_federation_rsa_01.pub
71+
openssl rsa -in cert/oidc_module_vci_rsa_01.key -pubout -out cert/oidc_module_vci_rsa_01.pub
6672
```
6773

68-
With a passphrase:
74+
With a password:
6975

7076
```bash
71-
openssl rsa -in cert/oidc_module.key -passin pass:myPassPhrase -pubout -out cert/oidc_module.crt
72-
openssl rsa -in cert/oidc_module_federation.key -passin pass:myPassPhrase -pubout -out cert/oidc_module_federation.crt
77+
openssl rsa -in cert/oidc_module_connect_rsa_01.key -passin pass:somePassword -pubout -out cert/oidc_module_connect_rsa_01.pub
78+
openssl rsa -in cert/oidc_module_federation_rsa_01.key -passin pass:somePassword -pubout -out cert/oidc_module_federation_rsa_01.pub
79+
openssl rsa -in cert/oidc_module_vci_rsa_01.key -passin pass:somePassword -pubout -out cert/oidc_module_vci_rsa_01.pub
7380
```
7481

75-
If you use different file names or a passphrase, update
76-
`config/module_oidc.php` accordingly.
82+
Enter algorithm, key file names, and a password (if used) in `config/module_oidc.php` accordingly.
7783

78-
### EC key pair generation
84+
### EC key pair generation, per curve for different algorithms
7985

8086
If you prefer to use Elliptic Curve Cryptography (ECC) instead of RSA.
8187

82-
Generate private keys without a passphrase:
88+
Generate private EC P‑256 keys without a password, usable for `ES256` algorithm:
8389

8490
```bash
85-
openssl ecparam -name prime256v1 -genkey -noout -out cert/oidc_module.key
86-
openssl ecparam -name prime256v1 -genkey -noout -out cert/oidc_module_federation.key
91+
openssl ecparam -genkey -name prime256v1 -noout -out cert/oidc_module_connect_ec_p256_01.key
92+
openssl ecparam -genkey -name prime256v1 -noout -out cert/oidc_module_federation_ec_p256_01.key
93+
openssl ecparam -genkey -name prime256v1 -noout -out cert/oidc_module_vci_ec_p256_01.key
8794
```
8895

89-
Generate private keys with a passphrase:
96+
Generate private EC P‑256 keys with a password, usable for `ES256` algorithm:
9097

9198
```bash
92-
openssl ecparam -genkey -name secp384r1 -noout -out cert/oidc_module.key -passout pass:myPassPhrase
93-
openssl ecparam -genkey -name secp384r1 -noout -out cert/oidc_module_federation.key -passout pass:myPassPhrase
99+
openssl ecparam -genkey -name prime256v1 | openssl ec -AES-128-CBC -passout pass:somePassword -out cert/oidc_module_connect_ec_p256_01.key
100+
openssl ecparam -genkey -name prime256v1 | openssl ec -AES-128-CBC -passout pass:somePassword -out cert/oidc_module_federation_ec_p256_01.key
101+
openssl ecparam -genkey -name prime256v1 | openssl ec -AES-128-CBC -passout pass:somePassword -out cert/oidc_module_vci_ec_p256_01.key
94102
```
95103

96104
Extract public keys:
97105

98-
Without passphrase:
106+
Without password:
99107

100108
```bash
101-
openssl ec -in cert/oidc_module.key -pubout -out cert/oidc_module.crt
102-
openssl ec -in cert/oidc_module_federation.key -pubout -out cert/oidc_module_federation.crt
109+
openssl ec -in cert/oidc_module_connect_ec_p256_01.key -pubout -out cert/oidc_module_connect_ec_p256_01.pub
110+
openssl ec -in cert/oidc_module_federation_ec_p256_01.key -pubout -out cert/oidc_module_federation_ec_p256_01.pub
111+
openssl ec -in cert/oidc_module_vci_ec_p256_01.key -pubout -out cert/oidc_module_vci_ec_p256_01.pub
103112
```
104113

105-
With a passphrase:
114+
With a password:
106115

107116
```bash
108-
openssl ec -in cert/oidc_module.key -passin pass:myPassPhrase -pubout -out cert/oidc_module.crt
109-
openssl ec -in cert/oidc_module.key -passin pass:myPassPhrase -pubout -out cert/oidc_module.crt
117+
openssl ec -in cert/oidc_module_connect_ec_p256_01.key -passin pass:somePassword -pubout -out cert/oidc_module_connect_ec_p256_01.pub
118+
openssl ec -in cert/oidc_module_federation_ec_p256_01.key -passin pass:somePassword -pubout -out cert/oidc_module_federation_ec_p256_01.pub
119+
openssl ec -in cert/oidc_module_vci_ec_p256_01.key -passin pass:somePassword -pubout -out cert/oidc_module_vci_ec_p256_01.pub
110120
```
111121

112-
If you use different file names or a passphrase, update
113-
`config/module_oidc.php` accordingly.
122+
For other curves, replace the `-name` option value depending on which
123+
algorithm you want to support:
124+
- `-name secp384r1`: usable for `ES384` algorithm
125+
- `-name secp521r1`: usable for `ES512` algorithm
126+
127+
Enter algorithm, key file names, and a password (if used) in `config/module_oidc.php` accordingly.
128+
129+
### Ed25519 key pair generation, for `EdDSA` algorithm
130+
131+
Generate private keys without a password:
132+
133+
```bash
134+
openssl genpkey -algorithm ED25519 -out cert/oidc_module_connect_ed25519_01.key
135+
openssl genpkey -algorithm ED25519 -out cert/oidc_module_federation_ed25519_01.key
136+
openssl genpkey -algorithm ED25519 -out cert/oidc_module_vci_ed25519_01.key
137+
```
138+
139+
Generate private keys with a password:
140+
141+
```bash
142+
openssl genpkey -algorithm ED25519 -AES-128-CBC -pass pass:somePassword -out cert/oidc_module_connect_ed25519_01.key
143+
openssl genpkey -algorithm ED25519 -AES-128-CBC -pass pass:somePassword -out cert/oidc_module_federation_ed25519_01.key
144+
openssl genpkey -algorithm ED25519 -AES-128-CBC -pass pass:somePassword -out cert/oidc_module_vci_ed25519_01.key
145+
```
146+
147+
Extract public keys:
148+
149+
Without password:
150+
151+
```bash
152+
openssl pkey -in cert/oidc_module_connect_ed25519_01.key -pubout -out cert/oidc_module_connect_ed25519_01.pub
153+
openssl pkey -in cert/oidc_module_federation_ed25519_01.key -pubout -out cert/oidc_module_federation_ed25519_01.pub
154+
openssl pkey -in cert/oidc_module_vci_ed25519_01.key -pubout -out cert/oidc_module_vci_ed25519_01.pub
155+
```
156+
157+
With a password:
158+
159+
```bash
160+
openssl pkey -in cert/oidc_module_connect_ed25519_01.key -passin pass:somePassword -pubout -out cert/oidc_module_connect_ed25519_01.pub
161+
openssl pkey -in cert/oidc_module_federation_ed25519_01.key -passin pass:somePassword -pubout -out cert/oidc_module_federation_ed25519_01.pub
162+
openssl pkey -in cert/oidc_module_vci_ed25519_01.key -passin pass:somePassword -pubout -out cert/oidc_module_vci_ed25519_01.pub
163+
```
164+
165+
Enter algorithm, key file names, and a password (if used) in `config/module_oidc.php` accordingly.
114166

115167
## 5. Enable the module
116168

0 commit comments

Comments
 (0)