{"id":17317420,"url":"https://github.com/justin-tay/mockpass-spring-boot-example","last_synced_at":"2026-05-03T16:32:32.854Z","repository":{"id":230857027,"uuid":"780215892","full_name":"justin-tay/mockpass-spring-boot-example","owner":"justin-tay","description":"Spring Boot example using Spring Security to integrate with Mockpass","archived":false,"fork":false,"pushed_at":"2024-04-12T08:06:49.000Z","size":73,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-12T15:24:18.944Z","etag":null,"topics":["corppass","java","mockpass","oidc","singpass","spring","spring-boot"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/justin-tay.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-04-01T01:59:57.000Z","updated_at":"2024-04-15T03:54:57.386Z","dependencies_parsed_at":"2024-04-05T15:28:49.006Z","dependency_job_id":"cb38b049-720c-4b53-b1c0-34e82f16c836","html_url":"https://github.com/justin-tay/mockpass-spring-boot-example","commit_stats":null,"previous_names":["justin-tay/mockpass-spring-boot-example"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/justin-tay/mockpass-spring-boot-example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/justin-tay%2Fmockpass-spring-boot-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/justin-tay%2Fmockpass-spring-boot-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/justin-tay%2Fmockpass-spring-boot-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/justin-tay%2Fmockpass-spring-boot-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/justin-tay","download_url":"https://codeload.github.com/justin-tay/mockpass-spring-boot-example/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/justin-tay%2Fmockpass-spring-boot-example/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32577121,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["corppass","java","mockpass","oidc","singpass","spring","spring-boot"],"created_at":"2024-10-15T13:16:34.574Z","updated_at":"2026-05-03T16:32:32.836Z","avatar_url":"https://github.com/justin-tay.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spring Boot Example OpenID Connect Relying Party for Singpass/Corppass\r\n\r\nThis project is an example implementation of a OpenID Connect Relying Party built using Spring Boot and Spring Security OAuth2 Client.\r\n\r\n[MockPass](https://github.com/opengovsg/mockpass) is used as the public Identity Provider for testing purposes\r\n\r\n## Quick Start\r\n\r\n### Configuring MockPass as the Identity Provider\r\n\r\nThe Spring Boot application exposes its JWKS at http://localhost:8080/oauth2/jwks\r\n\r\n```shell\r\nset SHOW_LOGIN_PAGE=true\r\nset SP_RP_JWKS_ENDPOINT=http://localhost:8080/oauth2/jwks\r\nset CP_RP_JWKS_ENDPOINT=http://localhost:8080/oauth2/jwks\r\nnpx --y @opengovsg/mockpass\r\n```\r\n\r\n### Installing and running the Relying Party Spring Boot application\r\n\r\n```shell\r\nmvn spring-boot:run\r\n```\r\n\r\n### Testing the example Relying Party\r\n\r\n\r\n| Description                        | Endpoint\r\n|------------------------------------|-----------------------------------------------------\r\n| Access the application             | http://localhost:8080/login-user\r\n| Logout from the application        | http://localhost:8080/logout\r\n| View the public keys               | http://localhost:8080/oauth2/jwks\r\n| View Mockpass public keys          | http://localhost:5156/singpass/v2/.well-known/keys\r\n| View Mockpass OpenID configuration | http://localhost:5156/singpass/v2/.well-known/openid-configuration\r\n\r\n## Integration Details\r\n\r\nThe following things are needed to be configured in Spring for the integration\r\n* Exposing the signature and encryption public keys via a JWKS endpoint\r\n* Use `private_key_jwt` client authentication with the `aud` claim set to the `iss` value and the `typ` header set to `JWT`\r\n* ID token needs to be decrypted with the private decryption key and signature verified against the Identity Provider's JWKS endpoint\r\n\r\nNote that this example does not securely store the private keys which are located in `src/main/resources/jwks.json`. This should be securely stored and rotated, for instance on AWS this should be stored in AWS Secrets Manager with a Secrets Manager Rotation Lambda. This can be configured in Spring using [Spring Cloud AWS Secrets Manager](https://github.com/awspring/spring-cloud-aws).\r\n\r\n### Json Web Key Sets\r\n\r\nMockpass will call the endpoint http://localhost:8080/oauth2/jwks in order to get the public keys of the application\r\n* The public encryption key used for Mockpass to encrypt the ID Token to send to the application\r\n* The public verification key used for Mockpass to verify the signature for the `private_key_jwt` client assertion\r\n\r\nThe `JWKSet` `@Bean` used by the application is produced in `WebSecurityConfiguration` and its public keys are exposed using the `@RestController` `JwksController`. Note that `JWKSet.toString()` removes the private components of the keys.\r\n\r\n### Client Authentication\r\n\r\nMockpass requires the use of `private_key_jwt` client authentication.\r\n\r\nSpring needs to be configured to use this client authentication method, and the token response client needs to be configured to use the appropriate private key to perform the signing as well as to set the `aud` claim to the issuer value.\r\n\r\n```yaml\r\nspring:\r\n  security:\r\n    oauth2:\r\n      client:\r\n        registration:\r\n          mockpass:\r\n            client-id: mockpass-spring-boot-example\r\n            client-authentication-method: private_key_jwt\r\n            authorization-grant-type: authorization_code\r\n            scope:\r\n            - openid\r\n```\r\n\r\nThe `DefaultAuthorizationCodeTokenResponseClient` is used with the `NimbusJwtClientAuthenticationParametersConverter` configured with the private key and `NimbusJwtClientAuthenticationParametersConverter` used to customize the claims and headers on the client assertion.\r\n\r\n### Decrypting ID Token\r\n\r\nA `JwtDecoderFactory\u003cClientRegistration\u003e` `@Bean` needs to be exposed to customize how the ID Token is decoded. A `DefaultJWTProcessor\u003cSecurityContext\u003e` is used with the `JWEKeySelector` and `JWSKeySelector` with the application's private decryption key to decrypt the ID Token and Mockpass's verification key to verify the signature on the ID Token. The verification keys from Mockpass are obtained by querying Mockpass's JWKS endpoint.\r\n\r\n## Flow\r\n\r\n```mermaid\r\nsequenceDiagram\r\n    autonumber\r\n\r\n    participant User\r\n    participant Browser\r\n    participant Application Server\r\n    participant Mockpass\r\n\r\n    User-\u003e\u003eBrowser: Navigate to user information page\r\n\r\n    Browser-\u003e\u003eApplication Server: Send request for user information page (/login-user)\r\n\r\n    Application Server-\u003e\u003eApplication Server: Not authenticated, determine provider to redirect to\r\n\r\n    Application Server--\u003e\u003eBrowser: Redirect to Application for Mockpass provider\r\n\r\n    Browser-\u003e\u003eApplication Server: Send request for Mockpass provider (/oauth2/authorization/mockpass)\r\n\r\n    Application Server-\u003e\u003eApplication Server: Generate Authorization Request\r\n\r\n    Application Server--\u003e\u003eBrowser: Redirect to Mockpass with Authorization Request\r\n\r\n    Browser-\u003e\u003eMockpass: Send Authorization Request (/singpass/v2/authorize)\r\n\r\n    Mockpass-\u003e\u003eMockpass: Generate login page\r\n\r\n    Mockpass--\u003e\u003eBrowser: Return login page\r\n\r\n    User-\u003e\u003eBrowser: Enter login credentials and sign in\r\n\r\n    Browser-\u003e\u003eMockpass: Send login credentials \r\n\r\n    Mockpass-\u003e\u003eMockpass: Process login credentials\r\n\r\n    Mockpass--\u003e\u003eBrowser: Redirect to Application with Authorization Response with code\r\n\r\n    Browser-\u003e\u003eApplication Server: Send Authorization Response with code (/login/oauth2/code/mockpass)\r\n\r\n    Application Server-\u003e\u003eApplication Server: Generate Token Request and client credentials\r\n\r\n    Application Server-\u003e\u003eMockpass: Send Token Request with client credentials (/singpass/v2/token)\r\n\r\n    Mockpass-\u003e\u003eApplication Server: Send request for client json web key set (/oauth2/jwks)\r\n\r\n    Application Server--\u003e\u003eMockpass: Return client json web key set\r\n\r\n    Mockpass-\u003e\u003eMockpass: Process client credentials and create tokens\r\n\r\n    Mockpass--\u003e\u003eApplication Server: Return Token Response with access and id tokens\r\n\r\n    Application Server--\u003e\u003eBrowser: Redirect to user information page\r\n\r\n    Browser-\u003e\u003eApplication Server: Send request for user information page (/login-user)\r\n\r\n    Application Server-\u003e\u003eApplication Server: Authenticated\r\n\r\n    Application Server--\u003e\u003eBrowser: Return user information page\r\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjustin-tay%2Fmockpass-spring-boot-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjustin-tay%2Fmockpass-spring-boot-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjustin-tay%2Fmockpass-spring-boot-example/lists"}