• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / useradm / 1030325529

09 Oct 2023 11:24AM UTC coverage: 89.205% (-0.3%) from 89.534%
1030325529

Pull #383

gitlab-ci

tranchitella
feat: support for Ed25519 server keys for signing the JWT tokens

Ticket: MEN-5676
Changelog: Title

Signed-off-by: Fabio Tranchitella <fabio.tranchitella@northern.tech>
Pull Request #383: feat: support for Ed25519 server keys for signing the JWT tokens

97 of 118 new or added lines in 7 files covered. (82.2%)

2 existing lines in 1 file now uncovered.

2661 of 2983 relevant lines covered (89.21%)

118.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.65
/authz/middleware.go
1
// Copyright 2023 Northern.tech AS
2
//
3
//        Licensed under the Apache License, Version 2.0 (the "License");
4
//        you may not use this file except in compliance with the License.
5
//        You may obtain a copy of the License at
6
//
7
//            http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//        Unless required by applicable law or agreed to in writing, software
10
//        distributed under the License is distributed on an "AS IS" BASIS,
11
//        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//        See the License for the specific language governing permissions and
13
//        limitations under the License.
14
package authz
15

16
import (
17
        "net/http"
18
        "strings"
19

20
        "github.com/ant0ine/go-json-rest/rest"
21
        "github.com/mendersoftware/go-lib-micro/log"
22
        "github.com/mendersoftware/go-lib-micro/rest_utils"
23

24
        "github.com/mendersoftware/useradm/jwt"
25
)
26

27
const (
28
        // token's key in request.Env
29
        ReqToken = "authz_token"
30
)
31

32
// AuthzMiddleware checks the authorization on a given request.
33
// It retrieves the token + requested resource and action, and delegates the authz check to an
34
// Authorizer.
35
type AuthzMiddleware struct {
36
        Authz              Authorizer
37
        ResFunc            ResourceActionExtractor
38
        JWTHandler         jwt.Handler
39
        JWTFallbackHandler jwt.Handler
40
}
41

42
// Action combines info about the requested resourd + http method.
43
type Action struct {
44
        Resource string
45
        Method   string
46
}
47

48
// ResourceActionExtractor extracts Actions from requests.
49
type ResourceActionExtractor func(r *rest.Request) (*Action, error)
50

51
// MiddlewareFunc makes AuthzMiddleware implement the Middleware interface.
52
func (mw *AuthzMiddleware) MiddlewareFunc(h rest.HandlerFunc) rest.HandlerFunc {
11✔
53
        return func(w rest.ResponseWriter, r *rest.Request) {
145✔
54
                l := log.FromContext(r.Context())
134✔
55

134✔
56
                //get token, no token header = http 401
134✔
57
                tokstr, err := ExtractToken(r.Request)
134✔
58
                if err != nil {
137✔
59
                        rest_utils.RestErrWithLog(w, r, l, err, http.StatusUnauthorized)
3✔
60
                        return
3✔
61
                }
3✔
62

63
                // parse token, insert into env
64
                token, err := mw.JWTHandler.FromJWT(tokstr)
131✔
65
                if err != nil && mw.JWTFallbackHandler != nil {
131✔
NEW
66
                        token, err = mw.JWTFallbackHandler.FromJWT(tokstr)
×
NEW
67
                }
×
68
                if err != nil {
139✔
69
                        rest_utils.RestErrWithLog(w, r, l, ErrAuthzTokenInvalid, http.StatusUnauthorized)
8✔
70
                        return
8✔
71
                }
8✔
72

73
                r.Env[ReqToken] = token
123✔
74

123✔
75
                // extract resource action
123✔
76
                action, err := mw.ResFunc(r)
123✔
77
                if err != nil {
125✔
78
                        rest_utils.RestErrWithLogInternal(w, r, l, err)
2✔
79
                        return
2✔
80
                }
2✔
81

82
                ctx := r.Context()
121✔
83

121✔
84
                //authorize, no authz = http 403
121✔
85
                err = mw.Authz.Authorize(ctx, token, action.Resource, action.Method)
121✔
86
                if err != nil {
124✔
87
                        if err == ErrAuthzUnauthorized {
4✔
88
                                rest_utils.RestErrWithLog(w, r, l,
1✔
89
                                        ErrAuthzUnauthorized, http.StatusForbidden)
1✔
90
                        } else if err == ErrAuthzTokenInvalid {
4✔
91
                                rest_utils.RestErrWithLog(w, r, l,
1✔
92
                                        ErrAuthzTokenInvalid, http.StatusUnauthorized)
1✔
93
                        } else {
2✔
94
                                rest_utils.RestErrWithLogInternal(w, r, l, err)
1✔
95
                        }
1✔
96
                        return
3✔
97
                }
98

99
                h(w, r)
118✔
100
        }
101
}
102

103
// extracts JWT from authorization header
104
func ExtractToken(req *http.Request) (string, error) {
159✔
105
        const authHeaderName = "Authorization"
159✔
106
        auth := req.Header.Get(authHeaderName)
159✔
107
        if auth != "" {
316✔
108
                auths := strings.Fields(auth)
157✔
109
                if !strings.EqualFold(auths[0], "Bearer") || len(auths) < 2 {
159✔
110
                        return "", ErrInvalidAuthHeader
2✔
111
                }
2✔
112
                return auths[1], nil
155✔
113
        }
114
        cookie, err := req.Cookie("JWT")
2✔
115
        if err != nil {
3✔
116
                return "", ErrAuthzNoAuth
1✔
117
        }
1✔
118
        auth = cookie.Value
1✔
119
        if auth == "" {
1✔
120
                return "", ErrAuthzNoAuth
×
121
        }
×
122
        return auth, nil
1✔
123
}
124

125
func GetRequestToken(env map[string]interface{}) *jwt.Token {
117✔
126
        return env[ReqToken].(*jwt.Token)
117✔
127
}
117✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc