Skip to content
Open

OIDC #2829

Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@

> **Migration plan**: see [`LIFT_HTTP4S_MIGRATION.md`](LIFT_HTTP4S_MIGRATION.md) for the full in-place Lift → http4s strategy, file order, auth stack workstream, and progress tracker.

The goal is a full http4s migration — replace Lift Web across all version files and remove it entirely. **API versions are tech-agnostic**: a version bump means a changed/new API signature, never a framework change. Framework migration happens in-place inside the existing version file. v7.0.0 currently serves 45 endpoints; most arrived there for historical reasons and stay as-is.
The goal is a full http4s migration — replace Lift Web across all version files and remove it entirely. **API versions are tech-agnostic**: a version bump means a changed/new API signature, never a framework change. Framework migration happens in-place inside the existing version file. v7.0.0 currently serves 46 endpoints; most arrived there for historical reasons and stay as-is.

**Request priority chain** (`Http4sApp.baseServices`): `corsHandler` (OPTIONS short-circuit) → `AppsPage` → `StatusPage` → `Http4sResourceDocs` → v510 → v600 → v500 → v700 → Berlin Group v2 → UK v2.0 → UK v3.1 → Berlin Group v1.3 (+Alias) → v400 → v310 → v300 → v220 → v210 → v200 → v140 → v130 → v121 → `dynamicEntityRoutes` → `dynamicEndpointRoutes` → DirectLogin → OpenIdConnect → AliveCheck → `notFoundCatchAll` (JSON 404). There is no Lift fallback — `Http4sLiftWebBridge` has been removed. Any unhandled `/obp/*` path returns a JSON 404 from `notFoundCatchAll`; it does not fall through to Lift.

**Key files**: `Http4s700.scala` (v7.0.0 endpoints), `Http4s200.scala` (v2.0.0 endpoints — 37 own + path-rewriting bridge to Http4s140), `Http4s140.scala` (v1.4.0 endpoints — 11 own + path-rewriting bridge to Http4s130), `Http4s130.scala` (v1.3.0 endpoints — 3 own + path-rewriting bridge to Http4s121), `Http4s121.scala` (v1.2.1 endpoints — all 323 API1_2_1Test scenarios), `Http4sSupport.scala` (EndpointHelpers + recordMetric), `ResourceDocMiddleware.scala` (auth, entity resolution, transaction wrapper), `IdempotencyMiddleware.scala` (Redis-backed idempotency, opt-in via `Idempotency-Key` header, nested inside ResourceDocMiddleware), `RequestScopeConnection.scala` (DB transaction propagation to Futures).

**v7.0.0 native endpoints** (45 ResourceDocs): root, corePrivateAccountsAllBanks, deleteEntitlement, addEntitlement, getAccountAccessTrace, getConsentsConfig, getErrorMessages, getUserByUserId, createTradingOffer, getTradingOffer, getTradingOffers, cancelTradingOffer, createMarketOrder, getMarketOrder, cancelMarketOrder, createMarketMatch, getMarketTrade, requestSettlement, notifyDeposit, requestWithdrawal, createPaymentAuth, capturePaymentAuth, releasePaymentAuth, getPaymentAuth, createTestEmail, createValidationEmail, createOrganisation, getOrganisations, getOrganisation, updateOrganisation, deleteOrganisation, createRoutingScheme, getRoutingSchemes, getRoutingScheme, updateRoutingScheme, deleteRoutingScheme, getBankSupportedRoutingSchemes, putBankSupportedRoutingScheme, createPayeeLookup, createTransactionRequestMobileWallet, createTransactionRequestOpenCorridor, createTransactionRequestBulk, factoryResetSystemView. These carry genuinely v7-specific signatures/behaviour. The 20 duplicate "POC" endpoints originally added as migration scaffolding (getBanks, getBank, getCurrentUser, getCoreAccountById, getPrivateAccountByIdFull, getExplicitCounterpartyById, getFeatures, getScannedApiVersions, getConnectors, getProviders, getUsers, getCustomersAtOneBank, getCustomerByCustomerId, getAccountsAtBank, getCacheConfig, getCacheInfo, getDatabasePoolInfo, getStoredProcedureConnectorHealth, getMigrations, getCacheNamespaces) were **removed** — they cascade to their v6 twin via `v700ToV600Bridge` (getExplicitCounterpartyById → v4, no v6/v5 twin), `X-OBP-Version-Served: v6.0.0`. Kept deliberately in v7: `deleteEntitlement` (204), `addEntitlement` (409), `getUserByUserId` (404) — intentional RESTful response-code improvements over the older v6 200/400 convention.
**v7.0.0 native endpoints** (46 ResourceDocs): root, corePrivateAccountsAllBanks, deleteEntitlement, addEntitlement, getAccountAccessTrace, getConsentsConfig, getErrorMessages, getUserByUserId, createTradingOffer, getTradingOffer, getTradingOffers, cancelTradingOffer, createMarketOrder, getMarketOrder, cancelMarketOrder, createMarketMatch, getMarketTrade, requestSettlement, notifyDeposit, requestWithdrawal, createPaymentAuth, capturePaymentAuth, releasePaymentAuth, getPaymentAuth, createTestEmail, createValidationEmail, createOrganisation, getOrganisations, getOrganisation, updateOrganisation, deleteOrganisation, createRoutingScheme, getRoutingSchemes, getRoutingScheme, updateRoutingScheme, deleteRoutingScheme, getBankSupportedRoutingSchemes, putBankSupportedRoutingScheme, createPayeeLookup, createTransactionRequestMobileWallet, createTransactionRequestUtility, createTransactionRequestOpenCorridor, createTransactionRequestBulk, factoryResetSystemView. These carry genuinely v7-specific signatures/behaviour. The 20 duplicate "POC" endpoints originally added as migration scaffolding (getBanks, getBank, getCurrentUser, getCoreAccountById, getPrivateAccountByIdFull, getExplicitCounterpartyById, getFeatures, getScannedApiVersions, getConnectors, getProviders, getUsers, getCustomersAtOneBank, getCustomerByCustomerId, getAccountsAtBank, getCacheConfig, getCacheInfo, getDatabasePoolInfo, getStoredProcedureConnectorHealth, getMigrations, getCacheNamespaces) were **removed** — they cascade to their v6 twin via `v700ToV600Bridge` (getExplicitCounterpartyById → v4, no v6/v5 twin), `X-OBP-Version-Served: v6.0.0`. Kept deliberately in v7: `deleteEntitlement` (204), `addEntitlement` (409), `getUserByUserId` (404) — intentional RESTful response-code improvements over the older v6 200/400 convention.

**Tests**: `Http4s700RoutesTest` (86 scenarios, port 8087). `makeHttpRequest` returns `(Int, JValue, Map[String, String])`. `makeHttpRequestWithBody(method, path, body, headers)` for POST/PUT.
**Tests**: `Http4s700RoutesTest` (91 scenarios, port 8087). `makeHttpRequest` returns `(Int, JValue, Map[String, String])`. `makeHttpRequestWithBody(method, path, body, headers)` for POST/PUT.
## Migrating a Lift Endpoint to http4s

Rules apply regardless of which version file the endpoint lives in. Use v7.0.0 only when the API signature is new or changed; otherwise migrate in-place in the original version file.
Expand Down
63 changes: 6 additions & 57 deletions obp-api/src/main/resources/props/sample.props.template
Original file line number Diff line number Diff line change
Expand Up @@ -806,51 +806,12 @@ super_admin_user_ids=USER_ID1,USER_ID2,
##########################


## Open Id Connect (OIDC) can be used to retrieve User information from an
## external OpenID Connect server.
## This will enable authentication of an external user stored in an external db,
## and will create a local OBP resource user in the OBP DB.
## To use an external OpenID Connect server,
## you will need to change these values.
## The following values provided for a temp test account.
## CallbackURL 127.0.0.1:8080 should work in most cases.
## Note: The email address used for login must match one
## registered on OBP localy.
# openid_connect.enabled=false
# CONFIG CAVEAT: portal-login was removed, so there is no server-side session state to compare.
# The code default is true (fail-closed) and will reject every real (non-empty) state with 401 —
# OIDC deployments MUST set this to false (or reintroduce state storage):
# openid_connect.check_session_state=false
# openid_connect.show_tokens=false
# Response mode
# possible values: query, fragment, form_post, query.jwt, fragment.jwt, form_post.jwt, jwt
# openid_connect.response_mode=form_post
# Response type
# possible values: "code", "id_token", "code id_token"
# openid_connect.response_type=code
# Scope
# possible values: "openid email profile", "openid email", "openid"
# openid_connect.scope=openid email profile
# First identity provider
# openid_connect_1.button_text = Google
# openid_connect_1.client_secret=OYdWujJlU7fFOW_NXzPlDI4T
# openid_connect_1.client_id=883773244832-s4hi72j0rble0iiivq1gn09k7vvptdci.apps.googleusercontent.com
# openid_connect_1.callback_url=http://127.0.0.1:8080/auth/openid-connect/callback
# openid_connect_1.endpoint.authorization=https://accounts.google.com/o/oauth2/v2/auth
# openid_connect_1.endpoint.userinfo=https://openidconnect.googleapis.com/v1/userinfo
# openid_connect_1.endpoint.token=https://oauth2.googleapis.com/token
# openid_connect_1.endpoint.jwks_uri=https://www.googleapis.com/oauth2/v3/certs
# openid_connect_1.access_type_offline=true
## Second identity provder
# openid_connect_2.button_text = name of 2nd provider
# openid_connect_2.client_secret=OYdWujJlU7fFOW_NXzPlDI4T
# openid_connect_2.client_id=883773244832-s4hi72j0rble0iiivq1gn09k7vvptdci.apps.googleusercontent.com
# openid_connect_2.callback_url=http://127.0.0.1:8080/auth/openid-connect/callback-2
# openid_connect_2.endpoint.authorization=https://accounts.google.com/o/oauth2/v2/auth
# openid_connect_2.endpoint.userinfo=https://openidconnect.googleapis.com/v1/userinfo
# openid_connect_2.endpoint.token=https://oauth2.googleapis.com/token
# openid_connect_2.endpoint.jwks_uri=https://www.googleapis.com/oauth2/v3/certs
# openid_connect_2.access_type_offline=false
# NOTE: OBP-API is a pure OAuth2 *resource server*. The OIDC relying-party login
# callback (/auth/openid-connect/callback{,-1,-2}) and its openid_connect.* /
# openid_connect_$n.* props were removed — the client/BFF runs the OIDC login
# against the provider and calls OBP with `Authorization: Bearer <jwt>`.
# Configure Bearer-JWT validation via the oauth2.* props further below
# (oauth2.jwk_set.url, oauth2.keycloak.*, oauth2.obp_oidc.*).

