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:
Stanislav Chzhen 2025-06-05 17:26:39 +03:00
parent e1f87ac8f4
commit f69da062eb
6 changed files with 213 additions and 27 deletions

2
go.mod
View File

@ -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
View File

@ -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=

View File

@ -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)
}

View File

@ -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)

View File

@ -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) {

View File

@ -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)