Passed
Push — main ( f24a32...53c867 )
by Acho
03:11
created

middlewares.APIKeyAuth   B

Complexity

Conditions 6

Size

Total Lines 24
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 17
dl 0
loc 24
rs 8.6166
c 0
b 0
f 0
nop 3
1
package middlewares
2
3
import (
4
	"fmt"
5
	"strings"
6
7
	"github.com/NdoleStudio/httpsms/pkg/repositories"
8
	"github.com/NdoleStudio/httpsms/pkg/telemetry"
9
	"github.com/gofiber/fiber/v2"
10
	"github.com/palantir/stacktrace"
11
)
12
13
// APIKeyAuth authenticates a user from the X-API-Key header
14
func APIKeyAuth(logger telemetry.Logger, tracer telemetry.Tracer, userRepository repositories.UserRepository) fiber.Handler {
15
	logger = logger.WithService("middlewares.APIKeyAuth")
16
17
	return func(c *fiber.Ctx) error {
18
		ctx, span := tracer.StartFromFiberCtx(c, "middlewares.APIKeyAuth")
19
		defer span.End()
20
21
		ctxLogger := tracer.CtxLogger(logger, span)
22
23
		apiKey := getAPIKeyFromRequest(c)
24
		if len(apiKey) == 0 || apiKey == "undefined" || strings.HasPrefix(apiKey, "pk_") {
25
			span.AddEvent(fmt.Sprintf("the request header has no primary [%s] header", authHeaderAPIKey))
26
			return c.Next()
27
		}
28
29
		authUser, err := userRepository.LoadAuthContext(ctx, apiKey)
30
		if err != nil {
31
			ctxLogger.Error(stacktrace.Propagate(err, fmt.Sprintf("cannot load user with api key [%s]", apiKey)))
32
			return c.Next()
33
		}
34
35
		c.Locals(ContextKeyAuthUserID, authUser)
36
		ctxLogger.Info(fmt.Sprintf("[%T] set successfully for user with ID [%s]", authUser, authUser.ID))
37
		return c.Next()
38
	}
39
}
40
41
func getAPIKeyFromRequest(c *fiber.Ctx) string {
42
	apiKey := c.Get(authHeaderAPIKey)
43
	if len(apiKey) != 0 {
44
		return apiKey
45
	}
46
47
	payload := struct {
48
		APIKey string `json:"x-api-key" form:"x-api-key" query:"x-api-key"`
49
	}{}
50
51
	if err := c.BodyParser(&payload); err == nil && payload.APIKey != "" {
52
		return payload.APIKey
53
	}
54
55
	if err := c.QueryParser(&payload); err != nil {
56
		return ""
57
	}
58
59
	return payload.APIKey
60
}
61