tokidoki/auth/imap.go

75 lines
1.8 KiB
Go
Raw Normal View History

2022-02-21 09:55:02 +00:00
package auth
import (
"net/http"
"github.com/rs/zerolog/log"
"github.com/emersion/go-imap/v2/imapclient"
2022-02-21 09:55:02 +00:00
)
type IMAPProvider struct {
addr string
tls bool
}
// Initializes a new IMAP auth provider with the given connection string.
func NewIMAP(addr string, tls bool) AuthProvider {
prov := &IMAPProvider{addr, tls}
conn, err := prov.dial()
if err != nil {
log.Fatal().Err(err).Msg("error dialing configured IMAP auth server")
2022-02-21 09:55:02 +00:00
}
conn.Close()
return prov
}
func (prov *IMAPProvider) Middleware() func(http.Handler) http.Handler {
2022-02-21 10:11:27 +00:00
return func(next http.Handler) http.Handler {
2022-02-21 09:55:02 +00:00
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
prov.doAuth(next, w, r)
})
}
}
func (prov *IMAPProvider) doAuth(next http.Handler,
w http.ResponseWriter, r *http.Request) {
user, pass, ok := r.BasicAuth()
if !ok {
w.Header().Add("WWW-Authenticate", `Basic realm="Please provide your IMAP credentials", charset="UTF-8"`)
http.Error(w, "HTTP Basic auth is required", http.StatusUnauthorized)
return
}
conn, err := prov.dial()
if err != nil {
2024-02-05 21:23:58 +00:00
log.Warn().Err(err).Msg("auth dial error")
2022-02-21 09:55:02 +00:00
http.Error(w, "Temporary authentication error, try again later", http.StatusServiceUnavailable)
return
}
defer conn.Close()
if err := conn.Login(user, pass).Wait(); err != nil {
2024-02-05 21:23:58 +00:00
log.Debug().Str("user", user).Err(err).Msg("auth error")
2022-02-21 09:55:02 +00:00
http.Error(w, "Invalid username or password", http.StatusUnauthorized)
return
}
conn.Close()
2022-02-21 09:55:02 +00:00
authCtx := AuthContext{
AuthMethod: "imap",
UserName: user,
}
ctx := NewContext(r.Context(), &authCtx)
r = r.WithContext(ctx)
2022-02-21 09:55:02 +00:00
next.ServeHTTP(w, r)
}
func (prov *IMAPProvider) dial() (*imapclient.Client, error) {
2022-02-21 09:55:02 +00:00
if prov.tls {
return imapclient.DialTLS(prov.addr, nil)
2022-02-21 09:55:02 +00:00
} else {
return imapclient.DialInsecure(prov.addr, nil)
2022-02-21 09:55:02 +00:00
}
}