diff --git a/authmw/token.go b/authmw/token.go index 492b3f5..8d7ef01 100644 --- a/authmw/token.go +++ b/authmw/token.go @@ -8,37 +8,14 @@ import ( "net/http" "slices" "strings" + "time" "git.t-juice.club/microfilm/auth" "github.com/golang-jwt/jwt/v5" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" ) func VerifyToken(authURL string, permittedRoles []string) func(http.Handler) http.Handler { - // Fetch current pubkey - url := fmt.Sprintf("%s/key", authURL) - req, err := http.NewRequest(http.MethodGet, url, nil) - if err != nil { - panic(err) - } - - resp, err := http.DefaultClient.Do(req) - if err != nil { - panic(err) - } - defer resp.Body.Close() - - var authResponse auth.PubkeyResponse - decoder := json.NewDecoder(resp.Body) - if err := decoder.Decode(&authResponse); err != nil { - panic(err) - } - - // Parse pubkey - pub, err := x509.ParsePKIXPublicKey(authResponse.PubKey) - if err != nil { - panic(err) - } - fn := func(next http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { authHeader := r.Header.Get("Authorization") @@ -61,6 +38,74 @@ func VerifyToken(authURL string, permittedRoles []string) func(http.Handler) htt return } + // Fetch current pubkey + url := fmt.Sprintf("%s/key", authURL) + ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second) + defer cancel() + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + if err != nil { + // TODO: Should log + w.WriteHeader(http.StatusInternalServerError) + errResp := &auth.ErrorResponse{ + Message: fmt.Sprintf("Error getting pubkey for token verification: %s", err), + Status: http.StatusUnauthorized, + } + + encoder := json.NewEncoder(w) + _ = encoder.Encode(&errResp) + return + } + + client := &http.Client{ + Transport: otelhttp.NewTransport(http.DefaultTransport), + } + + resp, err := client.Do(req) + if err != nil { + // TODO: Should log + w.WriteHeader(http.StatusInternalServerError) + errResp := &auth.ErrorResponse{ + Message: fmt.Sprintf("Error getting pubkey for token verification: %s", err), + Status: http.StatusUnauthorized, + } + + encoder := json.NewEncoder(w) + _ = encoder.Encode(&errResp) + return + } + defer resp.Body.Close() + + var authResponse auth.PubkeyResponse + decoder := json.NewDecoder(resp.Body) + if err := decoder.Decode(&authResponse); err != nil { + // TODO: Should log + w.WriteHeader(http.StatusInternalServerError) + errResp := &auth.ErrorResponse{ + Message: fmt.Sprintf("Error getting pubkey for token verification: %s", err), + Status: http.StatusUnauthorized, + } + + encoder := json.NewEncoder(w) + _ = encoder.Encode(&errResp) + return + } + + // Parse pubkey + pub, err := x509.ParsePKIXPublicKey(authResponse.PubKey) + if err != nil { + // TODO: Should log + w.WriteHeader(http.StatusInternalServerError) + errResp := &auth.ErrorResponse{ + Message: fmt.Sprintf("Error getting pubkey for token verification: %s", err), + Status: http.StatusUnauthorized, + } + + encoder := json.NewEncoder(w) + _ = encoder.Encode(&errResp) + return + } + // Validate token tokenString := strings.Split(authHeader, " ")[1] token, err := jwt.ParseWithClaims(tokenString, &auth.MicrofilmClaims{}, func(t *jwt.Token) (interface{}, error) { return pub, nil }) diff --git a/version.go b/version.go index b21f54a..2dbf174 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package auth -const Version = "v0.1.3" +const Version = "v0.1.4"