Skip to content

feat: add ldap support#232

Merged
steveiliop56 merged 7 commits intomainfrom
feat/ldap
Jul 5, 2025
Merged

feat: add ldap support#232
steveiliop56 merged 7 commits intomainfrom
feat/ldap

Conversation

@steveiliop56
Copy link
Copy Markdown
Member

@steveiliop56 steveiliop56 commented Jul 4, 2025

Summary by CodeRabbit

  • New Features

    • Added support for LDAP authentication, enabling login with LDAP credentials alongside existing methods.
    • Introduced LDAP configuration options via command-line flags and environment variables.
  • Improvements

    • Enhanced authentication flow to unify local and LDAP user search and verification.
    • Updated login page error message styling for improved readability.
    • Refined user context handling to support LDAP and local user distinctions consistently.
  • Chores

    • Added LDAP-related dependencies.
    • Updated tests and internal components to support LDAP integration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 4, 2025

Walkthrough

LDAP authentication support was added as an optional authentication source. This includes new configuration fields, CLI flags, and environment variables for LDAP settings, as well as integration into authentication logic. User search and verification now distinguish between local and LDAP users. Supporting types, methods, and tests were updated accordingly.

Changes

File(s) Change Summary
cmd/root.go, internal/types/config.go Added LDAP configuration fields, CLI flags, and env vars; integrated LDAP into authentication initialization and validation logic.
internal/ldap/ldap.go Introduced new LDAP client: config struct, connection, search, and bind methods.
internal/auth/auth.go, internal/types/types.go Added LDAP field to Auth struct, new user search/verification logic supporting LDAP and local users, new UserSearch struct.
internal/handlers/handlers.go, internal/hooks/hooks.go Updated login, TOTP, and context logic to use new user search/verification methods and handle user types.
go.mod Added LDAP and related dependencies.
internal/auth/auth_test.go, internal/server/server_test.go Updated tests to use new Auth constructor signature.
frontend/src/pages/login-page.tsx Changed error message element from h3 to p with updated styling.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Server
    participant AuthService
    participant LDAPService

    User->>Server: Submit login (username, password)
    Server->>AuthService: SearchUser(username)
    alt User is local
        AuthService->>AuthService: Find local user
        AuthService->>Server: Return UserSearch(type="local")
        Server->>AuthService: VerifyUser(UserSearch, password)
        AuthService->>AuthService: Check local password
        AuthService->>Server: Success/Failure
    else User is LDAP
        AuthService->>LDAPService: Search(username)
        LDAPService->>AuthService: Return userDN
        AuthService->>Server: Return UserSearch(type="ldap")
        Server->>AuthService: VerifyUser(UserSearch, password)
        AuthService->>LDAPService: Bind(userDN, password)
        LDAPService->>AuthService: Success/Failure
        AuthService->>Server: Success/Failure
    end
    Server->>User: Login result
Loading

Poem

A hop and a skip, LDAP’s in our den,
With configs and flags, we welcome new friends.
Local or LDAP, we search and we bind—
Authentication’s now more refined!
From login to TOTP, the flow’s crystal clear,
🐇 Cheers to new features—let’s all give a cheer!

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@steveiliop56 steveiliop56 mentioned this pull request Jul 4, 2025
@codecov
Copy link
Copy Markdown

codecov Bot commented Jul 5, 2025

Codecov Report

Attention: Patch coverage is 0.87336% with 227 lines in your changes missing coverage. Please review.

Project coverage is 12.01%. Comparing base (4524e33) to head (dc3b2bc).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
internal/auth/auth.go 2.85% 68 Missing ⚠️
internal/ldap/ldap.go 0.00% 50 Missing ⚠️
internal/hooks/hooks.go 0.00% 40 Missing ⚠️
cmd/root.go 0.00% 37 Missing ⚠️
internal/handlers/handlers.go 0.00% 32 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #232      +/-   ##
==========================================
- Coverage   12.84%   12.01%   -0.83%     
==========================================
  Files          19       20       +1     
  Lines        2344     2513     +169     
==========================================
+ Hits          301      302       +1     
- Misses       2031     2199     +168     
  Partials       12       12              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@steveiliop56 steveiliop56 marked this pull request as ready for review July 5, 2025 12:26
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.

Actionable comments posted: 5

