ldapauthgin

package module
v1.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 27, 2026 License: MIT Imports: 3 Imported by: 0

README

Gin middleware for ldap-authenticator

LDAP authentication for Gin, built on github.com/ctolon/ldap-authenticator.

go get github.com/ctolon/ldap-authenticator/contrib/gin

Why this is a separate module

The root package promises exactly one direct dependency, github.com/go-ldap/ldap/v3, and means it — a CI job fails the build if that stops being true. Framework middleware cannot live there without breaking that promise, so it lives here instead. Importing ldapauth never puts Gin in your build graph; importing this module is how you ask for it.

The policy — realms, group requirements, status codes, response padding — lives in the root module's httpauth package and is shared with the net/http, Gin, Echo, and Fiber adapters alike. There is one implementation of "what a 403 means here", not four.

Basic auth

auth, err := ldapauth.New(
    ldapauth.WithURL("ldaps://dc1.corp.example:636"),
    ldapauth.WithDirectBind("uid={{username}},ou=people,dc=corp,dc=example"),
    ldapauth.WithMemberOfGroups(),
)
if err != nil {
    log.Fatal(err)
}
defer auth.Close()

r := gin.New()

private := r.Group("/", ldapauthgin.BasicAuth(auth,
    httpauth.WithRealm("corp"),
    httpauth.RequireAnyGroup("developers", "ops"),
    httpauth.WithMinimumDuration(100*time.Millisecond),
))

private.GET("/me", func(c *gin.Context) {
    c.JSON(http.StatusOK, ldapauthgin.MustIdentity(c))
})

The middleware aborts the chain on failure, so a handler behind it only ever runs for a request that authenticated.

Login

r.POST("/login", ldapauthgin.LoginHandler(auth,
    func(c *gin.Context, identity ldapauth.Identity) {
        // Start whatever a session is in your application. This library
        // deliberately does not decide that for you.
        session.Start(c, identity.GetDN(), identity.GetGroups())

        c.JSON(http.StatusOK, gin.H{"dn": identity.GetDN()})
    },
))

Credentials are read from a JSON body, a form body, or a Basic header — whichever the request carries.

Reading the identity

identity, ok := ldapauthgin.IdentityFrom(c)     // the interface
principal, ok := ldapauthgin.PrincipalFrom(c)   // the concrete struct
identity := ldapauthgin.MustIdentity(c)         // panics if absent

The identity is put in both the Gin context, under ldapauthgin.ContextKey, and the request context, so a plain http.Handler further down the chain can read it with httpauth.IdentityFrom(r.Context()).

What the caller sees

200 authenticated, and in the required groups
400 the request was not a login: no username, an empty password
401 wrong or absent credentials, with a WWW-Authenticate challenge
403 the credentials were right and the groups were not
503 the directory could not answer

The body is empty by default: a rejection that explains itself is a rejection that helps somebody guess. httpauth.WithErrorHandler replaces that if your API has a shape of its own.

Options

Every option is an httpauth.Option, shared with the other adapters: WithRealm, RequireAnyGroup, RequireAllGroups, WithMinimumDuration, WithErrorHandler, WithSkip, WithMaxBodyBytes. All of them are applied here, including the two — the skip predicate and the body limit — that this adapter quietly ignored before v1.0.

An option that does not validate panics, because middleware is wired at startup and there is nowhere to return an error to. Use httpauth.NewPolicy if you would rather handle it.

Running the example

go run ./example
curl -u alice:s3cret localhost:8080/me

It runs against the in-memory directory in ldaptest, so there is no LDAP server to install.

More

Documentation

Overview

Package ldapauthgin is Gin middleware for github.com/ctolon/ldap-authenticator.

It is a separate module so that the root package can promise a single dependency and mean it: importing ldapauth never puts Gin in your build graph. The policy — realms, group requirements, status codes, response padding — lives in the httpauth package of the root module and is shared with the other framework adapters, so behaviour cannot drift between them.

r := gin.New()
r.Use(ldapauthgin.BasicAuth(auth, httpauth.RequireAnyGroup("developers")))
r.GET("/me", func(c *gin.Context) {
    c.JSON(200, ldapauthgin.MustIdentity(c))
})

Index

Constants

View Source
const ContextKey = "ldapauth.identity"

ContextKey is the key the identity is stored under in the Gin context, for handlers that would rather use c.Get than the request context.

Variables

This section is empty.

Functions

func BasicAuth

func BasicAuth(auth ldapauth.Authenticator, opts ...httpauth.Option) gin.HandlerFunc

BasicAuth returns middleware that authenticates every request with HTTP Basic credentials, aborting with 401, 403, or 503 as appropriate and otherwise passing the principal to the handlers behind it.

An option that does not validate panics: middleware is wired at startup, and there is nowhere to return an error to.

func IdentityFrom

func IdentityFrom(c *gin.Context) (ldapauth.Identity, bool)

IdentityFrom returns the identity the middleware authenticated.

func LoginHandler

func LoginHandler(
	auth ldapauth.Authenticator,
	onSuccess func(c *gin.Context, p ldapauth.Identity),
	opts ...httpauth.Option,
) gin.HandlerFunc

LoginHandler returns a handler that reads credentials from the request — JSON body, form body, or Basic header — and hands the authenticated principal to onSuccess.

It issues no session and no token. What a successful login becomes is the application's decision; see the httpauth package for why.

func MustIdentity

func MustIdentity(c *gin.Context) ldapauth.Identity

MustIdentity returns the authenticated identity and panics if there is none, for handlers that are only ever mounted behind BasicAuth.

func PrincipalFrom

func PrincipalFrom(c *gin.Context) (*ldapauth.Principal, bool)

PrincipalFrom returns the identity as the concrete ldapauth.Principal, for the common case where the mapper was not replaced and reading fields is nicer than calling accessors.

Types

This section is empty.

Directories

Path Synopsis
Command example is a Gin server authenticating against the in-memory directory, so it runs with no LDAP server anywhere.
Command example is a Gin server authenticating against the in-memory directory, so it runs with no LDAP server anywhere.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL