Skip to content

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

Open
itasli wants to merge 1 commit intotinyauthapp:mainfrom
itasli:fix/ldap-email-passthrough
Open

fix(ldap): pass through LDAP mail attribute instead of crafting email#834
itasli wants to merge 1 commit 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

  • New Features

    • LDAP authentication now automatically captures and stores user email information from the directory in user sessions, enabling improved user identification and account management across the platform.
  • Improvements

    • Email data retrieval during LDAP login has been enhanced to ensure proper integration with user session context, providing administrators with complete user identity 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

📝 Walkthrough

Walkthrough

This PR extends the LDAP user search flow to capture and propagate email addresses. The UserSearch struct gains an Email field, the LDAP service fetches both DN and email attributes via a new GetUserInfo method, and downstream layers wire this email through the authentication stack.

Changes

LDAP Email Field Integration

Layer / File(s) Summary
Data Shape
internal/config/config.go
UserSearch struct adds Email string field alongside Username and Type.
LDAP Service
internal/service/ldap_service.go
GetUserDN(username) is replaced by GetUserInfo(username), which searches LDAP for both DN and mail attributes, returning (dn, email, err).
Auth Service Integration
internal/service/auth_service.go
SearchUser switches from GetUserDN to GetUserInfo and populates Email in the returned UserSearch result.
Middleware Wiring
internal/middleware/context_middleware.go
Basic-auth LDAP path now computes a default email from basic.Username + CookieDomain, then overrides it when userSearch.Email is non-empty.
Controller Wiring
internal/controller/user_controller.go
loginHandler sets sessionCookie.Email from userSearch.Email when present for LDAP login types.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Controller as loginHandler
    participant AuthService as AuthService.SearchUser
    participant LdapService as LdapService.GetUserInfo
    participant Middleware as context_middleware
    participant Session as sessionCookie

    Client->>Controller: Login with LDAP credentials
    Controller->>AuthService: SearchUser(username, "ldap")
    AuthService->>LdapService: GetUserInfo(username)
    LdapService-->>AuthService: dn, email, error
    AuthService-->>Controller: UserSearch{Username, Type, Email}
    Controller->>Session: Set Email from userSearch.Email
    Controller-->>Client: Login response with session
    
    Note over Middleware: On subsequent requests,<br/>context_middleware uses LDAP<br/>email to populate UserContext.Email
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • feat: add ldap support #232: Introduced the original LDAP user search flow; this PR directly extends it by adding email field capture and propagation through the same UserSearch and SearchUser functions.

Poem

🐰 Whiskers twitch with email delight,
LDAP secrets now burn bright,
Mail attributes hop through the stack,
No username left to fall back!
Session cookies know thy name—and inbox too!

🚥 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 'fix(ldap): pass through LDAP mail attribute instead of crafting email' directly and precisely describes the main change: switching from synthetic email construction to using the actual LDAP mail attribute.
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
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

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

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

Labels

size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant