Skip to content

[PHEE-371] Add migrated identity-provider as paymenthub-ee-auth (Java 21 / SB 3.4 / Jakarta) - #1

Merged
tdaly61 merged 6 commits into
openMF:devfrom
GiulioRinalduzzi:feat/add-auth-identity-provider
Aug 21, 2026
Merged

tdaly61 merged 6 commits into
openMF:devfrom
GiulioRinalduzzi:feat/add-auth-identity-provider

Conversation

@GiulioRinalduzzi

@GiulioRinalduzzi GiulioRinalduzzi commented Aug 10, 2026 •

Copy link
Copy Markdown
Contributor

The auth service, migrated from openMF/ph-ee-identity-provider. This one had not been touched since 2020: Spring Boot 1.5.22, Java 8, Maven, and an OAuth2 authorization server built on a library that no longer exists.

before after
build Maven Gradle 8.10.2
Java 8 21
Spring Boot 1.5.22 3.4.4 (from the BOM)
auth spring-security-oauth2 2.4.1 + spring-security-jwt Spring Security 6
JPA provider EclipseLink 2.7.6 4.0.4
Flyway 2.1.1 (com.googlecode.flyway) 10
cache Ehcache 2 Caffeine
Spring Data 1.x 3.x

Every version comes from org.mifos:paymenthub-ee-bom. None are pinned by hand.

Maven to Gradle, as done for ph-ee-exporter: the shared PHEE CircleCI template runs ./gradlew and the coming mifos-gradle-conventions plugins are Gradle only. The pom had to be rewritten from scratch either way, since Spring Boot 1.5 to 3.4 changes every dependency, so there was no small-diff option to preserve.

The part worth a careful read: the authorization server

spring-security-oauth2 2.4.1 and spring-security-jwt were discontinued and have no Spring Boot 3 version. Their official successor, spring-authorization-server, dropped the password grant, which is what this service exists to serve. So the three endpoints are re-implemented by hand in TokenController, keeping the same external contract:

  • the same three grants: password, refresh_token, client_credentials
  • clients and their token lifetimes still read from the oauth_client_details table of the current tenant, the same rows the old JdbcClientDetailsService read
  • the same RSA-signed JWTs from the same jwt.pem / jwt_pub.pem, with the same claims (user_name, authorities, aud, scope, jti, client_id)
  • the same success body and the same 401 body

This is not new code invented here: it is the same replacement already written for ph-ee-operations-app, which validates the tokens this service issues, so the two agree claim by claim.

Two behaviours were deliberately re-implemented rather than left to fall out:

  • A refresh token must not work as an access token. Both are signed with the same key and a refresh token carries no authorities claim, so without an explicit check one can be sent as a bearer token and authenticates with an empty authority list, for the whole refresh lifetime instead of the 10-minute access lifetime. There is a validator and a unit test for it.
  • A refresh token must belong to the client presenting it, as the old DefaultTokenServices checked ("Wrong client for this refresh token").

AudienceVerifier moved from the old JwtClaimsSetVerifier to OAuth2TokenValidator. PemUtils replaces the PEM parsing spring-security-jwt did: jwt.pem is legacy PKCS#1, which the JDK cannot read directly, so it is wrapped into PKCS#8 in memory. No key file changed.

Four bugs only a running instance found

  1. Every valid token got a 401 on every protected endpoint. The tenant filter has to run before Spring Security so the audience check has a tenant to compare against. The old code arranged that with security.filter-order=5; Spring Boot 3 renamed the key to spring.security.filter.order and changed the default to -100, so the old key was silently ignored and the security chain ran first.

  2. A missing Platform-TenantId returned 401 instead of 400. Spring Security also filters the ERROR dispatch, so the sendError(400) from the tenant filter was authorized again on /error, where there is no authentication. Fixed by making /error permitAll.

  3. Every cross-origin call would have failed. Since Spring 5.3 the literal "*" origin together with allowCredentials(true) is rejected at request time. Under Spring 4.3, which the old app ran, it was permitted and reflected the origin, so addAllowedOriginPattern("*") restores the deployed behaviour rather than widening it.

  4. The application did not start at all, and only excluding hibernate-core made it happen. GroupRepository has @Query("select g.submittedOnDate from Group g ..."). Spring Data JPA 3.x parses every @Query at startup and picks its parser from the classpath: with Hibernate present it uses the lenient HQL one, without it the strict EQL grammar, where GROUP is a reserved word. Excluding hibernate-core from the data-jpa starter is right on its own merits — two JPA providers in one deployable jar — but it also flips that switch, so the context failed with Bad EQL grammar before opening a single connection. Group is now @Entity(name = "GroupEntity"), which changes the name used in JPQL and nothing else: same m_group table, same Java type. Note for the other repos: the trigger is any entity whose class name is a JPQL keyword, so it is worth a look wherever the same starter exclusion is applied.

Also: asking for a grant type the client is not allowed to use returned 401 where the old stack returned 400, so that path now throws a non-authentication exception and comes out as 400.

One thing that looks wrong in TokenController and is not: the final catch (Exception) answers 400, not 500, even for a server-side failure like the database being down. That is what the old code did. AuthExceptionTranslator was if (e instanceof InvalidGrantException) 401 else 400, with no branch for anything else, so every non-credential failure already came out as 400. The only difference is the body: the old one returned 400 empty, this one returns {"error": "invalid_request"}.

Flyway 2.1.1 to 10

Flyway 2.x kept its history in schema_version; Flyway 10 uses flyway_schema_history with a different layout, can read the old table but cannot write to it, and dropped the self-conversion it had up to version 4. So FlywayHistoryTableUpgrade (shared with operations-app) converts it once before migrate(), keeping the old table as a backup. It does nothing on a fresh database and nothing if it has already run.

Verified

23 unit tests, green, up from one empty test method.

8 of them cover the two things most likely to break silently on their own: the hand-written PKCS#1 to PKCS#8 key wrapping (a sign-then-verify round trip, which every token depends on) and the token validators.

The other 15 drive /oauth/token through MockMvc, with the database and the authentication manager stubbed but the real encoder and decoder from ResourceServerConfig reading the real jwt.pem - so the tokens under test are the tokens the service issues. They pin the parts that are easy to break and expensive to get wrong: the 400/401 split (a client that cannot authenticate gets 401, a grant type it may not use gets 400, as AuthExceptionTranslator did), the 401 body callers parse, the claims of an access token, and the four checks the refresh grant has to make for itself - the token belongs to the client presenting it, it really is a refresh token, the user still exists, the user is still enabled.

Those four were mutation-checked - each check broken on purpose to see the suite go red. Two tests did not survive it: with the client-binding check removed, and with the refresh-claim check removed, they still passed, because the request was refused a step later when the stubbed user lookup returned null. They were green for the wrong reason. Both now stub an enabled user, so the only thing that can produce the 401 is the check under test.

30/30 HTTP checks against MySQL 5.7, on three real tenant schemas:

group checks
token endpoint password grant; wrong password 401; unknown user 401; refresh grant; access token offered as a refresh token 401; client_credentials; unknown client 401; no client auth 401; grant not allowed for the client 400; client_id via Basic header
the other two endpoints token_key open with no tenant header; check_token authenticated 200, unauthenticated 401
/api/v1 users, roles, permissions with a token 200; no token 401; refresh token as bearer 401; client_credentials token without ALL_FUNCTIONS 403; garbage token 401; no tenant header 400; user/1 200; user/999 404; user/1/roles 200; transactions paged and sorted 200
tenant isolation two real tenants: each token works on its own tenant and is refused on the other, with the rejection logged
Flyway conversion built a real Flyway 2.1.1 schema_version table (28 rows, type='INIT', version_rank column), then restarted: converted to flyway_schema_history, 28 rows intact, backup kept, repair() ran once, no migration re-applied, tokens still issued. A second restart did not convert or repair again

Re-run on the final build after bug 4 above, on an empty MySQL 5.7.44 with hibernate-core excluded, so these numbers describe the commit as it stands and not an earlier classpath: startup clean, Flyway applying 1 migration to tenants and 28 to each of tn01 and tn02, then the token endpoint (all three grants), /api/v1 users, roles and permissions, check_token, token_key, and the refusals — refresh token as bearer, cross-tenant token, cross-tenant refresh redemption, missing tenant header, grant not allowed for the client.

Token claims checked by decoding a real token: aud: [identity-provider, tn01], authorities: [ALL_FUNCTIONS], user_name, scope, jti, client_id, exp, iat, the same set the old JwtAccessTokenConverter produced.

