mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2025-10-26 11:27:18 +00:00
Pull request 2420: AGDNS-2743-auth-middleware-glinet
Merge in DNS/adguard-home from AGDNS-2743-auth-middleware-glinet to master
Squashed commit of the following:
commit 66b6b3d94ec2e19c9fd7dc07c2496a7600d4395a
Merge: 7adae7e2a e1f87ac8f
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Thu Jun 5 16:08:23 2025 +0300
Merge branch 'master' into AGDNS-2743-auth-middleware-glinet
commit 7adae7e2a58bba2d224057e4079b4d1330d33b5d
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Thu Jun 5 15:02:21 2025 +0300
all: imp code
commit fbdc43cde06368db591e29618d0b7281f8342ad5
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Wed Jun 4 21:50:38 2025 +0300
home: add todo
commit 891db077a7bfc41ace66ec593e57253f50500737
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Wed Jun 4 20:36:29 2025 +0300
home: imp docs
commit c706ab6fc4293ce504a2e7b04393296e34cec03e
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Jun 3 22:40:07 2025 +0300
home: imp code
commit 5c75efd020f94a72f6ed48a78e12409a98d2bdc7
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Mon Jun 2 21:06:30 2025 +0300
home: auth middleware glinet config
commit f537365ca40ac75046c0ca31746af139572fde84
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Mon Jun 2 15:46:26 2025 +0300
home: auth middleware glinet
This commit is contained in:
parent
e1f87ac8f4
commit
f69da062eb
2
go.mod
2
go.mod
@ -20,7 +20,6 @@ require (
|
||||
github.com/google/renameio/v2 v2.0.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/insomniacslk/dhcp v0.0.0-20250417080101-5f8cf70e8c5f
|
||||
github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86
|
||||
github.com/kardianos/service v1.2.2
|
||||
github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118
|
||||
github.com/mdlayher/netlink v1.7.2
|
||||
@ -67,6 +66,7 @@ require (
|
||||
github.com/googleapis/gax-go/v2 v2.14.2 // indirect
|
||||
github.com/gookit/color v1.5.4 // indirect
|
||||
github.com/gordonklaus/ineffassign v0.1.0 // indirect
|
||||
github.com/josharian/native v1.1.0 // indirect
|
||||
github.com/jstemmer/go-junit-report/v2 v2.1.0 // indirect
|
||||
github.com/kisielk/errcheck v1.9.0 // indirect
|
||||
github.com/mdlayher/socket v0.5.1 // indirect
|
||||
|
||||
16
go.sum
16
go.sum
@ -54,7 +54,6 @@ github.com/go-ping/ping v1.2.0 h1:vsJ8slZBZAXNCK4dPcI2PEE9eM9n9RbXbGouVQ/Y4yQ=
|
||||
github.com/go-ping/ping v1.2.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
|
||||
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
|
||||
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
@ -94,14 +93,12 @@ github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5
|
||||
github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0=
|
||||
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 h1:/jC7qQFrv8CrSJVmaolDVOxTfS9kc36uB6H40kdbQq8=
|
||||
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905 h1:q3OEI9RaN/wwcx+qgGo6ZaoJkCiDYe/gjDLfq7lQQF4=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905/go.mod h1:VvGYjkZoJyKqlmT1yzakUs4mfKMNB0XdODP0+rdml6k=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20250417080101-5f8cf70e8c5f h1:dd33oobuIv9PcBVqvbEiCXEbNTomOHyj3WFuC5YiPRU=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20250417080101-5f8cf70e8c5f/go.mod h1:zhFlBeJssZ1YBCMZ5Lzu1pX4vhftDvU10WUVb1uXKtM=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86 h1:elKwZS1OcdQ0WwEDBeqxKwb7WB62QX8bvZ/FJnVXIfk=
|
||||
github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86/go.mod h1:aFAMtuldEgx/4q7iSGazk22+IcgvtiC+HIimFO9XlS8=
|
||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/jstemmer/go-junit-report/v2 v2.1.0 h1:X3+hPYlSczH9IMIpSC9CQSZA0L+BipYafciZUWHEmsc=
|
||||
github.com/jstemmer/go-junit-report/v2 v2.1.0/go.mod h1:mgHVr7VUo5Tn8OLVr1cKnLuEy0M92wdRntM99h7RkgQ=
|
||||
github.com/kardianos/service v1.2.2 h1:ZvePhAHfvo0A7Mftk/tEzqEZ7Q4lgnR8sGz4xu1YX60=
|
||||
@ -127,8 +124,6 @@ github.com/mdlayher/raw v0.1.0/go.mod h1:yXnxvs6c0XoF/aK52/H5PjsVHmWBCFfZUfoh/Y5
|
||||
github.com/mdlayher/socket v0.2.1/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E=
|
||||
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
|
||||
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
|
||||
github.com/miekg/dns v1.1.65 h1:0+tIPHzUW0GCge7IiK3guGP57VAw7hoPDfApjkMD1Fc=
|
||||
github.com/miekg/dns v1.1.65/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck=
|
||||
github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE=
|
||||
github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE=
|
||||
github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
|
||||
@ -150,8 +145,6 @@ github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4
|
||||
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.50.1 h1:unsgjFIUqW8a2oopkY7YNONpV1gYND6Nt9hnt1PN94Q=
|
||||
github.com/quic-go/quic-go v0.50.1/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E=
|
||||
github.com/quic-go/quic-go v0.52.0 h1:/SlHrCRElyaU6MaEPKqKr9z83sBg2v4FLLvWM+Z47pA=
|
||||
github.com/quic-go/quic-go v0.52.0/go.mod h1:MFlGGpcpJqRAfmYi6NC2cptDPSxRWTOGNuP4wqrWmzQ=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
@ -171,8 +164,6 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/ti-mo/netfilter v0.2.0/go.mod h1:8GbBGsY/8fxtyIdfwy29JiluNcPK4K7wIT+x42ipqUU=
|
||||
github.com/ti-mo/netfilter v0.5.2 h1:CTjOwFuNNeZ9QPdRXt1MZFLFUf84cKtiQutNauHWd40=
|
||||
github.com/ti-mo/netfilter v0.5.2/go.mod h1:Btx3AtFiOVdHReTDmP9AE+hlkOcvIy403u7BXXbWZKo=
|
||||
github.com/ti-mo/netfilter v0.5.3 h1:ikzduvnaUMwre5bhbNwWOd6bjqLMVb33vv0XXbK0xGQ=
|
||||
github.com/ti-mo/netfilter v0.5.3/go.mod h1:08SyBCg6hu1qyQk4s3DjjJKNrm3RTb32nm6AzyT972E=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
@ -214,8 +205,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
|
||||
golang.org/x/exp/typeparams v0.0.0-20250506013437-ce4c2cf36ca6 h1:UW7ILaA/QTIxnBKbgCV+72w0gRw97+MY93VyPjnGZJU=
|
||||
@ -251,7 +240,6 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.1-0.20230131160137-e7d7f63158de/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/telemetry v0.0.0-20250515191325-98a4f3d86569 h1:OARnwUWlmMxbLDao9LR63zaAhVt7wXqXSbSce28IWow=
|
||||
|
||||
@ -2,8 +2,10 @@ package home
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -11,7 +13,9 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/golibs/ioutil"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/josharian/native"
|
||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||
"github.com/AdguardTeam/golibs/netutil/httputil"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
)
|
||||
|
||||
// GLMode - enable GL-Inet compatibility mode
|
||||
@ -97,8 +101,7 @@ func glGetTokenDate(file string) uint32 {
|
||||
|
||||
buf := bytes.NewBuffer(bs)
|
||||
|
||||
// TODO(a.garipov): Get rid of github.com/josharian/native dependency.
|
||||
err = binary.Read(buf, native.Endian, &dateToken)
|
||||
err = binary.Read(buf, binary.NativeEndian, &dateToken)
|
||||
if err != nil {
|
||||
log.Error("decoding token: %s", err)
|
||||
|
||||
@ -107,3 +110,125 @@ func glGetTokenDate(file string) uint32 {
|
||||
|
||||
return dateToken
|
||||
}
|
||||
|
||||
// authMiddlewareGLiNetConfig is the configuration structure for the GLiNet
|
||||
// authentication middleware.
|
||||
type authMiddlewareGLiNetConfig struct {
|
||||
// logger is used for logging the operation of the middleware. It must not
|
||||
// be nil.
|
||||
//
|
||||
// TODO(s.chzhen): Use logger from the context.
|
||||
logger *slog.Logger
|
||||
|
||||
// clock is used to get the current time. It must not be nil.
|
||||
clock timeutil.Clock
|
||||
|
||||
// tokenFilePrefix is the prefix of the filepath where the authentication
|
||||
// token is stored. It must not be empty.
|
||||
tokenFilePrefix string
|
||||
|
||||
// ttl is the TTL (Time To Live) of the authentication token. It must be
|
||||
// greater than zero.
|
||||
ttl time.Duration
|
||||
|
||||
// maxTokenSize is the maximum size of the file containing the
|
||||
// authentication token. It must be greater than zero.
|
||||
maxTokenSize uint
|
||||
}
|
||||
|
||||
// authMiddlewareGLiNet is the GLiNet authentication middleware. It checks if
|
||||
// the request is authenticated using a cookie.
|
||||
type authMiddlewareGLiNet struct {
|
||||
logger *slog.Logger
|
||||
clock timeutil.Clock
|
||||
tokenFilePrefix string
|
||||
ttl time.Duration
|
||||
maxTokenSize uint
|
||||
}
|
||||
|
||||
// newAuthMiddlewareGLiNet returns the new properly initialized
|
||||
// *authMiddlewareGLiNet.
|
||||
func newAuthMiddlewareGLiNet(c *authMiddlewareGLiNetConfig) (mw *authMiddlewareGLiNet) {
|
||||
return &authMiddlewareGLiNet{
|
||||
logger: c.logger,
|
||||
clock: c.clock,
|
||||
tokenFilePrefix: c.tokenFilePrefix,
|
||||
ttl: c.ttl,
|
||||
maxTokenSize: c.maxTokenSize,
|
||||
}
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ httputil.Middleware = (*authMiddlewareGLiNet)(nil)
|
||||
|
||||
// Wrap implements the [httputil.Middleware] interface for
|
||||
// *authMiddlewareGLiNet.
|
||||
func (mw *authMiddlewareGLiNet) Wrap(h http.Handler) (wrapped http.Handler) {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
if mw.isAuthenticated(ctx, r) {
|
||||
h.ServeHTTP(w, r)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
})
|
||||
}
|
||||
|
||||
// isAuthenticated returns true if the request is authenticated using a cookie.
|
||||
//
|
||||
// TODO(s.chzhen): Use the request's path.
|
||||
func (mw *authMiddlewareGLiNet) isAuthenticated(ctx context.Context, r *http.Request) (ok bool) {
|
||||
c, err := r.Cookie(glCookieName)
|
||||
if err == http.ErrNoCookie {
|
||||
mw.logger.ErrorContext(ctx, "no authentication cookie", slogutil.KeyError, err)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return mw.checkToken(ctx, c.Value)
|
||||
}
|
||||
|
||||
// checkToken verifies the validity of an authentication token. It retrieves
|
||||
// the time stored in a file named after the token and checks if the token has
|
||||
// expired based on that time.
|
||||
func (mw *authMiddlewareGLiNet) checkToken(ctx context.Context, token string) (ok bool) {
|
||||
tokenFile := mw.tokenFilePrefix + token
|
||||
tokenDate := mw.tokenDate(ctx, tokenFile)
|
||||
now := mw.clock.Now()
|
||||
if now.Before(tokenDate.Add(mw.ttl)) {
|
||||
return true
|
||||
}
|
||||
|
||||
mw.logger.DebugContext(ctx, "authentication token has expired")
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// tokenDate returns the time stored in the authentication token file. If there
|
||||
// is an error, it logs the error and returns the zero time.
|
||||
func (mw *authMiddlewareGLiNet) tokenDate(ctx context.Context, tokenFile string) (t time.Time) {
|
||||
f, err := os.Open(tokenFile)
|
||||
if err != nil {
|
||||
mw.logger.ErrorContext(ctx, "opening token file", slogutil.KeyError, err)
|
||||
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
defer slogutil.CloseAndLog(ctx, mw.logger, f, slog.LevelError)
|
||||
|
||||
// Create a 4-byte long buffer to store Unix time as a uint32, since GL.iNet
|
||||
// routers use it as part of an authentication mechanism.
|
||||
//
|
||||
// See https://github.com/AdguardTeam/AdGuardHome/issues/1853.
|
||||
data := make([]byte, 4)
|
||||
_, err = io.ReadFull(f, data)
|
||||
if err != nil {
|
||||
mw.logger.ErrorContext(ctx, "reading token file", slogutil.KeyError, err)
|
||||
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
return time.Unix(int64(binary.NativeEndian.Uint32(data)), 0)
|
||||
}
|
||||
|
||||
@ -1,16 +1,84 @@
|
||||
package home
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/josharian/native"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAuthMiddlewareGLiNet(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const (
|
||||
testTTL = 60 * time.Second
|
||||
|
||||
glTokenFileSuffix = "test"
|
||||
)
|
||||
|
||||
tempDir := t.TempDir()
|
||||
glFilePrefix = tempDir + "/gl_token_"
|
||||
glTokenFile := glFilePrefix + glTokenFileSuffix
|
||||
|
||||
glFileData := make([]byte, 4)
|
||||
binary.NativeEndian.PutUint32(glFileData, uint32(time.Now().Add(testTTL).Unix()))
|
||||
|
||||
err := os.WriteFile(glTokenFile, glFileData, 0o644)
|
||||
require.NoError(t, err)
|
||||
|
||||
mw := newAuthMiddlewareGLiNet(&authMiddlewareGLiNetConfig{
|
||||
logger: testLogger,
|
||||
clock: timeutil.SystemClock{},
|
||||
tokenFilePrefix: glFilePrefix,
|
||||
maxTokenSize: MaxFileSize,
|
||||
ttl: testTTL,
|
||||
})
|
||||
|
||||
h := &testAuthHandler{}
|
||||
wrapped := mw.Wrap(h)
|
||||
|
||||
reqValidCookie := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
reqValidCookie.AddCookie(&http.Cookie{Name: glCookieName, Value: glTokenFileSuffix})
|
||||
|
||||
reqInvalidCookie := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
reqInvalidCookie.AddCookie(&http.Cookie{Name: glCookieName, Value: "invalid_cookie"})
|
||||
|
||||
testCases := []struct {
|
||||
req *http.Request
|
||||
name string
|
||||
wantCode int
|
||||
}{{
|
||||
req: httptest.NewRequest(http.MethodGet, "/", nil),
|
||||
name: "no_cookie",
|
||||
wantCode: http.StatusUnauthorized,
|
||||
}, {
|
||||
req: reqValidCookie,
|
||||
name: "valid_cookie",
|
||||
wantCode: http.StatusOK,
|
||||
}, {
|
||||
req: reqInvalidCookie,
|
||||
name: "invalid_cookie",
|
||||
wantCode: http.StatusUnauthorized,
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
wrapped.ServeHTTP(w, tc.req)
|
||||
|
||||
assert.Equal(t, tc.wantCode, w.Code)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthGL(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
|
||||
@ -19,13 +87,13 @@ func TestAuthGL(t *testing.T) {
|
||||
glFilePrefix = dir + "/gl_token_"
|
||||
|
||||
data := make([]byte, 4)
|
||||
native.Endian.PutUint32(data, 1)
|
||||
binary.NativeEndian.PutUint32(data, 1)
|
||||
|
||||
require.NoError(t, os.WriteFile(glFilePrefix+"test", data, 0o644))
|
||||
assert.False(t, glCheckToken("test"))
|
||||
|
||||
data = make([]byte, 4)
|
||||
native.Endian.PutUint32(data, uint32(time.Now().UTC().Unix()+60))
|
||||
binary.NativeEndian.PutUint32(data, uint32(time.Now().UTC().Unix()+60))
|
||||
|
||||
require.NoError(t, os.WriteFile(glFilePrefix+"test", data, 0o644))
|
||||
r, _ := http.NewRequest(http.MethodGet, "http://localhost/", nil)
|
||||
|
||||
@ -20,6 +20,7 @@ import (
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/netutil/httputil"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
"github.com/AdguardTeam/golibs/validate"
|
||||
)
|
||||
@ -392,8 +393,12 @@ func newAuthMiddlewareDefault(c *authMiddlewareDefaultConfig) (mw *authMiddlewar
|
||||
}
|
||||
}
|
||||
|
||||
// wrap adds authentication logic to the provided HTTP handler.
|
||||
func (mw *authMiddlewareDefault) wrap(h http.Handler) (wrapped http.Handler) {
|
||||
// type check
|
||||
var _ httputil.Middleware = (*authMiddlewareDefault)(nil)
|
||||
|
||||
// Wrap implements the [httputil.Middleware] interface for
|
||||
// *authMiddlewareDefault.
|
||||
func (mw *authMiddlewareDefault) Wrap(h http.Handler) (wrapped http.Handler) {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
if !mw.needsAuthentication(ctx, r) {
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@ -23,7 +24,6 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghuser"
|
||||
"github.com/AdguardTeam/golibs/httphdr"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/josharian/native"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
@ -179,7 +179,7 @@ func TestAuthMiddlewareDefault_firstRun(t *testing.T) {
|
||||
})
|
||||
|
||||
h := &testAuthHandler{}
|
||||
wrapped := mw.wrap(h)
|
||||
wrapped := mw.Wrap(h)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
@ -292,7 +292,7 @@ func TestAuthMiddlewareDefault(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
h := &testAuthHandler{}
|
||||
wrapped := mw.wrap(h)
|
||||
wrapped := mw.Wrap(h)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
wrapped.ServeHTTP(w, tc.req)
|
||||
@ -434,7 +434,7 @@ func TestAuth_ServeHTTP_auth(t *testing.T) {
|
||||
glTokenFile := glFilePrefix + glTokenFileSuffix
|
||||
|
||||
glFileData := make([]byte, 4)
|
||||
native.Endian.PutUint32(glFileData, uint32(time.Now().Unix()+testTTL))
|
||||
binary.NativeEndian.PutUint32(glFileData, uint32(time.Now().Unix()+testTTL))
|
||||
|
||||
err = os.WriteFile(glTokenFile, glFileData, 0o644)
|
||||
require.NoError(t, err)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user