comparison pkg/auth/middleware.go @ 1340:97430d442909

Added comments to auth middleware.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 26 Nov 2018 10:32:37 +0100
parents 450f5d0f5fe7
children
comparison
equal deleted inserted replaced
1339:1d1fc92fc3ea 1340:97430d442909
24 const ( 24 const (
25 sessionKey contextType = iota 25 sessionKey contextType = iota
26 tokenKey 26 tokenKey
27 ) 27 )
28 28
29 // GetSession returns the session stored in the context of the request.
29 func GetSession(req *http.Request) (*Session, bool) { 30 func GetSession(req *http.Request) (*Session, bool) {
30 session, ok := req.Context().Value(sessionKey).(*Session) 31 session, ok := req.Context().Value(sessionKey).(*Session)
31 return session, ok 32 return session, ok
32 } 33 }
33 34
35 // GetToken returns the session token associated with given request.
34 func GetToken(req *http.Request) (string, bool) { 36 func GetToken(req *http.Request) (string, bool) {
35 token, ok := req.Context().Value(tokenKey).(string) 37 token, ok := req.Context().Value(tokenKey).(string)
36 return token, ok 38 return token, ok
37 } 39 }
38 40
41 // SessionMiddleware constructs a middleware to enforce the existence
42 // of the header X-Gemma-Auth in the incoming request and checks
43 // if a session is bound to it.
44 // Ihe the checks fail the constructed handler issues an http.StatusUnauthorized
45 // back to the invokation stacks and prevents the execution of the
46 // nested http.Handler next.
47 // Inside the http.Handler next calls to GetSession and GetToken are valid
48 // to fetch the respective information.
39 func SessionMiddleware(next http.Handler) http.Handler { 49 func SessionMiddleware(next http.Handler) http.Handler {
40 50
41 return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { 51 return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
42 52
43 auth := req.Header.Get("X-Gemma-Auth") 53 auth := req.Header.Get("X-Gemma-Auth")
61 71
62 next.ServeHTTP(rw, req) 72 next.ServeHTTP(rw, req)
63 }) 73 })
64 } 74 }
65 75
76 // SessionChecker constructs a middleware to check invariants about a session
77 // before calling the nested http.Handler next.
78 // This is useful when creating specialized middleware e.g. to enforce
79 // a role system.
66 func SessionChecker(next http.Handler, check func(*Session) bool) http.Handler { 80 func SessionChecker(next http.Handler, check func(*Session) bool) http.Handler {
67 return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { 81 return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
68 if claims, ok := GetSession(req); !ok || !check(claims) { 82 if claims, ok := GetSession(req); !ok || !check(claims) {
69 http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) 83 http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
70 return 84 return
71 } 85 }
72 next.ServeHTTP(rw, req) 86 next.ServeHTTP(rw, req)
73 }) 87 })
74 } 88 }
75 89
90 // HasRole is a checker function fitting into SessionChecker to check
91 // if the user is logged in with at least one of list of given roles.
76 func HasRole(roles ...string) func(*Session) bool { 92 func HasRole(roles ...string) func(*Session) bool {
77 return func(session *Session) bool { 93 return func(session *Session) bool {
78 return session.Roles.HasAny(roles...) 94 return session.Roles.HasAny(roles...)
79 } 95 }
80 } 96 }
81 97
98 // EnsureRole is a macro function to stitch SessionChecker and HasRole together.
82 func EnsureRole(roles ...string) func(http.Handler) http.Handler { 99 func EnsureRole(roles ...string) func(http.Handler) http.Handler {
83 return func(handler http.Handler) http.Handler { 100 return func(handler http.Handler) http.Handler {
84 return SessionMiddleware(SessionChecker(handler, HasRole(roles...))) 101 return SessionMiddleware(SessionChecker(handler, HasRole(roles...)))
85 } 102 }
86 } 103 }