🧹 Nitpick comments (5)
internal/types/types.go (1)

15-19: Improve documentation and consider type safety

The UserSearch struct is well-designed for distinguishing between user types. However, consider these improvements:

-// UserSearch is the response of the get user
+// UserSearch represents the result of a user search operation, containing
+// user identification and the authentication source type
 type UserSearch struct {
 	Username string
 	Type     string // "local", "ldap" or empty
 }

Consider defining constants for the Type field values to improve type safety:

const (
	UserTypeLocal = "local"
	UserTypeLDAP  = "ldap"
	UserTypeEmpty = ""
)
internal/ldap/ldap.go (1)

65-72: Remove redundant return statement.

The return nil on line 71 is redundant since line 69 already returns any error.

Apply this diff to simplify the method:

 func (l *LDAP) Bind(userDN string, password string) error {
 	// Bind to the LDAP server with the user's DN and password
-	err := l.Conn.Bind(userDN, password)
-	if err != nil {
-		return err
-	}
-	return nil
+	return l.Conn.Bind(userDN, password)
 }
cmd/root.go (1)

248-253: Consider a more flexible default for LDAP search filter.

The default search filter (uid=%s) assumes the username field is uid. While this is common, different LDAP configurations might use cn, sAMAccountName, or other attributes.

Consider documenting this in the flag description or using a more generic example:

-	rootCmd.Flags().String("ldap-search-filter", "(uid=%s)", "LDAP search filter for user lookup.")
+	rootCmd.Flags().String("ldap-search-filter", "(uid=%s)", "LDAP search filter for user lookup (e.g., (uid=%s), (cn=%s), (sAMAccountName=%s)).")
internal/auth/auth.go (2)

99-101: Consider normalizing LDAP usernames instead of returning DN

Returning the full DN as username (e.g., uid=john,ou=users,dc=example,dc=com) might cause issues in other parts of the system that expect simpler usernames. Consider extracting just the uid/cn from the DN.


74-106: Add test coverage for SearchUser method

This critical authentication method lacks test coverage. Consider adding unit tests for:

  • Local user found scenario
  • LDAP user found scenario
  • User not found in either source
  • LDAP search error handling

