sourcefuse / sourcefuse/loopback4-microservice-catalog

feat(authentication-service): case-insensitive email lookup in login verify providers

Open
#2,609 0 comments 0 reactions 1 assignee View on GitHub

@piyushsinghgaur1 is already working on this.

Since Sep 14, 2026.

  • #2611 by @piyushsinghgaur1 — open
bug
Dominant language
TypeScript
Stars
297
Forks
78
Avg merge
2d 3h
Merged PRs (30d)
4

Description

Is your feature request related to a problem? Please describe.

Yes. In KeycloakVerifyProvider (services/authentication-service/src/modules/auth/providers/keycloak-verify.provider.ts), the existing user is resolved with a case-sensitive equality match:

let user: IAuthUser | null = await this.userRepository.findOne({
  where: {
    email: profile.email,
  },
});

Email addresses are case-insensitive in practice (the domain part per RFC, and the local part as treated by virtually all providers — Gmail, Outlook, corporate IdPs). However, identity providers do not guarantee a canonical casing: Keycloak can return John.Doe@example.com while the user row was created as john.doe@example.com (e.g. via admin user creation, bulk import, or a different signup path).

When the casing differs, findOne returns null, so a valid existing user is either:

  • rejected with 401 InvalidCredentials (when no signup provider creates users on the fly), or
  • JIT-provisioned as a duplicate user account by the signup provider, which is worse — the user silently loses access to their existing data.

The same case-sensitive email lookup pattern exists in the other verify/signup flows of the service (e.g. SAML verify provider, local login by username/email, forgot-password), so the issue is not limited to Keycloak.

Describe the solution you'd like

Make the email match case-insensitive in the login verify providers. Possible approaches:

  1. Normalize at query time — look up with a case-insensitive operator, e.g. where: {email: {ilike: <escaped profile.email>}} (with %/_/\ escaped since ILIKE is a pattern match), or lowercase both sides.
  2. Normalize at write time (preferred long-term) — store email lowercased in users/user_credentials on every create/update path, lowercase the incoming profile.email before lookup, and keep plain (index-friendly) equality. Optionally enforce with a unique functional index on LOWER(email).

Either approach could be gated behind an opt-in service config flag (e.g. emailCaseInsensitive: true on AuthServiceBindings.CONFIG) to avoid changing behavior for existing consumers, since tenants with mixed-case duplicate emails already in the DB would need to resolve collisions first.

Describe alternatives you've considered

  • Overriding Strategies.Passport.KEYCLOAK_VERIFIER in the consuming application with a copy of the stock provider that uses ilike — works, but duplicates ~60 lines of library code that drifts on every upgrade.
  • Doing a case-insensitive fallback lookup inside the KEYCLOAK_PRE_VERIFY_PROVIDER hook (the stock verifier passes the found-or-null user to it and uses its return value) — this is our current workaround, but it relies on a hook whose purpose is verification, not user resolution, and every consumer has to rediscover and re-implement it.

Additional context

Suggested acceptance criteria:

  • A user whose stored email differs from the IdP profile email only by case can log in via Keycloak and is matched to their existing account (no duplicate JIT-provisioned user).
  • Behavior is consistent across Keycloak, SAML, and local login flows.
  • Lookup remains SQL-injection safe (parameterized) and documented regarding index usage.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.