Known items, flagged not fixed

  • The JWT signing key is in the repo. src/main/resources/jwt.pem is the RSA private key every token is signed with, and it is committed, as it was in ph-ee-identity-provider. Nothing changed here and no key file was touched, but this repo is public, so anyone can mint a token with aud: [identity-provider, <tenant>] and authorities: [ALL_FUNCTIONS] against any deployment still running the default key. Together with the client row that V27__oauth_changes.sql seeds with no client_secret (checkClientSecret returns early on an empty stored secret, as JdbcClientDetailsService did), the password grant needs only client_id=client plus user credentials. Both predate the migration and are kept as they were, but this has to be settled before the service is deployed: the key belongs in a mounted secret, not on the classpath. PemUtils reads from ClassPathResource only, so that change lands there.

  • The Flyway migrations collide with ph-ee-operations-app, and the core schema is the worse half. Both services ship migrations for the same schemas with overlapping version numbers: on the tenant schemas 27 numbers overlap with different scripts, offset by one (V27 is oauth_changes here and add_refund_permission there), and on the core schema tenant_server_connections is V1 here and V2 there. Flyway keys a migration by version, so the second service to run replays a migration it thinks is pending. The two halves fail differently, and the difference matters: on a tenant schema flywayTenants() catches per tenant and only logs, so that tenant comes up with an unknown migration state; on the core schema flywayDefaultSchema() lets the exception escape, so the application does not start at all - Table 'tenant_server_connections' already exists, reproduced against a MySQL shaped like gazelle3.

    This predates the migration: rerunning com.googlecode.flyway:flyway-core:2.1.1, the version from the old pom, with the old migrations against the same schema fails identically, so ph-ee-identity-provider was never deployable there either - it has simply never been pointed at those schemas. It is also not a MySQL problem: on an empty PostgreSQL 16 the same two migrations collide the same way, so moving the platform to Postgres would not settle it by itself.

    The second commit here adds the switch that was missing rather than renumbering anything. The tenant schemas already had one, per tenant, in the auto_update column; the core schema had none. fineract.datasource.core.auto-update defaults to true, so a deployment with a database of its own builds it exactly as before; set to false the service reads a schema it does not own and writes nothing to it - verified on a gazelle-shaped MySQL, where it starts, issues tokens, serves /api/v1/users, and leaves both schema_version tables untouched with no flyway_schema_history created. For whoever writes the chart: both FINERACT_DATASOURCE_CORE_AUTOUPDATE and FINERACT_DATASOURCE_CORE_AUTO_UPDATE bind to it as environment variables - I checked both, since getting the name wrong would leave the flag at its default and the pod would fail to start.

    This unblocks the deployment, it does not resolve the collision. The numbers still overlap and the ownership question is still open: one owner for the migrations of the shared schemas - ph-ee-operations-app is the natural one, it is deployed and it already ships everything this service reads - or separate schemas, which would defeat a shared user store. Worth settling as part of the Postgres move, when the migrations have to be rewritten anyway.

  • GET /api/v1/users and /api/v1/user/{id} return the bcrypt password hash. AppUser has @JsonIgnore on getAuthorities() and getOffice() but not on getPassword(), so the hash of every user goes out to any caller holding ALL_FUNCTIONS. Inherited - nothing in this PR changes the serialization, and the same is true on ph-ee-identity-provider - but it is one annotation and it belongs in its own commit rather than in a migration.

  • No actuator, so no /actuator/health. The old app had none and I did not add one, to keep baseline parity. If this is deployed on kubernetes the probes will need it.

  • Verified locally only. ph-ee-identity-provider is not referenced in gazelle or in ph-ee-env-template, so there is no environment to verify against. Everything above is a real MySQL and a real HTTP client, but not a real deployment.

  • @Cacheable on loadUserByUsername is keyed on the username alone, in a service where the same username exists in every tenant. Turning caching.enabled on would let mifos on tn01 and mifos on tn02 share one entry for 10 seconds: wrong password hash, wrong authorities, across tenants. It is inert today (caching.enabled=false, and CacheConfig is @ConditionalOnExpression) and it is inherited, so it is left alone here, but it is a cross-tenant bug sitting behind a boolean. The fix is a cache key including the tenant schema.

  • token.access.validity-seconds and token.refresh.validity-seconds look like runtime settings but are not. They are Flyway placeholders consumed by V27__oauth_changes.sql when it seeds oauth_client_details. On a tenant where V27 has already run, changing them does nothing; the lifetimes live in the table from then on.

  • CORS reflects any Origin with credentials. Pre-existing and restored rather than introduced (see bug 3 above); worth an explicit origin allow-list in its own change.

  • Dead code kept out. There are org.apache.fineract.organisation.* classes (documents, groups, staff, offices, leftovers from the Fineract fork) that look unreferenced. Removing them is a separate commit after this merges, as agreed for notifications.

  • joda-time stays for the LocalDate fields of four read-only DTOs; swapping it for java.time is a code change, not a version change.

  • Package names stay org.apache.fineract.*, per the separate ticket.

