File size: 2,480 Bytes
b110593
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//                           _       _
// __      _____  __ ___   ___  __ _| |_ ___
// \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
//  \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
//   \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
//
//  Copyright © 2016 - 2024 Weaviate B.V. All rights reserved.
//
//  CONTACT: [email protected]
//

package anonymous

import (
	"net/http"
	"strings"

	"github.com/go-openapi/runtime"
	"github.com/weaviate/weaviate/usecases/config"
)

// Client for anonymous access
type Client struct {
	config config.AnonymousAccess
}

// New anonymous access client. Client.Middleware can be used as a regular
// golang http-middleware
func New(cfg config.Config) *Client {
	return &Client{config: cfg.Authentication.AnonymousAccess}
}

// Middleware will fail unauthenticated requests if anonymous access is
// disabled. This middleware should run after all previous middlewares.
func (c *Client) Middleware(next http.Handler) http.Handler {
	if c.config.Enabled {
		// Anonymous Access is allowed, this means we don't have to validate any
		// further, let's just return the original middleware stack

		return next
	}

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if hasBearerAuth(r) {
			// if an OIDC-Header is present we can be sure that the OIDC
			// Authenticator has already validated the token, so we don't have to do
			// anything and can call the next handler.
			next.ServeHTTP(w, r)
			return
		}

		w.WriteHeader(401)
		w.Write([]byte(
			`{"code":401,"message":"anonymous access not enabled, please provide an auth scheme such as OIDC"}`,
		))
	})
}

func hasBearerAuth(r *http.Request) bool {
	// The following logic to decide whether OIDC information is set is taken
	// straight from go-swagger to make sure the decision matches:
	// https://github.com/go-openapi/runtime/blob/109737172424d8a656fd1199e28c9f5cc89b0cca/security/authenticator.go#L208-L225
	const prefix = "Bearer "
	var token string
	hdr := r.Header.Get("Authorization")
	if strings.HasPrefix(hdr, prefix) {
		token = strings.TrimPrefix(hdr, prefix)
	}
	if token == "" {
		qs := r.URL.Query()
		token = qs.Get("access_token")
	}
	//#nosec
	ct, _, _ := runtime.ContentType(r.Header)
	if token == "" && (ct == "application/x-www-form-urlencoded" || ct == "multipart/form-data") {
		token = r.FormValue("access_token")
	}
	// End of go-swagger logic

	return token != ""
}