Skip to content

Commit

Permalink
Include WWW-Authenticate header in 401 responses
Browse files Browse the repository at this point in the history
Signed-off-by: Han Verstraete (OpenFaaS Ltd) <[email protected]>
  • Loading branch information
welteki committed May 21, 2024
1 parent 7645ca4 commit 80051c3
Showing 1 changed file with 14 additions and 4 deletions.
18 changes: 14 additions & 4 deletions executor/jwt_authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import (
"github.com/golang-jwt/jwt/v5"
)

const functionRealm = "IAM function invoke"

func NewJWTAuthMiddleware(next http.Handler) (http.Handler, error) {
var authority = "http://gateway.openfaas:8080/.well-known/openid-configuration"
if v, ok := os.LookupEnv("jwt_auth_local"); ok && (v == "true" || v == "1") {
Expand Down Expand Up @@ -71,7 +73,7 @@ func NewJWTAuthMiddleware(next http.Handler) (http.Handler, error) {
}

if bearer == "" {
http.Error(w, "Bearer must be present in Authorization header", http.StatusUnauthorized)
httpUnauthorized(w, "Bearer must be present in Authorization header")
log.Printf("%s %s - %d ACCESS DENIED - (%s)", r.Method, r.URL.Path, http.StatusUnauthorized, time.Since(st).Round(time.Millisecond))
return
}
Expand Down Expand Up @@ -108,14 +110,13 @@ func NewJWTAuthMiddleware(next http.Handler) (http.Handler, error) {
return key.Key.(crypto.PublicKey), nil
}, parseOptions...)
if err != nil {
http.Error(w, fmt.Sprintf("failed to parse JWT token: %s", err), http.StatusUnauthorized)

httpUnauthorized(w, fmt.Sprintf("failed to parse JWT token: %s", err))
log.Printf("%s %s - %d ACCESS DENIED - (%s)", r.Method, r.URL.Path, http.StatusUnauthorized, time.Since(st).Round(time.Millisecond))
return
}

if !token.Valid {
http.Error(w, fmt.Sprintf("invalid JWT token: %s", bearer), http.StatusUnauthorized)
httpUnauthorized(w, fmt.Sprintf("invalid JWT token: %s", bearer))

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

// httpUnauthorized replies to the request with the specified error message and 401 HTTP code.
// It sets the WWW-Authenticate header.
// It does not otherwise end the request; the caller should ensure no further writes are done to w.
// The error message should be plain text.
func httpUnauthorized(w http.ResponseWriter, err string) {
w.Header().Set("WWW-Authenticate", fmt.Sprintf("Bearer realm=%s", functionRealm))
http.Error(w, err, http.StatusUnauthorized)
}

func getKeyset(uri string) (jwk.KeySpecSet, error) {
var set jwk.KeySpecSet
req, err := http.NewRequest(http.MethodGet, uri, nil)
Expand Down

0 comments on commit 80051c3

Please sign in to comment.