fix: check or explicitly ignore returned errors

Satisfies errcheck. Errors that carry no actionable information are
ignored explicitly: writes to an already-committed response, and closing
a fully read response body or file.

Test fixture setup asserts with require.NoError instead, since a failure
there means the fixture itself is broken.
This commit is contained in:
Trong Huu Nguyen
2026-07-28 09:04:59 +02:00
parent c6e711cd85
commit c56625d842
15 changed files with 75 additions and 73 deletions
+3 -1
View File
@@ -5,6 +5,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/nais/wonderwall/internal/crypto"
)
@@ -61,6 +62,7 @@ func BenchmarkEncrypt(b *testing.B) {
crypter := crypto.NewCrypter(key)
for n := 0; n < b.N; n++ {
crypter.Encrypt(plaintext)
_, err := crypter.Encrypt(plaintext)
require.NoError(b, err)
}
}
+1 -1
View File
@@ -24,7 +24,7 @@ func DisallowNonNavigationalRequests(next http.Handler) http.Handler {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(`{"error": "unauthenticated", "error_description": "this is an interactive endpoint; user-agents must be navigated to this endpoint", "error_path": "` + r.URL.Path + `"}`))
_, _ = w.Write([]byte(`{"error": "unauthenticated", "error_description": "this is an interactive endpoint; user-agents must be navigated to this endpoint", "error_path": "` + r.URL.Path + `"}`))
return
}
+6 -6
View File
@@ -91,16 +91,16 @@ func openidFlags() {
func resolveOpenIdProvider() {
switch Provider(viper.GetString(OpenIDProvider)) {
case ProviderIDPorten:
viper.BindEnv(OpenIDClientID, "IDPORTEN_CLIENT_ID")
viper.BindEnv(OpenIDClientJWK, "IDPORTEN_CLIENT_JWK")
viper.BindEnv(OpenIDWellKnownURL, "IDPORTEN_WELL_KNOWN_URL")
_ = viper.BindEnv(OpenIDClientID, "IDPORTEN_CLIENT_ID")
_ = viper.BindEnv(OpenIDClientJWK, "IDPORTEN_CLIENT_JWK")
_ = viper.BindEnv(OpenIDWellKnownURL, "IDPORTEN_WELL_KNOWN_URL")
viper.SetDefault(OpenIDACRValues, acr.IDPortenLevelHigh)
viper.SetDefault(OpenIDUILocales, "nb")
case ProviderAzure:
viper.BindEnv(OpenIDClientID, "AZURE_APP_CLIENT_ID")
viper.BindEnv(OpenIDClientJWK, "AZURE_APP_JWK")
viper.BindEnv(OpenIDWellKnownURL, "AZURE_APP_WELL_KNOWN_URL")
_ = viper.BindEnv(OpenIDClientID, "AZURE_APP_CLIENT_ID")
_ = viper.BindEnv(OpenIDClientJWK, "AZURE_APP_JWK")
_ = viper.BindEnv(OpenIDWellKnownURL, "AZURE_APP_WELL_KNOWN_URL")
default:
viper.Set(OpenIDProvider, ProviderOpenID)
}
+1 -1
View File
@@ -652,7 +652,7 @@ func request(t *testing.T, client *http.Client, method, url string, headers ...h
}
func body(t *testing.T, resp *http.Response) string {
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()
body, err := io.ReadAll(resp.Body)
assert.NoError(t, err)
+2 -2
View File
@@ -209,10 +209,10 @@ func handleAutologin(src ReverseProxySource, w http.ResponseWriter, r *http.Requ
if httpinternal.Accepts(r, "*/*", "application/json") {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(`{"error": "unauthenticated, please log in"}`))
_, _ = w.Write([]byte(`{"error": "unauthenticated, please log in"}`))
} else {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("unauthenticated, please log in"))
_, _ = w.Write([]byte("unauthenticated, please log in"))
}
}
+28 -28
View File
@@ -347,7 +347,7 @@ func (ip *IdentityProviderHandler) parseAuthorizationRequest(query url.Values) (
func (ip *IdentityProviderHandler) Jwks(w http.ResponseWriter, r *http.Request) {
jwks, _ := ip.Provider.GetPublicJwkSet(r.Context())
json.NewEncoder(w).Encode(jwks)
_ = json.NewEncoder(w).Encode(jwks)
}
func (ip *IdentityProviderHandler) PushedAuthorizationRequest(w http.ResponseWriter, r *http.Request) {
@@ -391,7 +391,7 @@ func (ip *IdentityProviderHandler) PushedAuthorizationRequest(w http.ResponseWri
w.Header().Set("content-type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(openid.PushedAuthorizationResponse{
_ = json.NewEncoder(w).Encode(openid.PushedAuthorizationResponse{
RequestUri: requestUri,
ExpiresIn: 60,
})
@@ -480,13 +480,13 @@ func (ip *IdentityProviderHandler) TokenCodeGrant(w http.ResponseWriter, r *http
sub := uuid.New().String()
accessToken := jwt.New()
accessToken.Set("sub", sub)
accessToken.Set("iss", ip.Config.Provider().Issuer())
accessToken.Set("acr", auth.AcrLevel)
accessToken.Set("iat", iat.Unix())
accessToken.Set("exp", exp.Unix())
accessToken.Set("jti", uuid.NewString())
accessToken.Set("aud", auth.ClientID)
_ = accessToken.Set("sub", sub)
_ = accessToken.Set("iss", ip.Config.Provider().Issuer())
_ = accessToken.Set("acr", auth.AcrLevel)
_ = accessToken.Set("iat", iat.Unix())
_ = accessToken.Set("exp", exp.Unix())
_ = accessToken.Set("jti", uuid.NewString())
_ = accessToken.Set("aud", auth.ClientID)
signedAccessToken, err := ip.signToken(accessToken)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
@@ -495,19 +495,19 @@ func (ip *IdentityProviderHandler) TokenCodeGrant(w http.ResponseWriter, r *http
}
idToken := jwt.New()
idToken.Set("sub", sub)
idToken.Set("iss", ip.Config.Provider().Issuer())
idToken.Set("aud", auth.ClientID)
idToken.Set("locale", auth.Locale)
idToken.Set("nonce", auth.Nonce)
idToken.Set("acr", auth.AcrLevel)
idToken.Set("iat", iat.Unix())
idToken.Set("exp", exp.Unix())
idToken.Set("jti", uuid.NewString())
_ = idToken.Set("sub", sub)
_ = idToken.Set("iss", ip.Config.Provider().Issuer())
_ = idToken.Set("aud", auth.ClientID)
_ = idToken.Set("locale", auth.Locale)
_ = idToken.Set("nonce", auth.Nonce)
_ = idToken.Set("acr", auth.AcrLevel)
_ = idToken.Set("iat", iat.Unix())
_ = idToken.Set("exp", exp.Unix())
_ = idToken.Set("jti", uuid.NewString())
// If the sid claim should be in token and in active session
if ip.Config.Provider().SidClaimRequired() {
idToken.Set("sid", auth.SessionID)
_ = idToken.Set("sid", auth.SessionID)
}
signedIdToken, err := ip.signToken(idToken)
@@ -536,7 +536,7 @@ func (ip *IdentityProviderHandler) TokenCodeGrant(w http.ResponseWriter, r *http
w.Header().Set("content-type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(token)
_ = json.NewEncoder(w).Encode(token)
}
func (ip *IdentityProviderHandler) RefreshTokenGrant(w http.ResponseWriter, r *http.Request) {
@@ -570,11 +570,11 @@ func (ip *IdentityProviderHandler) RefreshTokenGrant(w http.ResponseWriter, r *h
}
accessToken := jwt.New()
accessToken.Set("sub", sub)
accessToken.Set("iss", ip.Config.Provider().Issuer())
accessToken.Set("iat", iat.Unix())
accessToken.Set("exp", exp.Unix())
accessToken.Set("jti", uuid.NewString())
_ = accessToken.Set("sub", sub)
_ = accessToken.Set("iss", ip.Config.Provider().Issuer())
_ = accessToken.Set("iat", iat.Unix())
_ = accessToken.Set("exp", exp.Unix())
_ = accessToken.Set("jti", uuid.NewString())
signedAccessToken, err := ip.signToken(accessToken)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
@@ -604,7 +604,7 @@ func (ip *IdentityProviderHandler) RefreshTokenGrant(w http.ResponseWriter, r *h
w.Header().Set("content-type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(token)
_ = json.NewEncoder(w).Encode(token)
}
func (ip *IdentityProviderHandler) validateClientAuthentication(w http.ResponseWriter, r *http.Request, expectedClientID string) error {
@@ -627,7 +627,7 @@ func (ip *IdentityProviderHandler) validateClientAuthentication(w http.ResponseW
clientJwk := ip.Config.Client().ClientJWK()
clientJwkSet := jwk.NewSet()
clientJwkSet.AddKey(clientJwk)
_ = clientJwkSet.AddKey(clientJwk)
publicClientJwkSet, err := jwk.PublicSetOf(clientJwkSet)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
@@ -705,7 +705,7 @@ func (in *relyingPartyServer) SetHandler(handler http.Handler) {
func oauthError(w http.ResponseWriter, err error) {
w.Header().Set("content-type", "application/json")
json.NewEncoder(w).Encode(openid.TokenErrorResponse{
_ = json.NewEncoder(w).Encode(openid.TokenErrorResponse{
Error: "invalid_request",
ErrorDescription: err.Error(),
})
+1 -1
View File
@@ -213,7 +213,7 @@ func (c *Client) oauthPostRequest(ctx context.Context, endpoint string, payload
if err != nil {
return nil, fmt.Errorf("performing request: %w", err)
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()
body, err := io.ReadAll(resp.Body)
if err != nil {
+1 -1
View File
@@ -88,7 +88,7 @@ func NewProviderConfig(cfg *config.Config) (Provider, error) {
if err != nil {
return nil, fmt.Errorf("fetching well known configuration: %w", err)
}
defer response.Body.Close()
defer func() { _ = response.Body.Close() }()
providerCfg := new(ProviderMetadata)
if err := json.NewDecoder(response.Body).Decode(providerCfg); err != nil {
+1 -1
View File
@@ -115,7 +115,7 @@ func New(src Source, cfg *config.Config) chi.Router {
r.Get(paths.Ping, func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("pong"))
_, _ = w.Write([]byte("pong"))
})
r.Route(paths.Session, func(r chi.Router) {
+1 -1
View File
@@ -118,7 +118,7 @@ func newProbeServer(cfg *config.Config) *http.Server {
mux := http.NewServeMux()
healthz := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
_, _ = w.Write([]byte("ok"))
})
mux.HandleFunc("/", healthz)
mux.HandleFunc("/healthz", healthz)
+23 -24
View File
@@ -9,6 +9,7 @@ import (
jwtlib "github.com/lestrrat-go/jwx/v3/jwt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/nais/wonderwall/pkg/mock"
"github.com/nais/wonderwall/pkg/openid"
@@ -29,7 +30,7 @@ func TestExternalID(t *testing.T) {
{
name: "Support for front channel session with required sid claim",
config: sidRequired(),
idToken: idTokenWithSid("some-sid"),
idToken: idTokenWithSid(t, "some-sid"),
want: "some-sid",
exactMatch: true,
},
@@ -37,20 +38,20 @@ func TestExternalID(t *testing.T) {
name: "Support for front channel session with required sid claim and session_state in param",
config: sidRequired(),
params: params("session_state", "some-session-state"),
idToken: idTokenWithSid("some-sid"),
idToken: idTokenWithSid(t, "some-sid"),
want: "some-sid",
exactMatch: true,
},
{
name: "Support for front channel session without required sid claim",
config: sidRequired(),
idToken: idToken(),
idToken: idToken(t),
expectErr: true,
},
{
name: "Support for session management with required param",
config: sessionStateRequired(),
idToken: idToken(),
idToken: idToken(t),
params: params("session_state", "some-session"),
want: "some-session",
exactMatch: true,
@@ -58,7 +59,7 @@ func TestExternalID(t *testing.T) {
{
name: "Support for session management with required param and sid in id_token",
config: sessionStateRequired(),
idToken: idTokenWithSid("some-sid"),
idToken: idTokenWithSid(t, "some-sid"),
params: params("session_state", "some-session"),
want: "some-sid",
exactMatch: true,
@@ -66,28 +67,28 @@ func TestExternalID(t *testing.T) {
{
name: "Support for session management with missing required param",
config: sessionStateRequired(),
idToken: idToken(),
idToken: idToken(t),
params: params("not_session_state", "some-session"),
expectErr: true,
},
{
name: "No support for front-channel logout nor session management should generate session ID",
config: standardConfig(),
idToken: idToken(),
idToken: idToken(t),
want: "some-generated-id",
exactMatch: false,
},
{
name: "No support for front-channel logout nor session management, sid in id_token",
config: standardConfig(),
idToken: idTokenWithSid("some-sid"),
idToken: idTokenWithSid(t, "some-sid"),
want: "some-sid",
exactMatch: true,
},
{
name: "No support for front-channel logout nor session management, session_state in param",
config: standardConfig(),
idToken: idToken(),
idToken: idToken(t),
params: params("session_state", "some-session-state"),
want: "some-session-state",
exactMatch: true,
@@ -95,7 +96,7 @@ func TestExternalID(t *testing.T) {
{
name: "No support for front-channel logout nor session management, sid in id_token and session_state in param, sid should take precedence",
config: standardConfig(),
idToken: idTokenWithSid("some-sid"),
idToken: idTokenWithSid(t, "some-sid"),
params: params("session_state", "some-session-state"),
want: "some-sid",
exactMatch: true,
@@ -159,36 +160,34 @@ func params(key, value string) url.Values {
return values
}
func newIDToken(extraClaims map[string]string) *openid.IDToken {
func newIDToken(t *testing.T, extraClaims map[string]string) *openid.IDToken {
now := time.Now().Truncate(time.Second)
idToken := jwtlib.New()
idToken.Set("sub", "test")
idToken.Set("iss", "test")
idToken.Set("aud", "test")
idToken.Set("iat", now.Unix())
idToken.Set("exp", now.Add(time.Hour).Unix())
require.NoError(t, idToken.Set("sub", "test"))
require.NoError(t, idToken.Set("iss", "test"))
require.NoError(t, idToken.Set("aud", "test"))
require.NoError(t, idToken.Set("iat", now.Unix()))
require.NoError(t, idToken.Set("exp", now.Add(time.Hour).Unix()))
for claim, value := range extraClaims {
if len(claim) > 0 {
idToken.Set(claim, value)
require.NoError(t, idToken.Set(claim, value))
}
}
serialized, err := jwtlib.NewSerializer().Serialize(idToken)
if err != nil {
panic(err)
}
require.NoError(t, err)
return openid.NewIDToken(string(serialized), idToken)
}
func idTokenWithSid(sid string) *openid.IDToken {
return newIDToken(map[string]string{
func idTokenWithSid(t *testing.T, sid string) *openid.IDToken {
return newIDToken(t, map[string]string{
"sid": sid,
})
}
func idToken() *openid.IDToken {
return newIDToken(nil)
func idToken(t *testing.T) *openid.IDToken {
return newIDToken(t, nil)
}
+1 -1
View File
@@ -10,7 +10,7 @@ import (
func TestMemory(t *testing.T) {
crypter := makeCrypter(t)
data := makeData()
data := makeData(t)
encryptedData, err := data.Encrypt(crypter)
assert.NoError(t, err)
+1 -1
View File
@@ -12,7 +12,7 @@ import (
func TestRedis(t *testing.T) {
crypter := makeCrypter(t)
data := makeData()
data := makeData(t)
encryptedData, err := data.Encrypt(crypter)
assert.NoError(t, err)
+3 -2
View File
@@ -8,6 +8,7 @@ import (
jwtlib "github.com/lestrrat-go/jwx/v3/jwt"
"github.com/nais/liberator/pkg/keygen"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/nais/wonderwall/internal/crypto"
"github.com/nais/wonderwall/pkg/openid"
@@ -32,9 +33,9 @@ func makeCrypter(t *testing.T) crypto.Crypter {
return crypto.NewCrypter(key)
}
func makeData() *session.Data {
func makeData(t *testing.T) *session.Data {
idToken := jwtlib.New()
idToken.Set("jti", "id-token-jti")
require.NoError(t, idToken.Set("jti", "id-token-jti"))
accessToken := "some-access-token"
refreshToken := "some-refresh-token"
+2 -2
View File
@@ -29,7 +29,7 @@ func TestAbsoluteValidator_IsValidRedirect(t *testing.T) {
t.Run("open redirects list", func(t *testing.T) {
file, err := os.Open("testdata/open-redirects.txt")
require.NoError(t, err)
defer file.Close()
defer func() { _ = file.Close() }()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
@@ -143,7 +143,7 @@ func TestRelativeValidator_IsValidRedirect(t *testing.T) {
t.Run("open redirects list", func(t *testing.T) {
file, err := os.Open("testdata/open-redirects.txt")
require.NoError(t, err)
defer file.Close()
defer func() { _ = file.Close() }()
scanner := bufio.NewScanner(file)
for scanner.Scan() {