Two questions

  1. Maven to Gradle: done on the exporter precedent. Confirm it is what you want for the remaining Maven repos (pch-java, the two nats ones).
  2. Is this service going to be deployed? The repo exists so I assume yes, but it is in no chart today and the console has moved to Keycloak auth (PHEE-381). The answer decides how much the health endpoint and the shared-schema question above are worth.

Scaffold docs

The last commit applies the org-wide scaffold docs from ph-ee-start-here (CODE_OF_CONDUCT.md, contributing.md replacing CONTRIBUTING.md, a new security.md), with the seven clone/fork/remote URLs pointing at this repo, and fixes the README line that linked CONTRIBUTING.md: blob paths on GitHub are case sensitive, so after the rename that link 404s (checked, not assumed). LICENSE is left alone; its only difference from the source copy is line 360, https:// here against http:// there, so that fix belongs in ph-ee-start-here.

@GiulioRinalduzzi
GiulioRinalduzzi force-pushed the feat/add-auth-identity-provider branch 3 times, most recently from 9bf9bda to dd55863 Compare August 10, 2026 14:32
… 21 / SB 3.4 / Jakarta)

The auth service, migrated from openMF/ph-ee-identity-provider. It had not been
touched since 2020: Spring Boot 1.5.22, Java 8, Maven, and an OAuth2 authorization
server built on a library that no longer exists.

Spring Boot 1.5.22 -> 3.4.4, Java 8 -> 21, javax.* -> jakarta.* in 29 files,
EclipseLink 2.7.6 -> 4.0.4, Flyway 2.1.1 -> 10, Ehcache 2 -> Caffeine, Spring Data
1.x -> 3.x. Every version comes from org.mifos:paymenthub-ee-bom; none are pinned by
hand.

Maven -> Gradle, as done for ph-ee-exporter: the shared PHEE CircleCI template runs
./gradlew and the coming mifos-gradle-conventions plugins are Gradle only. The pom
had to be rewritten from scratch either way. Its exclusion of hibernate-core from
spring-boot-starter-data-jpa is kept: EclipseLink is the JPA provider here, and
without it Hibernate 6.6 ships alongside it in the same jar. jakarta.transaction-api
is now declared directly, because GroupRepository imports it and Spring Boot 1.5 was
the last version whose data-jpa starter brought it in by itself.

The bulk of the work is the authorization server, rebuilt on Spring Security 6.
spring-security-oauth2 2.4.1 and spring-security-jwt were discontinued and have no
Spring Boot 3 version, and their successor dropped the password grant this service
exists to serve. So /oauth/token, /oauth/token_key and /oauth/check_token are
re-implemented in TokenController with the same external contract: the same three
grants, clients still read from oauth_client_details, the same RSA-signed JWTs with
the same claims, and the same success and 401 bodies. This is the same replacement
already written for ph-ee-operations-app, which validates these tokens, so the two
agree claim by claim. AudienceVerifier moved from JwtClaimsSetVerifier to
OAuth2TokenValidator, and PemUtils replaces the PEM parsing spring-security-jwt did.

Bugs that only a running instance, or a second read, found:
- spring.security.filter.order has to stay set. Spring Boot 3 renamed the key and
  made the default -100, which put the security chain before the tenant filter, so
  the audience check ran with no tenant and every valid token came back 401.
- /error is permitAll: Spring Security also filters the ERROR dispatch, so the 400
  the tenant filter sends for a missing Platform-TenantId was re-authorized there and
  became a 401.
- CORS: the literal "*" origin with allowCredentials(true) has been rejected since
  Spring 5.3, so addAllowedOriginPattern. Under Spring 4.3 the old code worked and
  reflected the origin, so this restores the deployed behaviour.
