Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
da38910
Start with Credential Issuer and OAuth2 configuration discovery
cicnavi Apr 6, 2025
512b0ad
WIP Credential Issuer
cicnavi Apr 10, 2025
9d73bc5
To be removed
cicnavi Apr 28, 2025
f02db2c
To be removed
cicnavi Apr 28, 2025
6d10476
To be removed
cicnavi Apr 28, 2025
1a9c775
Interop
cicnavi Apr 28, 2025
e75ccda
Interop
cicnavi Apr 28, 2025
8fcf3d5
Interop
cicnavi Apr 28, 2025
4c54a79
Revert hardcoded kid for interop
cicnavi Apr 28, 2025
f041094
Merge branch 'master' into wip-vci
cicnavi Apr 29, 2025
6d4245b
WIP
cicnavi May 7, 2025
fccdbe1
WIP
cicnavi May 13, 2025
1d806d5
WIP
May 14, 2025
b9ba594
WIP
cicnavi May 14, 2025
e65bbf6
WIP
cicnavi May 14, 2025
2589357
WIP
cicnavi May 14, 2025
5b64d71
WIP
cicnavi May 14, 2025
02625cb
WIP
cicnavi May 14, 2025
d3d1e76
WIP
cicnavi May 14, 2025
bfbc3c0
WIP
cicnavi May 14, 2025
f4c9788
WIP
cicnavi May 14, 2025
435f512
WIP
cicnavi May 14, 2025
ef51047
WIP
cicnavi May 14, 2025
70866d7
WIP
cicnavi May 15, 2025
bd7447c
WIP
cicnavi May 15, 2025
2725b3d
WIP
cicnavi May 15, 2025
07cec9f
WIP
cicnavi May 15, 2025
559a9c5
WIP
cicnavi May 15, 2025
9bce3f8
WIP
cicnavi May 15, 2025
bf4597e
WIP
cicnavi May 22, 2025
2eda4a0
WIP
cicnavi May 29, 2025
3910e53
WIP
cicnavi May 29, 2025
ee98b5a
WIP
cicnavi Jun 2, 2025
3d0c16a
WIP
cicnavi Jun 3, 2025
a89915d
WIP
cicnavi Jun 5, 2025
a049d09
WIP
cicnavi Jun 6, 2025
0598490
Merge with master
cicnavi Jul 28, 2025
b2282ff
WIP
cicnavi Aug 4, 2025
5d4c433
WIP
cicnavi Aug 4, 2025
eb44e29
WIP
cicnavi Aug 6, 2025
089780e
WIP
cicnavi Aug 6, 2025
ba04a70
WIP
cicnavi Aug 6, 2025
819bc62
WIP
cicnavi Aug 6, 2025
dc8766f
WIP
cicnavi Aug 12, 2025
6594667
WIP
cicnavi Aug 12, 2025
9e7e094
WIP
cicnavi Aug 12, 2025
3579417
WIP
cicnavi Aug 13, 2025
2dd5315
WIP
cicnavi Aug 18, 2025
36553ad
WIP
cicnavi Sep 8, 2025
9ec2306
Lint
cicnavi Sep 10, 2025
a16b998
Update conformance SQL
cicnavi Sep 10, 2025
d75b9d2
Before VCI Authorization Code
cicnavi Sep 10, 2025
ce40d95
Rename ClientIdRule to ClientRule
cicnavi Sep 10, 2025
847111a
Pre auth code release modification
cicnavi Sep 12, 2025
14317dd
Introduce auth code flow type attribute
cicnavi Sep 12, 2025
2fc22b0
Lint
cicnavi Sep 12, 2025
cc1256d
WIP Authorization Details in AuthCode
cicnavi Sep 12, 2025
1210f98
Rename IdTokenResponse to TokenResponse
cicnavi Sep 12, 2025
cd7a71e
Initial auth-code implementation
cicnavi Sep 15, 2025
759e689
Update AT state
cicnavi Sep 16, 2025
46ae341
Check for flow type when issuing credentials
cicnavi Sep 17, 2025
1937761
Remove no clinet_id ability
cicnavi Sep 18, 2025
36d09d0
Add grant_type param to VCI api
cicnavi Sep 18, 2025
f1e2af5
Move to generic client instantiation to client repo
cicnavi Sep 18, 2025
94af021
Add main auth code validation
cicnavi Sep 18, 2025
cfc93cc
Add API documentation
cicnavi Sep 26, 2025
954d4af
Merge branch 'wip-version-7' into wip-vci
cicnavi Oct 6, 2025
32ddccc
Merge with version-7
cicnavi Oct 10, 2025
092bf54
Merge with version 7
cicnavi Oct 10, 2025
07e7977
Reflect issuer_state in access_token (#317)
mrvanes Oct 24, 2025
933277d
Merge branch 'wip-version-7' into wip-vci
cicnavi Oct 24, 2025
76c5b22
Don't handle issuer state for pre-auth code flow
cicnavi Oct 27, 2025
8461589
Include issuer_state when building access token from data
cicnavi Oct 27, 2025
8378963
Fix issuerState update statement
cicnavi Oct 27, 2025
1f1da59
Clean up logging a bit
cicnavi Oct 27, 2025
20419a3
Merge with wip-version-7
cicnavi Nov 10, 2025
5e268a8
Update docs
cicnavi Nov 21, 2025
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
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"psr/container": "^2.0",
"psr/log": "^3",
"simplesamlphp/composer-module-installer": "^1.3",
"simplesamlphp/openid": "~0.0.18",
"simplesamlphp/openid": "~0.1.0",
"spomky-labs/base64url": "^2.0",
"symfony/expression-language": "^6.3",
"symfony/psr-http-message-bridge": "^7.1",
Expand Down
354 changes: 354 additions & 0 deletions config/module_oidc.php.dist

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions docker/apache-override.cf
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
RewriteEngine On
RewriteRule ^/.well-known/openid-configuration(.*) /${SSP_APACHE_ALIAS}module.php/oidc/.well-known/openid-configuration$1 [PT]
RewriteRule ^/.well-known/openid-federation(.*) /${SSP_APACHE_ALIAS}module.php/oidc/.well-known/openid-federation$1 [PT]
RewriteRule ^/.well-known/openid-credential-issuer(.*) /${SSP_APACHE_ALIAS}module.php/oidc/.well-known/openid-credential-issuer$1 [PT]
RewriteRule ^/.well-known/oauth-authorization-server(.*) /${SSP_APACHE_ALIAS}module.php/oidc/.well-known/oauth-authorization-server$1 [PT]
RewriteRule ^/.well-known/jwt-vc-issuer(.*) /${SSP_APACHE_ALIAS}module.php/oidc/.well-known/jwt-vc-issuer$1 [PT]

# Leave Authorization header with Bearer tokens available in requests.
# Solution 1:
Expand Down
48 changes: 33 additions & 15 deletions docker/conformance.sql
Original file line number Diff line number Diff line change
Expand Up @@ -43,30 +43,36 @@ CREATE TABLE oidc_client (
updated_at TIMESTAMP NULL DEFAULT NULL,
created_at TIMESTAMP NULL DEFAULT NULL,
expires_at TIMESTAMP NULL DEFAULT NULL,
is_federated BOOLEAN NOT NULL DEFAULT false
is_federated BOOLEAN NOT NULL DEFAULT false,
is_generic BOOLEAN NOT NULL DEFAULT false
);
-- Used 'httpd' host for back-channel logout url (https://httpd:8443/test/a/simplesamlphp-module-oidc/backchannel_logout)
-- since this is the hostname of conformance server while running in container environment
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
CREATE TABLE oidc_access_token (
id VARCHAR(191) PRIMARY KEY NOT NULL,
scopes TEXT,
expires_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
user_id VARCHAR(191) NOT NULL,
user_id VARCHAR(191) NOT NULL,
client_id VARCHAR(191) NOT NULL,
is_revoked BOOLEAN NOT NULL DEFAULT false,
auth_code_id varchar(191) DEFAULT NULL, requested_claims TEXT NULL,
CONSTRAINT FK_43C1650EA76ED395 FOREIGN KEY (user_id)
REFERENCES oidc_user (id) ON DELETE CASCADE,
CONSTRAINT FK_43C1650E19EB6921 FOREIGN KEY (client_id)
REFERENCES oidc_client (id) ON DELETE CASCADE
flow_type CHAR(64) NULL,
authorization_details TEXT NULL,
bound_client_id TEXT NULL,
bound_redirect_uri TEXT NULL,
issuer_state TEXT NULL,
CONSTRAINT FK_43C1650EA76ED395 FOREIGN KEY (user_id)
REFERENCES oidc_user (id) ON DELETE CASCADE,
CONSTRAINT FK_43C1650E19EB6921 FOREIGN KEY (client_id)
REFERENCES oidc_client (id) ON DELETE CASCADE
);
CREATE TABLE oidc_refresh_token (
id VARCHAR(191) PRIMARY KEY NOT NULL,
id VARCHAR(191) PRIMARY KEY NOT NULL,
expires_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
access_token_id VARCHAR(191) NOT NULL,
is_revoked BOOLEAN NOT NULL DEFAULT false,
Expand All @@ -78,14 +84,20 @@ CREATE TABLE oidc_auth_code (
id VARCHAR(191) PRIMARY KEY NOT NULL,
scopes TEXT,
expires_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
user_id VARCHAR(191) NOT NULL,
user_id VARCHAR(191) NOT NULL,
client_id VARCHAR(191) NOT NULL,
is_revoked BOOLEAN NOT NULL DEFAULT false,
redirect_uri TEXT NOT NULL, nonce TEXT NULL,
flow_type CHAR(64) DEFAULT NULL,
tx_code varchar(191) DEFAULT NULL,
authorization_details TEXT NULL,
bound_client_id TEXT NULL,
bound_redirect_uri TEXT NULL,
issuer_state TEXT NULL,
CONSTRAINT FK_97D32CA7A76ED395 FOREIGN KEY (user_id)
REFERENCES oidc_user (id) ON DELETE CASCADE,
REFERENCES oidc_user (id) ON DELETE CASCADE,
CONSTRAINT FK_97D32CA719EB6921 FOREIGN KEY (client_id)
REFERENCES oidc_client (id) ON DELETE CASCADE
REFERENCES oidc_client (id) ON DELETE CASCADE
);
CREATE TABLE oidc_allowed_origin (
client_id varchar(191) NOT NULL,
Expand All @@ -98,4 +110,10 @@ CREATE TABLE oidc_session_logout_ticket (
sid VARCHAR(191) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE oidc_vci_issuer_state (
value CHAR(64) PRIMARY KEY NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
is_revoked BOOLEAN NOT NULL DEFAULT false
);
COMMIT;
20 changes: 20 additions & 0 deletions docs/1-oidc.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,26 @@ Currently supported OIDFed features:
OIDFed is implemented using the
[SimpleSAMLphp OpenID library](https://github.com/simplesamlphp/openid).

## Note on OpenID for Verifiable Credential Issuance (OpenID4VCI) support

OpenID4VCI support was done as per draft 15 of the specification and is in the
experimental stage. You should NOT use it in production environments.

Currently implemented OpenID4VCI features:

- Grant types:
- Pre-authorized Code flow (new flow defined by the OpenID4VCI spec)
- Authorization Code flow
- Credential formats:
- jwt_vc_json, using VCDM v1.1
- dc+sd-jwt (previously vc+sd-jwt) (SD-JWT VC)
- Proof types:
- jwt
- API for credential offer fetching

OpenID4VCI is also implemented using the
[SimpleSAMLphp OpenID library](https://github.com/simplesamlphp/openid).

## Version compatibility

Minor versions listed show which SimpleSAMLphp versions were used during
Expand Down
41 changes: 40 additions & 1 deletion docs/2-oidc-installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@ and ensure at least the following parameters are set:

Note: SQLite, PostgreSQL, and MySQL are supported.

## 4. Create RSA key pairs
## 4. Create key pairs

ID and Access tokens are signed JWTs. Create a public/private RSA key
pair for OIDC protocol operations. If you plan to use OpenID Federation,
create a separate key pair for federation operations.

### RSA key pair generation

Generate private keys without a passphrase:

```bash
Expand Down Expand Up @@ -73,6 +75,43 @@ openssl rsa -in cert/oidc_module_federation.key -passin pass:myPassPhrase -pubou
If you use different file names or a passphrase, update
`config/module_oidc.php` accordingly.

### EC key pair generation

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

Generate private keys without a passphrase:

```bash
openssl ecparam -name prime256v1 -genkey -noout -out cert/oidc_module.key
openssl ecparam -name prime256v1 -genkey -noout -out cert/oidc_module_federation.key
```

Generate private keys with a passphrase:

```bash
openssl ecparam -genkey -name secp384r1 -noout -out cert/oidc_module.key -passout pass:myPassPhrase
openssl ecparam -genkey -name secp384r1 -noout -out cert/oidc_module_federation.key -passout pass:myPassPhrase
```

Extract public keys:

Without passphrase:

```bash
openssl ec -in cert/oidc_module.key -pubout -out cert/oidc_module.crt
openssl ec -in cert/oidc_module_federation.key -pubout -out cert/oidc_module_federation.crt
```

With a passphrase:

```bash
openssl ec -in cert/oidc_module.key -passin pass:myPassPhrase -pubout -out cert/oidc_module.crt
openssl ec -in cert/oidc_module.key -passin pass:myPassPhrase -pubout -out cert/oidc_module.crt
```

If you use different file names or a passphrase, update
`config/module_oidc.php` accordingly.

## 5. Enable the module

Edit `config/config.php` and enable `oidc`:
Expand Down
6 changes: 6 additions & 0 deletions docs/3-oidc-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ There you can see discovery URLs. Typical discovery endpoints are:
[https://yourserver/simplesaml/module.php/oidc/.well-known/openid-configuration](https://yourserver/simplesaml/module.php/oidc/.well-known/openid-configuration)
- OpenID Federation configuration:
[https://yourserver/simplesaml/module.php/oidc/.well-known/openid-federation](https://yourserver/simplesaml/module.php/oidc/.well-known/openid-federation)
- OpenID for Verifiable Credential Issuance configuration:
[https://yourserver/simplesaml/module.php/oidc/.well-known/openid-credential-issuer](https://yourserver/simplesaml/module.php/oidc/.well-known/openid-credential-issuer)
- OAuth2 Authorization Server configuration:
[https://yourserver/simplesaml/module.php/oidc/.well-known/oauth-authorization-server](https://yourserver/simplesaml/module.php/oidc/.well-known/oauth-authorization-server)
- JWT VC Issuer configuration:
[https://yourserver/simplesaml/module.php/oidc/.well-known/jwt-vc-issuer](https://yourserver/simplesaml/module.php/oidc/.well-known/jwt-vc-issuer)

You may publish these as ".well-known" URLs at the web root using your
web server. For example, for `openid-configuration`:
Expand Down
6 changes: 6 additions & 0 deletions docs/6-oidc-upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ apply those relevant to your deployment.

New features:

- Initial support for OpenID for Verifiable Credential Issuance
(OpenID4VCI). Note that the implementation is experimental. You should not use
it in production yet.

New configuration options:

- Several new options regarding support for OpenID4VCI.

Major impact changes:

- In v6 of the module, when defining custom scopes, there was a possibility to
Expand Down
Loading