# When new consumers inserted they should use this setting.
consumers_enabled_by_default=true
Expand Down Expand Up @@ -1320,18 +1281,6 @@ outboundAdapterCallContext.generalContext
## This should include the JWKS URI for OBP-OIDC provider
## Multiple JWKS URIs can be comma-separated
#oauth2.jwk_set.url=http://localhost:9000/obp-oidc/jwks

## OpenID Connect Client Configuration for OBP-OIDC
#openid_connect_1.button_text=OBP-OIDC
#openid_connect_1.client_id=obp-api-client
#openid_connect_1.client_secret=your-client-secret-here
#openid_connect_1.callback_url=http://localhost:8080/auth/openid-connect/callback
#openid_connect_1.endpoint.discovery=http://localhost:9000/obp-oidc/.well-known/openid-configuration
#openid_connect_1.endpoint.authorization=http://localhost:9000/obp-oidc/auth
#openid_connect_1.endpoint.userinfo=http://localhost:9000/obp-oidc/userinfo
#openid_connect_1.endpoint.token=http://localhost:9000/obp-oidc/token
#openid_connect_1.endpoint.jwks_uri=http://localhost:9000/obp-oidc/jwks
#openid_connect_1.access_type_offline=true
# ------------------------------ OBP-OIDC oauth2 props end ------------------------------

# ------------------------------ default entitlements ------------------------------
Expand Down
16 changes: 9 additions & 7 deletions obp-api/src/main/scala/bootstrap/liftweb/Boot.scala
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ import code.group.Group
import code.organisation.Organisation
import code.routingscheme.{RoutingScheme, BankSupportedRoutingScheme}
import code.payeelookup.PayeeLookup
import code.utilitypayment.UtilityPaymentCallback
import code.bulkpayment.{BulkPayment, BulkBatchReference}
import code.kycchecks.MappedKycCheck
import code.kycdocuments.MappedKycDocument
Expand Down Expand Up @@ -281,7 +282,7 @@ class Boot extends MdcLoggable {
// Please note that migration scripts are executed after Lift Mapper Schemifier
Migration.database.executeScripts(startedBeforeSchemifier = false)

// Idempotent seed of country-qualified routing schemes (TZ.MSISDN, GePG, Luku, etc.).
// Idempotent seed of country-qualified routing schemes (TZ.MSISDN, bill, utility, etc.).
// Toggle off via routing_schemes.seed_defaults_at_boot=false in environments that don't want defaults.
code.routingscheme.RoutingSchemeSeed.runIfEnabled()

Expand Down Expand Up @@ -479,12 +480,12 @@ class Boot extends MdcLoggable {
enableVersionIfAllowed(ApiVersion.`dynamic-endpoint`)
enableVersionIfAllowed(ApiVersion.`dynamic-entity`)

// OpenID Connect callbacks (/auth/openid-connect/callback{,-1,-2}), DirectLogin
// (POST /my/logins/direct) and aliveCheck (GET /alive) are now served by their
// native http4s counterparts wired into Http4sApp.baseServices
// (Http4sOpenIdConnect / DirectLoginRoutes / AliveCheckRoutes). The Lift
// dispatches were retired in the http4s migration; any prop gates
// (e.g. `openid_connect.enabled`, `allow_direct_login`) live with those routes.
// DirectLogin (POST /my/logins/direct) and aliveCheck (GET /alive) are now served
// by their native http4s counterparts wired into Http4sApp.baseServices
// (DirectLoginRoutes / AliveCheckRoutes). The Lift dispatches were retired in the
// http4s migration; any prop gates (e.g. `allow_direct_login`) live with those
// routes. The OBP-as-relying-party OpenID Connect callback was removed: OBP is a
// pure OAuth2 resource server (Bearer-JWT validation), login is done by the client/BFF.

//////////////////////////////////////////////////////////////////////////////////////////////////
// Resource Docs are used in the process of surfacing endpoints so we enable them explicitly
Expand Down Expand Up @@ -1029,6 +1030,7 @@ object ToSchemify extends MdcLoggable {
RoutingScheme,
BankSupportedRoutingScheme,
PayeeLookup,
UtilityPaymentCallback,
BulkPayment,
BulkBatchReference,
AccountAccessRequest,
Expand Down
Loading
Loading