Skip to content

fix(ldap): pass through LDAP mail attribute instead of crafting email#834

Open
itasli wants to merge 3 commits intotinyauthapp:mainfrom
itasli:fix/ldap-email-passthrough
Open

fix(ldap): pass through LDAP mail attribute instead of crafting email#834
itasli wants to merge 3 commits intotinyauthapp:mainfrom
itasli:fix/ldap-email-passthrough

Conversation

@itasli
Copy link
Copy Markdown

@itasli itasli commented May 3, 2026

TinyAuth was constructing LDAP user emails as username@CookieDomain instead of using the mail attribute stored in the directory. This caused OIDC clients like Grafana to receive a synthetic email rather than the real one.

Rename GetUserDN to GetUserInfo and extend it to also fetch the mail attribute in the same LDAP query. Thread the result through UserSearch and use it in both the login flow and the basic auth middleware, falling back to the crafted email only when LDAP returns no mail value.

Summary by CodeRabbit

  • Bug Fixes
    • LDAP user email addresses are now properly retrieved from the directory during authentication and session management, ensuring accurate user profile information.

TinyAuth was constructing LDAP user emails as username@CookieDomain
instead of using the mail attribute stored in the directory. This caused
OIDC clients like Grafana to receive a synthetic email rather than the
real one.

Rename GetUserDN to GetUserInfo and extend it to also fetch the mail
attribute in the same LDAP query. Thread the result through UserSearch
and use it in both the login flow and the basic auth middleware, falling
back to the crafted email only when LDAP returns no mail value.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dosubot dosubot Bot added the size:S This PR changes 10-29 lines, ignoring generated files. label May 3, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 3, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c13d46ba-4a86-4da6-b10f-5282fc72257b

📥 Commits

Reviewing files that changed from the base of the PR and between d5cf076 and 5bcedf9.

📒 Files selected for processing (4)
  • internal/controller/user_controller.go
  • internal/middleware/context_middleware.go
  • internal/model/users.go
  • internal/service/auth_service.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • internal/controller/user_controller.go
  • internal/middleware/context_middleware.go
  • internal/service/auth_service.go

📝 Walkthrough

Walkthrough

LDAP authentication now retrieves the user's email address from the LDAP directory via a new GetUserInfo() method and threads it through service layers into session cookies and middleware context, enabling LDAP email to be available throughout the request lifecycle.

Changes

LDAP Email Retrieval and Threading

Layer / File(s) Summary
Data Shape
internal/model/users.go
UserSearch struct gains an Email field for LDAP email transport.
LDAP Service
internal/service/ldap_service.go
GetUserDN() is replaced by GetUserInfo(), which retrieves both DN and mail attribute from LDAP directory, validates exactly one entry, and returns (dn, email, error).
Auth Service Integration
internal/service/auth_service.go
SearchUser() calls GetUserInfo() and populates UserSearch with both Username (from DN) and Email for LDAP users.
Session Cookie Wiring
internal/controller/user_controller.go
loginHandler sets session cookie's Email from search.Email when non-empty for LDAP logins.
Middleware Email Resolution
internal/middleware/context_middleware.go
Session-cookie and basic-auth LDAP paths compute userContext.LDAP.Email from username and CookieDomain, then override with search.Email when present.

Possibly related PRs

  • tinyauthapp/tinyauth#232: Earlier LDAP user-search refactoring that this PR extends by adding email retrieval and threading through the authentication flow.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 The bunny hops with glee,
As LDAP now brings email, you see!
From directory depths to middleware clear,
The user's true address now threads through here.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: retrieving the LDAP mail attribute instead of constructing synthetic emails, which is the core objective of this changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
internal/service/ldap_service.go (1)

146-171: ⚡ Quick win

Consider making the mail attribute name configurable.

"mail" is the RFC 2256 / inetOrgPerson standard and covers OpenLDAP and Active Directory. However, some deployments use "mailPrimaryAddress", "email", or other names. Users on those schemas will silently fall back to the synthetic username@domain email and get no benefit from this fix.

Adding a field to LdapConfig with "mail" as the default keeps backward compatibility and makes the feature complete for all LDAP setups.

💡 Suggested approach

In internal/config/config.go, extend LdapConfig:

 type LdapConfig struct {
     ...
     GroupCacheTTL int    `description:"Cache duration for LDAP group membership in seconds." yaml:"groupCacheTTL"`
+    MailAttribute string `description:"LDAP attribute name for the user's email address." yaml:"mailAttribute"`
 }

In NewDefaultConfiguration():

 Ldap: LdapConfig{
     Insecure:      false,
     SearchFilter:  "(uid=%s)",
     GroupCacheTTL: 900,
+    MailAttribute: "mail",
 },

In LdapServiceConfig and wherever LdapService is initialised, thread the field through, then in GetUserInfo:

-       []string{"dn", "mail"},
+       []string{"dn", ldap.config.MailAttribute},
 ...
-       return entry.DN, entry.GetAttributeValue("mail"), nil
+       return entry.DN, entry.GetAttributeValue(ldap.config.MailAttribute), nil
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/service/ldap_service.go` around lines 146 - 171, Add a configurable
mail attribute to LDAP config and use it in GetUserInfo: add a MailAttribute
string field to LdapConfig with default "mail" in NewDefaultConfiguration,
propagate that field through LdapServiceConfig and into LdapService
initialization, and then replace the hard-coded "mail" in
LdapService.GetUserInfo with ldap.config.MailAttribute (falling back to "mail"
if empty) so different schemas like "mailPrimaryAddress" or "email" are
supported.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@internal/service/ldap_service.go`:
- Around line 146-171: Add a configurable mail attribute to LDAP config and use
it in GetUserInfo: add a MailAttribute string field to LdapConfig with default
"mail" in NewDefaultConfiguration, propagate that field through
LdapServiceConfig and into LdapService initialization, and then replace the
hard-coded "mail" in LdapService.GetUserInfo with ldap.config.MailAttribute
(falling back to "mail" if empty) so different schemas like "mailPrimaryAddress"
or "email" are supported.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7751862c-66ae-403b-97a9-141e35b899a6

📥 Commits

Reviewing files that changed from the base of the PR and between 956d2f5 and d5cf076.

📒 Files selected for processing (5)
  • internal/config/config.go
  • internal/controller/user_controller.go
  • internal/middleware/context_middleware.go
  • internal/service/auth_service.go
  • internal/service/ldap_service.go

@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. and removed size:S This PR changes 10-29 lines, ignoring generated files. labels May 7, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 7, 2026

Codecov Report

❌ Patch coverage is 0% with 15 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/service/ldap_service.go 0.00% 6 Missing ⚠️
internal/middleware/context_middleware.go 0.00% 5 Missing ⚠️
internal/controller/user_controller.go 0.00% 2 Missing ⚠️
internal/service/auth_service.go 0.00% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants