Skip to content

Commit 841d15b

Browse files
weltekialexellis
authored andcommitted
Include WWW-Authenticate header in 401 responses
Signed-off-by: Han Verstraete (OpenFaaS Ltd) <[email protected]>
1 parent f78ca34 commit 841d15b

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed

executor/jwt_authenticator.go

+14-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import (
1717
"github.com/golang-jwt/jwt/v5"
1818
)
1919

20+
const functionRealm = "IAM function invoke"
21+
2022
func NewJWTAuthMiddleware(next http.Handler) (http.Handler, error) {
2123
var authority = "http://gateway.openfaas:8080/.well-known/openid-configuration"
2224
if v, ok := os.LookupEnv("jwt_auth_local"); ok && (v == "true" || v == "1") {
@@ -71,7 +73,7 @@ func NewJWTAuthMiddleware(next http.Handler) (http.Handler, error) {
7173
}
7274

7375
if bearer == "" {
74-
http.Error(w, "Bearer must be present in Authorization header", http.StatusUnauthorized)
76+
httpUnauthorized(w, "Bearer must be present in Authorization header")
7577
log.Printf("%s %s - %d ACCESS DENIED - (%s)", r.Method, r.URL.Path, http.StatusUnauthorized, time.Since(st).Round(time.Millisecond))
7678
return
7779
}
@@ -108,14 +110,13 @@ func NewJWTAuthMiddleware(next http.Handler) (http.Handler, error) {
108110
return key.Key.(crypto.PublicKey), nil
109111
}, parseOptions...)
110112
if err != nil {
111-
http.Error(w, fmt.Sprintf("failed to parse JWT token: %s", err), http.StatusUnauthorized)
112-
113+
httpUnauthorized(w, fmt.Sprintf("failed to parse JWT token: %s", err))
113114
log.Printf("%s %s - %d ACCESS DENIED - (%s)", r.Method, r.URL.Path, http.StatusUnauthorized, time.Since(st).Round(time.Millisecond))
114115
return
115116
}
116117

117118
if !token.Valid {
118-
http.Error(w, fmt.Sprintf("invalid JWT token: %s", bearer), http.StatusUnauthorized)
119+
httpUnauthorized(w, fmt.Sprintf("invalid JWT token: %s", bearer))
119120

120121
log.Printf("%s %s - %d ACCESS DENIED - (%s)", r.Method, r.URL.Path, http.StatusUnauthorized, time.Since(st).Round(time.Millisecond))
121122
return
@@ -132,6 +133,15 @@ func NewJWTAuthMiddleware(next http.Handler) (http.Handler, error) {
132133
}), nil
133134
}
134135

136+
// httpUnauthorized replies to the request with the specified error message and 401 HTTP code.
137+
// It sets the WWW-Authenticate header.
138+
// It does not otherwise end the request; the caller should ensure no further writes are done to w.
139+
// The error message should be plain text.
140+
func httpUnauthorized(w http.ResponseWriter, err string) {
141+
w.Header().Set("WWW-Authenticate", fmt.Sprintf("Bearer realm=%s", functionRealm))
142+
http.Error(w, err, http.StatusUnauthorized)
143+
}
144+
135145
func getKeyset(uri string) (jwk.KeySpecSet, error) {
136146
var set jwk.KeySpecSet
137147
req, err := http.NewRequest(http.MethodGet, uri, nil)

0 commit comments

Comments
 (0)