Would you like me to generate unit tests for this method?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4524e33 and c671ef1.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (11)
  • cmd/root.go (4 hunks)
  • frontend/src/pages/login-page.tsx (1 hunks)
  • go.mod (2 hunks)
  • internal/auth/auth.go (5 hunks)
  • internal/auth/auth_test.go (4 hunks)
  • internal/handlers/handlers.go (4 hunks)
  • internal/hooks/hooks.go (2 hunks)
  • internal/ldap/ldap.go (1 hunks)
  • internal/server/server_test.go (1 hunks)
  • internal/types/config.go (2 hunks)
  • internal/types/types.go (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
internal/server/server_test.go (1)
internal/auth/auth.go (1)
  • NewAuth (29-49)
internal/hooks/hooks.go (4)
internal/auth/auth.go (1)
  • Auth (20-27)
internal/types/types.go (1)
  • UserContext (42-52)
internal/utils/utils.go (1)
  • Capitalize (335-340)
internal/types/config.go (1)
  • Config (4-45)
internal/ldap/ldap.go (1)
internal/types/config.go (2)
  • Config (4-45)
  • LdapConfig (133-140)
internal/handlers/handlers.go (4)
internal/auth/auth.go (1)
  • Auth (20-27)
internal/types/types.go (1)
  • SessionCookie (32-39)
internal/utils/utils.go (1)
  • Capitalize (335-340)
internal/types/config.go (1)
  • Config (4-45)
🪛 GitHub Check: codecov/patch
internal/hooks/hooks.go

[warning] 38-39: internal/hooks/hooks.go#L38-L39
Added lines #L38 - L39 were not covered by tests


[warning] 41-41: internal/hooks/hooks.go#L41
Added line #L41 was not covered by tests


[warning] 49-54: internal/hooks/hooks.go#L49-L54
Added lines #L49 - L54 were not covered by tests


[warning] 57-59: internal/hooks/hooks.go#L57-L59
Added lines #L57 - L59 were not covered by tests


[warning] 66-66: internal/hooks/hooks.go#L66
Added line #L66 was not covered by tests


[warning] 70-79: internal/hooks/hooks.go#L70-L79
Added lines #L70 - L79 were not covered by tests

cmd/root.go

[warning] 143-163: cmd/root.go#L143-L163
Added lines #L143 - L163 were not covered by tests


[warning] 166-168: cmd/root.go#L166-L168
Added lines #L166 - L168 were not covered by tests


[warning] 171-171: cmd/root.go#L171
Added line #L171 was not covered by tests


[warning] 248-253: cmd/root.go#L248-L253
Added lines #L248 - L253 were not covered by tests


[warning] 289-294: cmd/root.go#L289-L294
Added lines #L289 - L294 were not covered by tests

internal/handlers/handlers.go

[warning] 366-368: internal/handlers/handlers.go#L366-L368
Added lines #L366 - L368 were not covered by tests


[warning] 371-371: internal/handlers/handlers.go#L371
Added line #L371 was not covered by tests


[warning] 385-385: internal/handlers/handlers.go#L385
Added line #L385 was not covered by tests


[warning] 401-417: internal/handlers/handlers.go#L401-L417
Added lines #L401 - L417 were not covered by tests


[warning] 419-424: internal/handlers/handlers.go#L419-L424
Added lines #L419 - L424 were not covered by tests


[warning] 426-428: internal/handlers/handlers.go#L426-L428
Added lines #L426 - L428 were not covered by tests


[warning] 480-480: internal/handlers/handlers.go#L480
Added line #L480 was not covered by tests

internal/auth/auth.go

[warning] 74-74: internal/auth/auth.go#L74
Added line #L74 was not covered by tests


[warning] 76-86: internal/auth/auth.go#L76-L86
Added lines #L76 - L86 were not covered by tests


[warning] 89-96: internal/auth/auth.go#L89-L96
Added lines #L89 - L96 were not covered by tests


[warning] 99-102: internal/auth/auth.go#L99-L102
Added lines #L99 - L102 were not covered by tests


[warning] 105-105: internal/auth/auth.go#L105
Added line #L105 was not covered by tests


[warning] 108-127: internal/auth/auth.go#L108-L127
Added lines #L108 - L127 were not covered by tests


[warning] 130-134: internal/auth/auth.go#L130-L134
Added lines #L130 - L134 were not covered by tests


[warning] 139-140: internal/auth/auth.go#L139-L140
Added lines #L139 - L140 were not covered by tests


[warning] 143-146: internal/auth/auth.go#L143-L146
Added lines #L143 - L146 were not covered by tests


[warning] 149-149: internal/auth/auth.go#L149
Added line #L149 was not covered by tests


[warning] 154-155: internal/auth/auth.go#L154-L155
Added lines #L154 - L155 were not covered by tests


[warning] 355-355: internal/auth/auth.go#L355
Added line #L355 was not covered by tests

🪛 ast-grep (0.38.1)
internal/ldap/ldap.go

[warning] 18-20: MinVersionis missing from this TLS configuration. By default, TLS 1.2 is currently used as the minimum when acting as a client, and TLS 1.0 when acting as a server. General purpose web applications should default to TLS 1.3 with all other protocols disabled. Only where it is known that a web server must support legacy clients with unsupported an insecure browsers (such as Internet Explorer 10), it may be necessary to enable TLS 1.0 to provide support. AddMinVersion: tls.VersionTLS13' to the TLS configuration to bump the minimum version to TLS 1.3.
Context: tls.Config{
InsecureSkipVerify: config.Insecure,
}
Note: [CWE-327]: Use of a Broken or Risky Cryptographic Algorithm [OWASP A03:2017]: Sensitive Data Exposure [OWASP A02:2021]: Cryptographic Failures [REFERENCES]
https://owasp.org/Top10/A02_2021-Cryptographic_Failures

(missing-ssl-minversion-go)

🔇 Additional comments (19)
frontend/src/pages/login-page.tsx (1)

165-167: LGTM: Improved error message styling

The change from <h3> to <p> with added width constraint improves the semantic correctness and visual presentation of the error message when no authentication providers are configured. This aligns well with the LDAP integration changes.

go.mod (2)

25-25: LGTM: ASN.1 BER dependency

The go-asn1-ber/asn1-ber dependency is correctly added as an indirect dependency, which is required for LDAP protocol handling.


65-65: LGTM: LDAP client library

The github.com/go-ldap/ldap/v3 dependency is the standard Go LDAP client library and is appropriate for this integration.

internal/server/server_test.go (1)

87-87: LGTM: Updated auth constructor call

The addition of the third parameter nil correctly aligns with the updated NewAuth signature that now accepts an LDAP service parameter. Using nil is appropriate for tests that don't require LDAP functionality.

internal/auth/auth_test.go (4)

21-21: LGTM: Updated auth constructor for rate limiting tests

The addition of the third parameter nil correctly updates the NewAuth call to match the new signature. This is appropriate for rate limiting tests that don't require LDAP functionality.


65-65: LGTM: Consistent constructor update

The NewAuth call is correctly updated with the third parameter for the timeout testing scenario.


90-90: LGTM: Constructor update for disabled rate limiting test

The constructor call is properly updated to include the LDAP parameter for the disabled rate limiting test case.


106-106: LGTM: Final constructor update

The last NewAuth call is correctly updated to maintain consistency with the new signature for concurrent login attempts testing.

internal/types/config.go (1)

39-44: LGTM! Clean LDAP configuration structure.

The LDAP configuration fields follow the existing patterns with consistent naming and mapstructure tags. The separate LdapConfig struct provides good encapsulation for LDAP-specific parameters.

Also applies to: 132-140

internal/hooks/hooks.go (1)

38-79: Excellent refactoring for LDAP integration.

The authentication logic has been cleanly refactored to support both local and LDAP users using the new SearchUser/VerifyUser pattern. The handling of user types is correct - LDAP users have TOTP disabled (since it's a local-only feature) while local users retain their TOTP configuration. The improved error logging is also a nice touch.

Also applies to: 107-126

internal/ldap/ldap.go (1)

39-63: LDAP search implementation looks robust.

The search method correctly handles the LDAP search flow with proper error checking for multiple/no entries found. Using a configurable search filter with fmt.Sprintf is a good approach for flexibility.

internal/handlers/handlers.go (2)

365-385: Well-implemented LDAP integration in authentication handlers.

The login handler correctly adopts the new SearchUser/VerifyUser pattern and appropriately handles TOTP only for local users. The logic flow ensures LDAP users bypass TOTP completely, which is the correct behavior since TOTP secrets are stored locally.

Also applies to: 401-429


480-480: Correct use of GetLocalUser for TOTP validation.

Using GetLocalUser directly in the TOTP handler is appropriate since TOTP is only applicable to local users, not LDAP users.

cmd/root.go (2)

143-168: Excellent LDAP service integration.

The conditional LDAP service creation with proper error handling and the validation ensuring at least one authentication source is configured demonstrate good defensive programming. The dependency injection pattern is consistently applied.

Also applies to: 171-171


289-294: Environment variable bindings follow consistent pattern.

The LDAP environment variable bindings maintain consistency with the existing configuration approach.

internal/auth/auth.go (4)

355-355: LGTM!

The logic correctly checks if either local users or LDAP authentication is configured.


29-29: All NewAuth callsites updated
Verified that every invocation of NewAuth now includes the new ldap *ldap.LDAP parameter in both production and test code. No further updates are required.

Affected files:

  • cmd/root.go
  • internal/server/server_test.go
  • internal/auth/auth_test.go

143-156: No nil-return issue with GetLocalUser

GetLocalUser’s signature returns a concrete types.User (struct), not a pointer, so it never returned nil. Every call site you have:

  • internal/auth/auth.go:
    if auth.GetLocalUser(username).Username != "" { … }
  • internal/handlers/handlers.go:
    if localUser.TotpSecret != "" { … }
  • internal/hooks/hooks.go:
    assigns user := hooks.Auth.GetLocalUser(...) without any nil check

all correctly treat “not found” as empty fields rather than a nil pointer. There’s no caller comparing the returned User to nil, and no breaking change here.

Likely an incorrect or invalid review comment.


158-161: bcrypt CompareHashAndPassword is safe with an empty hash

Calling bcrypt.CompareHashAndPassword([]byte(""), …) returns a non-nil error (e.g. ErrHashTooShort), so CheckPassword simply returns false—it will not panic. No additional guard is required unless you’d like an early-return for clarity when user.Password is empty.

Comment thread go.mod
Comment thread internal/ldap/ldap.go
Comment thread internal/auth/auth.go Outdated
Comment thread internal/auth/auth.go
Comment thread internal/auth/auth.go
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.

Actionable comments posted: 1

♻️ Duplicate comments (1)
internal/auth/auth.go (1)

74-106: LDAP injection vulnerability persists in SearchUser method

The SearchUser method correctly implements the dual search strategy (local first, then LDAP), but the LDAP injection vulnerability from previous reviews remains unaddressed. On line 92, the username is passed directly to auth.LDAP.Search(username) without proper escaping.

This requires fixing the underlying Search method in the LDAP implementation to properly escape the username parameter using ldap.EscapeFilter() before embedding it in the search filter. The vulnerability allows attackers to manipulate LDAP queries through crafted usernames.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c671ef1 and dc3b2bc.

📒 Files selected for processing (2)
  • internal/auth/auth.go (5 hunks)
  • internal/ldap/ldap.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/ldap/ldap.go
🧰 Additional context used
🧠 Learnings (1)
internal/auth/auth.go (1)
Learnt from: steveiliop56
PR: steveiliop56/tinyauth#122
File: internal/handlers/handlers.go:75-81
Timestamp: 2025-04-30T15:03:09.620Z
Learning: Values from identity providers and user inputs should be sanitized before being set as HTTP headers in TinyAuth to prevent CRLF injection attacks, even if they come from seemingly trusted sources like OAuth providers.
🪛 GitHub Check: codecov/patch
internal/auth/auth.go

[warning] 74-74: internal/auth/auth.go#L74
Added line #L74 was not covered by tests


[warning] 76-86: internal/auth/auth.go#L76-L86
Added lines #L76 - L86 were not covered by tests


[warning] 89-96: internal/auth/auth.go#L89-L96
Added lines #L89 - L96 were not covered by tests


[warning] 99-102: internal/auth/auth.go#L99-L102
Added lines #L99 - L102 were not covered by tests


[warning] 105-105: internal/auth/auth.go#L105
Added line #L105 was not covered by tests


[warning] 108-127: internal/auth/auth.go#L108-L127
Added lines #L108 - L127 were not covered by tests


[warning] 130-135: internal/auth/auth.go#L130-L135
Added lines #L130 - L135 were not covered by tests


[warning] 137-140: internal/auth/auth.go#L137-L140
Added lines #L137 - L140 were not covered by tests


[warning] 142-144: internal/auth/auth.go#L142-L144
Added lines #L142 - L144 were not covered by tests


[warning] 148-149: internal/auth/auth.go#L148-L149
Added lines #L148 - L149 were not covered by tests


[warning] 152-155: internal/auth/auth.go#L152-L155
Added lines #L152 - L155 were not covered by tests


[warning] 158-158: internal/auth/auth.go#L158
Added line #L158 was not covered by tests


[warning] 163-164: internal/auth/auth.go#L163-L164
Added lines #L163 - L164 were not covered by tests


[warning] 364-364: internal/auth/auth.go#L364
Added line #L364 was not covered by tests

🔇 Additional comments (4)
internal/auth/auth.go (4)

10-10: LDAP integration structure looks good

The LDAP field addition to the Auth struct and corresponding constructor changes are well-implemented and follow good practices.

Also applies to: 26-26, 29-29, 47-47


108-150: VerifyUser method implementation addresses previous security concerns

The method correctly:

  • Handles both local and LDAP authentication flows
  • Includes proper error handling for the rebind operation (lines 130-135) as requested in previous reviews
  • Has a default case in the switch statement (lines 142-144) as requested in previous reviews
  • Provides comprehensive logging for debugging

152-165: GetLocalUser method improvements look good

The changes to return types.User{} instead of nil, along with the added debug and warning logging, improve the method's robustness and debuggability.


364-364: UserAuthConfigured method correctly includes LDAP check

The update to include LDAP configuration in the authentication check is appropriate and maintains the method's purpose.

Comment thread internal/auth/auth.go
Comment on lines +74 to +150
func (auth *Auth) SearchUser(username string) types.UserSearch {
// Loop through users and return the user if the username matches
log.Debug().Str("username", username).Msg("Searching for user")

if auth.GetLocalUser(username).Username != "" {
log.Debug().Str("username", username).Msg("Found local user")

// If user found, return a user with the username and type "local"
return types.UserSearch{
Username: username,
Type: "local",
}
}

// If no user found, check LDAP
if auth.LDAP != nil {
log.Debug().Str("username", username).Msg("Checking LDAP for user")

userDN, err := auth.LDAP.Search(username)
if err != nil {
log.Warn().Err(err).Str("username", username).Msg("Failed to find user in LDAP")
return types.UserSearch{}
}

// If user found in LDAP, return a user with the DN as username
return types.UserSearch{
Username: userDN,
Type: "ldap",
}
}

return types.UserSearch{}
}

func (auth *Auth) VerifyUser(search types.UserSearch, password string) bool {
// Authenticate the user based on the type
switch search.Type {
case "local":
// Get local user
user := auth.GetLocalUser(search.Username)

// Check if password is correct
return auth.CheckPassword(user, password)
case "ldap":
// If LDAP is configured, bind to the LDAP server with the user DN and password
if auth.LDAP != nil {
log.Debug().Str("username", search.Username).Msg("Binding to LDAP for user authentication")

// Bind to the LDAP server
err := auth.LDAP.Bind(search.Username, password)
if err != nil {
log.Warn().Err(err).Str("username", search.Username).Msg("Failed to bind to LDAP")
return false
}

// If bind is successful, rebind with the LDAP bind user
err = auth.LDAP.Bind(auth.LDAP.Config.BindDN, auth.LDAP.Config.BindPassword)
if err != nil {
log.Error().Err(err).Msg("Failed to rebind with service account after user authentication")
// Consider closing the connection or creating a new one
return false
}

log.Debug().Str("username", search.Username).Msg("LDAP authentication successful")

// Return true if the bind was successful
return true
}
default:
log.Warn().Str("type", search.Type).Msg("Unknown user type for authentication")
return false
}

// If no user found or authentication failed, return false
log.Warn().Str("username", search.Username).Msg("User authentication failed")
return false
}
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.

🛠️ Refactor suggestion

Consider adding comprehensive unit tests for LDAP functionality

The static analysis shows extensive test coverage gaps for the new LDAP functionality. Given the security-critical nature of authentication code and the complexity of the dual authentication flow, comprehensive unit tests are essential.

Would you like me to help generate unit tests that cover:

  • SearchUser method with both local and LDAP scenarios
  • VerifyUser method for both authentication types
  • Error handling paths and edge cases
  • LDAP connection failures and timeouts
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 74-74: internal/auth/auth.go#L74
Added line #L74 was not covered by tests


[warning] 76-86: internal/auth/auth.go#L76-L86
Added lines #L76 - L86 were not covered by tests


[warning] 89-96: internal/auth/auth.go#L89-L96
Added lines #L89 - L96 were not covered by tests


[warning] 99-102: internal/auth/auth.go#L99-L102
Added lines #L99 - L102 were not covered by tests


[warning] 105-105: internal/auth/auth.go#L105
Added line #L105 was not covered by tests


[warning] 108-127: internal/auth/auth.go#L108-L127
Added lines #L108 - L127 were not covered by tests


[warning] 130-135: internal/auth/auth.go#L130-L135
Added lines #L130 - L135 were not covered by tests


[warning] 137-140: internal/auth/auth.go#L137-L140
Added lines #L137 - L140 were not covered by tests


[warning] 142-144: internal/auth/auth.go#L142-L144
Added lines #L142 - L144 were not covered by tests


[warning] 148-149: internal/auth/auth.go#L148-L149
Added lines #L148 - L149 were not covered by tests

🤖 Prompt for AI Agents
In internal/auth/auth.go from lines 74 to 150, the LDAP functionality in
SearchUser and VerifyUser lacks comprehensive unit tests. Add unit tests
covering SearchUser for both local user found and LDAP user found scenarios,
VerifyUser for local and LDAP authentication success and failure cases,
including error handling paths such as LDAP search errors, bind failures, and
rebind failures. Also include tests for edge cases like nil LDAP configuration
and unknown user types to ensure full coverage of the dual authentication flow.

@steveiliop56 steveiliop56 merged commit 6ec8c97 into main Jul 5, 2025
6 of 8 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Oct 6, 2025
@coderabbitai coderabbitai Bot mentioned this pull request Jan 16, 2026
@Rycochet Rycochet deleted the feat/ldap branch April 1, 2026 16:08
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.

1 participant