- /oauth/token and /oauth/token_key each get a security chain with no resource
  server on it. The bearer filter validates a token whenever the caller sends one,
  permitAll or not, and it stops the chain when that fails - so a client refreshing
  an expired access token, with that token still in the Authorization header, got a
  401 from the endpoint that exists to recover from the expiry. The old
  @EnableAuthorizationServer kept these endpoints on their own chain, which had no
  bearer filter at all.
- A Basic header that is not valid base64 raises IllegalArgumentException from the
  decoder, which was being answered with 400. It is a failed client authentication,
  so it answers 401 like the missing-colon case next to it.

Flyway 10 cannot write to a Flyway 2.x schema_version table, so
FlywayHistoryTableUpgrade converts it once before migrate(). It COPIES that table and
never renames or drops it: this application is not always the only user of a schema -
ph-ee-operations-app owns the history of the tenant schemas and still runs a Flyway 2
build - so schema_version can be another service's live table rather than a leftover.
Copying also makes the conversion reversible. See the class comment for what this
does not solve: the migration numbers themselves still overlap with operations-app,
which predates this change and needs one owner for the tenant migrations.

Cleanup from the reviews on the merged paymenthub-ee-* PRs: Jenkinsfile and
docker-compose.yml removed (the latter pointed at the retired Azure registry and
passed no profile, so it could not start), dead logback FILE appender removed, empty
TestSomething removed, CircleCI added on JDK 21 (the repo had none), Dockerfile on
eclipse-temurin:21-jre with a pinned app.jar and exec-form CMD. The
application-large/med/bb.properties profiles are all kept: they are the only source
of the tenants property, so dropping one makes that profile fail to start.

Tests: 8 unit tests, up from one empty one. They cover the RSA key loading - the
hand-written PKCS#1 to PKCS#8 wrapping every token depends on - and the token
validators, including that a refresh token is refused as an access token.

Client credentials can be sent as request parameters here, which the old stack did
not allow (it never called allowFormAuthenticationForClients, so /oauth/token sat
behind BasicAuthenticationFilter). It is kept - ph-ee-operations-app carries the
same replacement and accepts it, and it widens nothing by itself - but it does mean
client_secret can now be a request parameter, and PlatformRequestLog logs the
parameter map. It is dropped there, next to password, so it is not written in clear
at INFO on every token request. resolveClientCredentials says the same thing for
whoever reads it next.
@GiulioRinalduzzi
GiulioRinalduzzi force-pushed the feat/add-auth-identity-provider branch from dd55863 to ab7a6b6 Compare August 10, 2026 15:09
The tenant schemas already had this switch, one per tenant, in the auto_update
column that flywayTenants() reads. The core schema had none, and it is the one
that cannot recover: ph-ee-operations-app ships tenant_server_connections as V2
and this repository ships it as V1, so on a shared schema Flyway replays it out
of order, the CREATE TABLE fails on a table that is already there, and
flywayDefaultSchema() lets the exception escape - the application does not start.
The same collision on a tenant schema is caught per tenant and only logged.

fineract.datasource.core.auto-update, default true, so a deployment with a
database of its own builds it exactly as before. Off, the service reads a schema
it does not own: no migrations and no tenant registration, both of which write to
the core schema. Everything it needs is already there in that case - m_appuser,
m_role, m_permission and oauth_client_details all come from the owner.

This does not renumber anything and does not decide who owns the migrations. It
makes that decision expressible: without it there is no configuration in which
this service starts against the core schema on gazelle.

Verified against a MySQL 5.7 shaped like gazelle3 - core history holding
V2__tenant-server-connections.sql, tenant history holding another service's
migrations, auto_update 0 on the tenant row. With the flag on it fails to start
with "Table 'tenant_server_connections' already exists", which is the bug. With
it off the application starts, issues tokens and serves /api/v1/users for that
tenant, and neither schema is touched: no flyway_schema_history is created and
both legacy schema_version tables are left exactly as they were.
TokenController re-implements by hand what spring-security-oauth2 used to do, so
nothing outside this repository pins its behaviour any more. It had no test: the
8 that existed cover PemUtils and the two validators, which are pure functions,
and the endpoint itself was only ever checked by hand over HTTP. Every bug listed
in the PR was found by running an instance, which is the argument for this.

15 tests through MockMvc, database and authentication manager stubbed, but the
encoder and decoder are the real ones from ResourceServerConfig reading the real
jwt.pem - the tokens here are the tokens the service issues. They pin what is
easy to break and expensive to get wrong: the 400/401 split (a client that cannot
authenticate gets 401, a grant type it may not use gets 400, as AuthExceptionTranslator
did), the 401 body callers parse, the claims of an access token, and the four
checks the refresh grant has to make for itself - the token belongs to the client
presenting it, it really is a refresh token, the user still exists, the user is
still enabled.

