Compare commits

...

2 Commits

Author SHA1 Message Date
Stavros ffafb5bff5 feat: add a reconnect to the initial ldap connection (#928) 2026-06-30 15:57:41 +03:00
Stavros bb867ea5f4 docs: update readme with openid certification badge 2026-06-29 01:35:06 +03:00
2 changed files with 17 additions and 6 deletions
+5 -1
View File
@@ -1,7 +1,7 @@
<div align="center"> <div align="center">
<img alt="Tinyauth" title="Tinyauth" width="96" src="assets/logo-rounded.png"> <img alt="Tinyauth" title="Tinyauth" width="96" src="assets/logo-rounded.png">
<h1>Tinyauth</h1> <h1>Tinyauth</h1>
<p>The tiniest authentication and authorization server you have ever seen.</p> <p>The tiniest OpenID Certified™ authorization and authentication server you have ever seen.</p>
</div> </div>
<div align="center"> <div align="center">
@@ -28,6 +28,10 @@ Tinyauth is the simplest and tiniest authentication and authorization server you
> [!NOTE] > [!NOTE]
> This is the main development branch. For the latest stable release, see the [documentation](https://tinyauth.app) or the latest stable tag. > This is the main development branch. For the latest stable release, see the [documentation](https://tinyauth.app) or the latest stable tag.
As of 2026-06-25, Tinyauth v5.1.0 is OpenID Certified™ for Basic OP. You can find the certification details [here](https://openid.net/certification-old/certified-openid-providers-profiles/), test suite available [here](https://www.certification.openid.net/plan-detail.html?public=true&plan=H0qhpsOcQkxUE).
<img alt="OpenID Certified" width="200" src="https://openid.net/wordpress-content/uploads/2016/05/oid-l-certification-mark-l-cmyk-150dpi-90mm.jpg" />
## Getting Started ## Getting Started
You can get started with Tinyauth by following the guide in the [documentation](https://tinyauth.app/docs/getting-started). There is also an available [docker-compose](./docker-compose.example.yml) file that has Traefik, Whoami and Tinyauth to demonstrate its capabilities (keep in mind that this file lives in the development branch so it may have updates that are not yet released). You can get started with Tinyauth by following the guide in the [documentation](https://tinyauth.app/docs/getting-started). There is also an available [docker-compose](./docker-compose.example.yml) file that has Traefik, Whoami and Tinyauth to demonstrate its capabilities (keep in mind that this file lives in the development branch so it may have updates that are not yet released).
+12 -5
View File
@@ -18,6 +18,7 @@ import (
type LdapService struct { type LdapService struct {
log *logger.Logger log *logger.Logger
ctx context.Context
config *model.Config config *model.Config
conn *ldapgo.Conn conn *ldapgo.Conn
@@ -32,6 +33,7 @@ type LdapServiceInput struct {
Log *logger.Logger Log *logger.Logger
Config *model.Config Config *model.Config
Ding *ding.Ding Ding *ding.Ding
Ctx context.Context
} }
func NewLdapService(i LdapServiceInput) (*LdapService, error) { func NewLdapService(i LdapServiceInput) (*LdapService, error) {
@@ -42,6 +44,7 @@ func NewLdapService(i LdapServiceInput) (*LdapService, error) {
ldap := &LdapService{ ldap := &LdapService{
log: i.Log, log: i.Log,
config: i.Config, config: i.Config,
ctx: i.Ctx,
} }
ldap.bindPw = utils.GetSecret(i.Config.LDAP.BindPassword, i.Config.LDAP.BindPasswordFile) ldap.bindPw = utils.GetSecret(i.Config.LDAP.BindPassword, i.Config.LDAP.BindPasswordFile)
@@ -73,6 +76,8 @@ func NewLdapService(i LdapServiceInput) (*LdapService, error) {
_, err := ldap.connect() _, err := ldap.connect()
if err != nil { if err != nil {
// 3s + 4.5s (3x1.5) = ~6.75-8.25s total wait time before giving up
err = ldap.reconnect(3 * time.Second)
return nil, fmt.Errorf("failed to connect to ldap server: %w", err) return nil, fmt.Errorf("failed to connect to ldap server: %w", err)
} }
@@ -88,7 +93,7 @@ func NewLdapService(i LdapServiceInput) (*LdapService, error) {
err := ldap.heartbeat() err := ldap.heartbeat()
if err != nil { if err != nil {
ldap.log.App.Warn().Err(err).Msg("LDAP connection heartbeat failed, attempting to reconnect") ldap.log.App.Warn().Err(err).Msg("LDAP connection heartbeat failed, attempting to reconnect")
if reconnectErr := ldap.reconnect(); reconnectErr != nil { if reconnectErr := ldap.reconnect(1 * time.Second); reconnectErr != nil {
ldap.log.App.Error().Err(reconnectErr).Msg("Failed to reconnect to LDAP server") ldap.log.App.Error().Err(reconnectErr).Msg("Failed to reconnect to LDAP server")
continue continue
} }
@@ -276,17 +281,19 @@ func (ldap *LdapService) heartbeat() error {
return nil return nil
} }
func (ldap *LdapService) reconnect() error { func (ldap *LdapService) reconnect(interval time.Duration) error {
ldap.log.App.Info().Msg("Attempting to reconnect to LDAP server") ldap.log.App.Info().Msg("Attempting to reconnect to LDAP server")
exp := backoff.NewExponentialBackOff() exp := backoff.NewExponentialBackOff()
exp.InitialInterval = 500 * time.Millisecond exp.InitialInterval = interval
exp.RandomizationFactor = 0.1 exp.RandomizationFactor = 0.1
exp.Multiplier = 1.5 exp.Multiplier = 1.5
exp.Reset() exp.Reset()
operation := func() (*ldapgo.Conn, error) { operation := func() (*ldapgo.Conn, error) {
ldap.conn.Close() if ldap.conn != nil {
ldap.conn.Close()
}
conn, err := ldap.connect() conn, err := ldap.connect()
if err != nil { if err != nil {
return nil, err return nil, err
@@ -294,7 +301,7 @@ func (ldap *LdapService) reconnect() error {
return conn, nil return conn, nil
} }
_, err := backoff.Retry(context.TODO(), operation, backoff.WithBackOff(exp), backoff.WithMaxTries(3)) _, err := backoff.Retry(ldap.ctx, operation, backoff.WithBackOff(exp), backoff.WithMaxTries(3))
if err != nil { if err != nil {
return err return err