{"id":29021579,"url":"https://github.com/openbankproject/obp-portal","last_synced_at":"2026-04-03T10:40:51.084Z","repository":{"id":297177436,"uuid":"991896112","full_name":"OpenBankProject/OBP-Portal","owner":"OpenBankProject","description":"Some new Portal and Consent pages (WIP) Note: The main Portal functionality is currently in OBP-API","archived":false,"fork":false,"pushed_at":"2025-07-29T08:22:05.000Z","size":2177,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-29T10:38:43.324Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OpenBankProject.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,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-05-28T10:03:42.000Z","updated_at":"2025-07-29T08:22:09.000Z","dependencies_parsed_at":"2025-06-04T13:29:00.272Z","dependency_job_id":"525a35af-6b6b-424b-a520-194f6f386e4a","html_url":"https://github.com/OpenBankProject/OBP-Portal","commit_stats":null,"previous_names":["openbankproject/obp-portal"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/OpenBankProject/OBP-Portal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenBankProject%2FOBP-Portal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenBankProject%2FOBP-Portal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenBankProject%2FOBP-Portal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenBankProject%2FOBP-Portal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OpenBankProject","download_url":"https://codeload.github.com/OpenBankProject/OBP-Portal/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenBankProject%2FOBP-Portal/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269180879,"owners_count":24373836,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-06T02:00:09.910Z","response_time":99,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2025-06-26T02:06:48.934Z","updated_at":"2026-04-03T10:40:51.079Z","avatar_url":"https://github.com/OpenBankProject.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"41111## Getting Started\n\n### Install dependencies\n\n```bash\nnpm install\n```\n\n### Configure Environment\n\ncopy .env.example to .env and fill out as needed\n\nMake sure you set the `ORIGIN` variable to the domain that you are deploying to i.e. https://obp-portal.openbankproject.com or something like that\n\nFor a complete list of environment variables and their usage, see [Environment Variables Documentation](./docs/environment-variables.md).\n\n## Developing\n\nOnce you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:\n\n```bash\nnpm run dev\n\n# To run on a specific port use:\n# Note: Another port will be used if the target is port is already in use\nnpm run dev -- --port 5174\n\n# To force the use of a port use the following (an error will be thrown if the target port is already in use) use:\nnpm run dev -- --port 5174 --strictPort\n\n# To see other server options see : https://vite.dev/config/server-options (note remove the word server.)\n\n# or start the server and open the app in a new browser tab\nnpm run dev -- --open\n```\n\n## Building\n\nTo create a production version of your app:\n\n```bash\nnpm run build\n```\n\nYou can preview the production build with `npm run preview`.\n\n\u003e To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.\n\n## Deploying in production\n\nMake sure to deploy the latest commit/docker image.\n\nLook carefully at the `.env.example` provided, Copy to `.env` (`.env-docker`) and fill out the variables as needed.\n\nA common mistake is to not change the `APP_CALLBACK_URL`, which should be the domain that the portal is deployed to, not `localhost`.\n\n## Troubleshooting\n\n### OAuth Token Refresh Failures\n\nIf you encounter errors like:\n\n```\nOAuth2RequestError: OAuth request error: invalid_grant\ncode: 'invalid_grant',\ndescription: 'Token is not active'\n```\n\n**What's happening:**\n\n- User's refresh token has expired or become invalid (normal OAuth behavior)\n- System cannot automatically renew the session\n- User needs to log in again\n- Now logged as INFO instead of ERROR since this is expected behavior\n\n**Common causes:**\n\n1. **Refresh token expiration** - OAuth providers set token lifetimes (e.g., 30 days)\n2. **Token revocation** - User logged out from another session\n3. **Provider security policy** - Tokens invalidated after inactivity\n4. **Configuration mismatch** - OAuth client settings incorrect\n\n**Solutions:**\n\n1. **Check your environment configuration** - Verify OAuth settings in `.env`\n2. **Clear cached sessions** - Remove `.svelte-kit/output` and rebuild\n3. **Use fresh credentials** - Re-authenticate with valid tokens\n4. **This is now logged as INFO** - No longer appears as ERROR in logs since it's normal OAuth behavior\n\n**Quick fixes:**\n\n```bash\n# Clear cached sessions\nrm -rf .svelte-kit/output/server/chunks\nnpm run build\n\n# Restart development server\nnpm run dev\n```\n\n**Note:** As of recent updates, token refresh failures are now logged as INFO messages rather than ERROR messages, since expired tokens are part of normal OAuth security behavior.\n\n### Opey Chat JWT Expiration\n\nIf you encounter errors like:\n\n```\nOBP-20204: Bad JWT error. Expired JWT \u003c- com.nimbusds.jwt.proc.BadJWTException: Expired JWT\nError creating authenticated Opey session: OBPRequestError: OBP-20204\n```\n\n**What's happening:**\n\n- The JWT token used for Opey chat integration has expired (normal behavior)\n- System cannot create authenticated chat session with expired JWT\n- User needs to re-authenticate to use chat features\n- Now logged as INFO instead of ERROR since this is expected JWT lifecycle\n\n**Common causes:**\n\n1. **JWT expiration** - Consent JWTs have their own expiration times (typically 1 hour)\n2. **Clock skew** - Server time differences can cause premature expiration\n3. **User consent revoked** - User may have revoked consent from another session\n4. **Session timeout** - Long periods of inactivity\n\n**Solutions:**\n\n1. **User re-authentication** - User should log out and log back in\n2. **Check system clocks** - Ensure server times are synchronized\n3. **This is now logged as INFO** - JWT expiration is normal security behavior\n4. **Fallback to anonymous chat** - System gracefully falls back to anonymous mode\n\n**Quick fixes:**\n\n```bash\n# For development - restart with fresh session\nnpm run dev\n\n# User should log out and back in to get fresh JWTs\n```\n\n## Theming\n\nThemes should be created using the (skeleton UI designer)[https://themes.skeleton.dev/themes/create]. Then you can replace obp-theme.css with your file.\n\n\n## Logging Configuration\n\n### Username Logging for Opey Communication\n\nThe OBP-Portal automatically logs the username from consent JWTs when communicating with Opey. This feature helps with monitoring and debugging by showing which user is making requests to the Opey service.\n\nThe logging includes:\n\n- Function name that created the log entry\n- Username extracted from the consent JWT token (with explicit field identification)\n- Opey session creation details\n- Success/failure status of operations\n\nExample log output:\n\n```\nINFO [2025-08-13T15:03:36.690Z] [INFO] [OBPIntegrationService] getOrCreateOpeyConsent says: Created new consent JWT for user: 91be7e0b-bf6b-4476-8a89-75850a11313b\nINFO [2025-08-13T15:03:36.691Z] [INFO] [OpeyAuthServer] _getAuthenticatedSession says: Sending consent JWT to Opey for user: 91be7e0b-bf6b-4476-8a89-75850a11313b\nINFO [2025-08-13T15:03:36.692Z] [INFO] [OpeyAuthServer] _getAuthenticatedSession says: Making request to http://localhost:5000/create-session with consent for user: 91be7e0b-bf6b-4476-8a89-75850a11313b\nINFO [2025-08-13T15:03:36.720Z] [INFO] [OpeyAuthServer] _getAuthenticatedSession says: Successfully created authenticated Opey session for user: 91be7e0b-bf6b-4476-8a89-75850a11313b\n```\n\n### JWT User Identification Fields\n\nThe system attempts to extract user identifiers from these JWT fields in order (prioritizing human-readable identifiers):\n\n1. `email`\n2. `name`\n3. `preferred_username`\n4. `username`\n5. `user_name`\n6. `login`\n7. `sub`\n8. `user_id`\n\nThe system will log which field was used for user identification:\n\n```\nINFO [timestamp] [INFO] [JWTUtils] extractUsernameFromJWT says: User identifier extracted from JWT field 'email': john.doe@example.com\nINFO [timestamp] [INFO] [JWTUtils] extractUsernameFromJWT says: User identifier extracted from JWT field 'sub': 91be7e0b-bf6b-4476-8a89-75850a11313b\n```\n\n### Function Name Prefixes\n\nAll log messages include the service/function name that generated the log for easier debugging:\n\n- `extractUsernameFromJWT says:` - JWT user identifier extraction logs\n- `getOrCreateOpeyConsent says:` - Consent JWT creation/retrieval logs\n- `_getAuthenticatedSession says:` - Authenticated session creation logs\n- `_getAnonymousSession says:` - Anonymous session creation logs\n- `ConsentSessionService says:` - Session service operation logs\n\n### Development vs Production Logging\n\nWhen no user identifier can be found in the JWT, the system will log all available JWT fields to help with debugging. The system prioritizes human-readable identifiers like email addresses and display names over system identifiers like UUIDs.\n\nMake sure that the `APP_CALLBACK_URL` is registered with the OAuth2/OIDC provider, so that it will properly redirect. Without this the Portal will not work.\n\n## Keycloak Front-Channel Logout Configuration\n\nWhen using Keycloak as your Identity Provider (IdP), the system automatically implements **Option 2: Front-Channel Logout (Browser-based)** for proper session management.\n\n### Configuration Requirements\n\nFor Keycloak logout to work properly, ensure your OAuth client configuration includes:\n\n```javascript\n{\n  clientId: '[SET]',\n  clientSecret: '[SET]',\n  callbackUrl: 'http://localhost:5174/login/obp/callback',\n  configUrl: 'http://localhost:7787/realms/master/.well-known/openid-configuration'\n}\n```\n\n**Note**: The system supports multiple providers simultaneously:\n- **OBP-OIDC**: `http://localhost:9000/obp-oidc/.well-known/openid-configuration`  \n- **Keycloak**: `http://localhost:7787/realms/master/.well-known/openid-configuration`\n\nThe Keycloak front-channel logout will only be used when the user is authenticated via the Keycloak provider.\n\n### How It Works\n\n1. **User clicks logout** in the application\n2. **App redirects browser** to Keycloak's `end_session_endpoint`\n3. **Keycloak ends the session** and logs the user out of all Keycloak-managed clients\n4. **Keycloak redirects back** to the application's origin URL\n\n### Logout Flow Parameters\n\nThe system automatically sends these parameters to Keycloak's logout endpoint:\n\n- `id_token_hint`: The ID token from the user's session (required for proper logout)\n- `post_logout_redirect_uri`: The application origin URL (where to redirect after logout)\n\n### Provider-Specific Behavior\n\n- **Keycloak**: Uses front-channel logout via `end_session_endpoint` with ID token hint\n- **Other providers**: Falls back to standard token revocation via `revocation_endpoint`\n\nThe system automatically detects the provider type and uses the appropriate logout method. No additional configuration is needed beyond ensuring your Keycloak realm has the proper `end_session_endpoint` configured in its OIDC discovery document.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenbankproject%2Fobp-portal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenbankproject%2Fobp-portal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenbankproject%2Fobp-portal/lists"}