Each of those four was mutation-checked, and two of the tests did not survive it:
with the client-binding check removed, and with the refresh-claim check removed,
they still passed - the request was refused a step later because the stubbed user
lookup returned null, so they were green for the wrong reason. Both now stub an
enabled user, so the only thing that can produce the 401 is the check under test.

spring-boot-starter-test replaces the bare junit-jupiter dependency: JUnit 5,
Mockito and spring-test, all versions from the BOM.
The switch only covered the core schema. Run against the real gazelle database with
just that half skipped, Flyway finds a tenant schema of 255 tables with no history
of its own, BASELINES it - creating a flyway_schema_history inside a schema owned by
another service - then tries to apply V2 on tables that already exist and fails.
What it leaves behind is a history table containing a failed row, which blocks
Flyway for whoever does own that schema until someone runs repair() by hand. The
per-tenant loop catches and only logs, so the service starts, the pod goes green,
and the damage is one ERROR line in the log.

The tenant schemas do have their own switch, the auto_update column, but it cannot
carry this: it defaults to 1 - it is 1 for both tenants on gazelle - and it lives in
tenant_server_connections, a table in the core schema this service does not own, so
setting it to 0 means writing into the very schema we are trying not to touch.

So one property now means one thing: either this service builds its own database, or
it applies no migration anywhere and reads what the owner put there.

Found by restoring the real gazelle dump (mifos-gazelle/config) instead of a
reconstruction, which is also what turned up the numbers above: with the switch on,
startup fails on the real tenants schema exactly as predicted, its single history row
being V2__tenant-server-connections.sql. With the switch on both halves, the
application starts and greenbank stays at 255 tables with no flyway_schema_history,
bluebank stays empty, and tenants.schema_version is untouched.
David asked for these files to be the same across every new repo. Taken from
ph-ee-start-here, with the repo-specific lines kept pointing at this repo.

  CODE_OF_CONDUCT.md   replaced
  contributing.md      replaces CONTRIBUTING.md
  security.md          new, was missing
  README.md            one link fixed, see below

The seven clone/fork/remote URLs in contributing.md say
paymenthub-ee-auth, not ph-ee-start-here. Everything else is
byte-identical to the source.

The CONTRIBUTING.md being replaced is the generic Mifos template: it points
contributors at Jira project MXWAR and MXWAR-<ID> branch names, and still carries
two unfilled placeholders. The new version is the Payment Hub one, pointing at
PHEE and #payment-hub.

The rename breaks a link in README.md, which said
"See [CONTRIBUTING.md](CONTRIBUTING.md)". Blob paths on GitHub are case
sensitive, so with the file now called contributing.md that link gives a 404
(checked, not assumed). The line points at the new name and, while there, at the
new security policy, so all three documents are reachable from the README.

LICENSE is left alone. The only difference from the source copy is line 360:
this repo has https://mozilla.org/MPL/2.0/ and ph-ee-start-here has http://.
Applying it would swap a secure link for a plain one, so the fix belongs in
ph-ee-start-here instead.
@GiulioRinalduzzi
GiulioRinalduzzi force-pushed the feat/add-auth-identity-provider branch from 37cc4cd to 22b0c1a Compare August 13, 2026 21:45

@tdaly61 tdaly61 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GiulioRinalduzzi , can you file tickets for the security items please , let me know when you have and I will approve ..but I don't want to loose what you have noted.

@GiulioRinalduzzi

Copy link
Copy Markdown
Contributor Author

Ticket created: PHEE-405

@tdaly61 tdaly61 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See PHEE-405 for future actions required and well flagged by Giulio in this PR

@tdaly61
tdaly61 requested a review from a team August 21, 2026 07:21
@tdaly61
tdaly61 merged commit b403fa8 into openMF:dev Aug 21, 2026
1 check passed
@GiulioRinalduzzi GiulioRinalduzzi changed the title [PHEE-370] Add migrated identity-provider as paymenthub-ee-auth (Java 21 / SB 3.4 / Jakarta) [PHEE-371] Add migrated identity-provider as paymenthub-ee-auth (Java 21 / SB 3.4 / Jakarta) Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants