annotate pkg/auth/middleware.go @ 5688:6281c18b109f sr-v2

Finsh serializing v2 meshes.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 12 Feb 2024 02:27:41 +0100
parents 97430d442909
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1017
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 493
diff changeset
1 // This is Free Software under GNU Affero General Public License v >= 3.0
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 493
diff changeset
2 // without warranty, see README.md and license for details.
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 493
diff changeset
3 //
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 493
diff changeset
4 // SPDX-License-Identifier: AGPL-3.0-or-later
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 493
diff changeset
5 // License-Filename: LICENSES/AGPL-3.0.txt
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 493
diff changeset
6 //
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 493
diff changeset
7 // Copyright (C) 2018 by via donau
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 493
diff changeset
8 // – Österreichische Wasserstraßen-Gesellschaft mbH
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 493
diff changeset
9 // Software engineering by Intevation GmbH
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 493
diff changeset
10 //
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 493
diff changeset
11 // Author(s):
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 493
diff changeset
12 // * Sascha L. Teichmann <sascha.teichmann@intevation.de>
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 493
diff changeset
13
119
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
14 package auth
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
15
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
16 import (
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
17 "context"
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
18 "net/http"
134
0c56c56a1c44 Removed the JWT layer from the session management.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 128
diff changeset
19 "strings"
119
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
20 )
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
21
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
22 type contextType int
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
23
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
24 const (
134
0c56c56a1c44 Removed the JWT layer from the session management.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 128
diff changeset
25 sessionKey contextType = iota
119
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
26 tokenKey
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
27 )
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
28
1340
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
29 // GetSession returns the session stored in the context of the request.
134
0c56c56a1c44 Removed the JWT layer from the session management.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 128
diff changeset
30 func GetSession(req *http.Request) (*Session, bool) {
0c56c56a1c44 Removed the JWT layer from the session management.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 128
diff changeset
31 session, ok := req.Context().Value(sessionKey).(*Session)
0c56c56a1c44 Removed the JWT layer from the session management.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 128
diff changeset
32 return session, ok
119
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
33 }
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
34
1340
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
35 // GetToken returns the session token associated with given request.
119
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
36 func GetToken(req *http.Request) (string, bool) {
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
37 token, ok := req.Context().Value(tokenKey).(string)
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
38 return token, ok
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
39 }
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
40
1340
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
41 // SessionMiddleware constructs a middleware to enforce the existence
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
42 // of the header X-Gemma-Auth in the incoming request and checks
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
43 // if a session is bound to it.
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
44 // Ihe the checks fail the constructed handler issues an http.StatusUnauthorized
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
45 // back to the invokation stacks and prevents the execution of the
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
46 // nested http.Handler next.
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
47 // Inside the http.Handler next calls to GetSession and GetToken are valid
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
48 // to fetch the respective information.
134
0c56c56a1c44 Removed the JWT layer from the session management.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 128
diff changeset
49 func SessionMiddleware(next http.Handler) http.Handler {
119
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
50
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
51 return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
52
134
0c56c56a1c44 Removed the JWT layer from the session management.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 128
diff changeset
53 auth := req.Header.Get("X-Gemma-Auth")
119
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
54
134
0c56c56a1c44 Removed the JWT layer from the session management.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 128
diff changeset
55 token := strings.TrimSpace(auth)
0c56c56a1c44 Removed the JWT layer from the session management.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 128
diff changeset
56 if token == "" {
119
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
57 http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
58 return
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
59 }
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
60
493
8a0737aa6ab6 The connection pool is now only a session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 447
diff changeset
61 session := Sessions.Session(token)
134
0c56c56a1c44 Removed the JWT layer from the session management.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 128
diff changeset
62 if session == nil {
0c56c56a1c44 Removed the JWT layer from the session management.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 128
diff changeset
63 http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
119
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
64 return
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
65 }
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
66
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
67 ctx := req.Context()
134
0c56c56a1c44 Removed the JWT layer from the session management.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 128
diff changeset
68 ctx = context.WithValue(ctx, sessionKey, session)
0c56c56a1c44 Removed the JWT layer from the session management.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 128
diff changeset
69 ctx = context.WithValue(ctx, tokenKey, token)
119
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
70 req = req.WithContext(ctx)
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
71
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
72 next.ServeHTTP(rw, req)
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
73 })
29e56c342c9f Added first middleware for JWT token extraction. TODO: Add second one to check against logged in users.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
74 }
128
441a8ee637c5 Added claims checker + example.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 119
diff changeset
75
1340
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
76 // SessionChecker constructs a middleware to check invariants about a session
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
77 // before calling the nested http.Handler next.
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
78 // This is useful when creating specialized middleware e.g. to enforce
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
79 // a role system.
134
0c56c56a1c44 Removed the JWT layer from the session management.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 128
diff changeset
80 func SessionChecker(next http.Handler, check func(*Session) bool) http.Handler {
128
441a8ee637c5 Added claims checker + example.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 119
diff changeset
81 return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
1319
450f5d0f5fe7 Cosmetics.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1017
diff changeset
82 if claims, ok := GetSession(req); !ok || !check(claims) {
128
441a8ee637c5 Added claims checker + example.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 119
diff changeset
83 http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
441a8ee637c5 Added claims checker + example.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 119
diff changeset
84 return
441a8ee637c5 Added claims checker + example.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 119
diff changeset
85 }
441a8ee637c5 Added claims checker + example.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 119
diff changeset
86 next.ServeHTTP(rw, req)
441a8ee637c5 Added claims checker + example.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 119
diff changeset
87 })
441a8ee637c5 Added claims checker + example.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 119
diff changeset
88 }
441a8ee637c5 Added claims checker + example.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 119
diff changeset
89
1340
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
90 // HasRole is a checker function fitting into SessionChecker to check
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
91 // if the user is logged in with at least one of list of given roles.
134
0c56c56a1c44 Removed the JWT layer from the session management.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 128
diff changeset
92 func HasRole(roles ...string) func(*Session) bool {
0c56c56a1c44 Removed the JWT layer from the session management.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 128
diff changeset
93 return func(session *Session) bool {
447
62c909dd3098 Only allow log in if user has at least one of the roles 'sys_admin', 'waterway_admin', 'waterway_user'.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 414
diff changeset
94 return session.Roles.HasAny(roles...)
128
441a8ee637c5 Added claims checker + example.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 119
diff changeset
95 }
441a8ee637c5 Added claims checker + example.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 119
diff changeset
96 }
226
63dd5216eee4 Refactored gemma server to be more REST-like.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 134
diff changeset
97
1340
97430d442909 Added comments to auth middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1319
diff changeset
98 // EnsureRole is a macro function to stitch SessionChecker and HasRole together.
237
3771788d3dae Reduce boilerplate code when writing JSON parsing/generating endpoints.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 230
diff changeset
99 func EnsureRole(roles ...string) func(http.Handler) http.Handler {
3771788d3dae Reduce boilerplate code when writing JSON parsing/generating endpoints.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 230
diff changeset
100 return func(handler http.Handler) http.Handler {
3771788d3dae Reduce boilerplate code when writing JSON parsing/generating endpoints.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 230
diff changeset
101 return SessionMiddleware(SessionChecker(handler, HasRole(roles...)))
226
63dd5216eee4 Refactored gemma server to be more REST-like.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 134
diff changeset
102 }
63dd5216eee4 Refactored gemma server to be more REST-like.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 134
diff changeset
103 }