Mercurial > gemma
annotate pkg/auth/middleware.go @ 1606:a4d8f284db93
spacer in admin interface added
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Mon, 17 Dec 2018 15:54:27 +0100 |
parents | 97430d442909 |
children |
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 } |