remove usages of WithStack, removes github.com/pkg/errors as direct dep

Signed-off-by: Ryan Richard <richardry@vmware.com>
This commit is contained in:
Ryan Richard
2026-05-07 10:57:39 -07:00
parent f9a863f220
commit c8e98d350e
7 changed files with 42 additions and 66 deletions

2
go.mod
View File

@@ -30,7 +30,6 @@ require (
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/ory/fosite v0.49.1-0.20250703093431-a5f0b09bf31c
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
github.com/pkg/errors v0.9.1
github.com/sclevine/spec v1.4.0
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10
@@ -127,6 +126,7 @@ require (
github.com/ory/go-convenience v0.1.0 // indirect
github.com/ory/x v0.0.677 // indirect
github.com/pelletier/go-toml/v2 v2.0.9 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/pquerna/cachecontrol v0.1.0 // indirect
github.com/prometheus/client_golang v1.23.2 // indirect

View File

@@ -1,4 +1,4 @@
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Package token provides a handler for the OIDC token endpoint.
@@ -14,7 +14,6 @@ import (
"time"
"github.com/ory/fosite"
errorsx "github.com/pkg/errors"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/warning"
@@ -165,19 +164,19 @@ func upstreamRefresh(
customSessionData := session.Custom
if customSessionData == nil {
return errorsx.WithStack(errMissingUpstreamSessionInternalError())
return errMissingUpstreamSessionInternalError()
}
providerName := customSessionData.ProviderName
providerType := customSessionData.ProviderType
providerUID := customSessionData.ProviderUID
if providerUID == "" || providerName == "" {
return errorsx.WithStack(errMissingUpstreamSessionInternalError())
return errMissingUpstreamSessionInternalError()
}
skipGroups := !slices.Contains(accessRequest.GetGrantedScopes(), oidcapi.ScopeGroups)
if session.IDTokenClaims().AuthTime.IsZero() {
return errorsx.WithStack(resolvedprovider.ErrMissingUpstreamSessionInternalError())
return resolvedprovider.ErrMissingUpstreamSessionInternalError()
}
err := validateSessionHasUsername(session)
@@ -201,7 +200,7 @@ func upstreamRefresh(
cloneOfIDPSpecificSessionData := idp.CloneIDPSpecificSessionDataFromSession(session.Custom)
if cloneOfIDPSpecificSessionData == nil {
return errorsx.WithStack(resolvedprovider.ErrMissingUpstreamSessionInternalError())
return resolvedprovider.ErrMissingUpstreamSessionInternalError()
}
oldUntransformedUsername := session.Custom.UpstreamUsername
@@ -299,21 +298,21 @@ func findProviderByNameAndType(
for _, p := range idpLister.GetIdentityProviders() {
if p.GetSessionProviderType() == providerType && p.GetProvider().GetResourceName() == providerResourceName {
if p.GetProvider().GetResourceUID() != mustHaveResourceUID {
return nil, errorsx.WithStack(errUpstreamRefreshError().WithHint(
"Provider from upstream session data has changed its resource UID since authentication."))
return nil, errUpstreamRefreshError().WithHint(
"Provider from upstream session data has changed its resource UID since authentication.")
}
return p, nil
}
}
return nil, errorsx.WithStack(errUpstreamRefreshError().
return nil, errUpstreamRefreshError().
WithHint("Provider from upstream session data was not found.").
WithDebugf("provider name: %q, provider type: %q", providerResourceName, providerType))
WithDebugf("provider name: %q, provider type: %q", providerResourceName, providerType)
}
func validateSessionHasUsername(session *psession.PinnipedSession) error {
downstreamUsername := session.Custom.Username
if len(downstreamUsername) == 0 {
return errorsx.WithStack(errMissingUpstreamSessionInternalError())
return errMissingUpstreamSessionInternalError()
}
return nil
}
@@ -348,22 +347,22 @@ func applyIdentityTransformationsDuringRefresh(
func validateAndGetDownstreamGroupsFromSession(session *psession.PinnipedSession) ([]string, error) {
extra := session.Fosite.Claims.Extra
if extra == nil {
return nil, errorsx.WithStack(errMissingUpstreamSessionInternalError())
return nil, errMissingUpstreamSessionInternalError()
}
downstreamGroupsInterface := extra[oidcapi.IDTokenClaimGroups]
if downstreamGroupsInterface == nil {
return nil, errorsx.WithStack(errMissingUpstreamSessionInternalError())
return nil, errMissingUpstreamSessionInternalError()
}
downstreamGroupsInterfaceList, ok := downstreamGroupsInterface.([]any)
if !ok {
return nil, errorsx.WithStack(errMissingUpstreamSessionInternalError())
return nil, errMissingUpstreamSessionInternalError()
}
downstreamGroups := make([]string, 0, len(downstreamGroupsInterfaceList))
for _, downstreamGroupInterface := range downstreamGroupsInterfaceList {
downstreamGroup, ok := downstreamGroupInterface.(string)
if !ok || len(downstreamGroup) == 0 {
return nil, errorsx.WithStack(errMissingUpstreamSessionInternalError())
return nil, errMissingUpstreamSessionInternalError()
}
downstreamGroups = append(downstreamGroups, downstreamGroup)
}

View File

@@ -1,4 +1,4 @@
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package tokenexchange
@@ -11,7 +11,6 @@ import (
"github.com/ory/fosite"
fositeoauth2 "github.com/ory/fosite/handler/oauth2"
"github.com/ory/fosite/handler/openid"
"github.com/pkg/errors"
oidcapi "go.pinniped.dev/generated/latest/apis/supervisor/oidc"
"go.pinniped.dev/internal/psession"
@@ -48,44 +47,44 @@ var _ fosite.TokenEndpointHandler = (*tokenExchangeHandler)(nil)
func (t *tokenExchangeHandler) HandleTokenEndpointRequest(ctx context.Context, requester fosite.AccessRequester) error {
// Skip this request if it's for a different grant type.
if !t.CanHandleTokenEndpointRequest(ctx, requester) {
return errors.WithStack(fosite.ErrUnknownRequest)
return fosite.ErrUnknownRequest
}
// Validate the basic RFC8693 parameters we support.
params, err := t.validateParams(requester.GetRequestForm())
if err != nil {
return errors.WithStack(err)
return err
}
// Validate the incoming access token and lookup the information about the original authorize request from storage.
originalRequester, err := t.validateAccessToken(ctx, requester, params.subjectAccessToken)
if err != nil {
return errors.WithStack(err)
return err
}
// Check that the currently authenticated client and the client which was originally used to get the access token are the same.
if originalRequester.GetClient().GetID() != requester.GetClient().GetID() {
// This error message is copied from the similar check in fosite's flow_authorize_code_token.go.
return errors.WithStack(fosite.ErrInvalidGrant.WithHint("The OAuth 2.0 Client ID from this request does not match the one from the authorize request."))
return fosite.ErrInvalidGrant.WithHint("The OAuth 2.0 Client ID from this request does not match the one from the authorize request.")
}
// Check that the client is allowed to perform this grant type.
if !requester.GetClient().GetGrantTypes().Has(oidcapi.GrantTypeTokenExchange) {
// This error message is trying to be similar to the analogous one in fosite's flow_authorize_code_token.go.
return errors.WithStack(fosite.ErrUnauthorizedClient.WithHintf(`The OAuth 2.0 Client is not allowed to use token exchange grant "%s".`, oidcapi.GrantTypeTokenExchange))
return fosite.ErrUnauthorizedClient.WithHintf(`The OAuth 2.0 Client is not allowed to use token exchange grant "%s".`, oidcapi.GrantTypeTokenExchange)
}
// Require that the incoming access token has the pinniped:request-audience and OpenID scopes.
if !originalRequester.GetGrantedScopes().Has(oidcapi.ScopeRequestAudience) {
return errors.WithStack(fosite.ErrAccessDenied.WithHintf("Missing the %q scope.", oidcapi.ScopeRequestAudience))
return fosite.ErrAccessDenied.WithHintf("Missing the %q scope.", oidcapi.ScopeRequestAudience)
}
if !originalRequester.GetGrantedScopes().Has(oidcapi.ScopeOpenID) {
return errors.WithStack(fosite.ErrAccessDenied.WithHintf("Missing the %q scope.", oidcapi.ScopeOpenID))
return fosite.ErrAccessDenied.WithHintf("Missing the %q scope.", oidcapi.ScopeOpenID)
}
// Check that the stored session meets the minimum requirements for token exchange.
if err := t.validateSession(originalRequester); err != nil {
return errors.WithStack(err)
return err
}
// Copy the original session ID from storage.
@@ -102,7 +101,7 @@ func (t *tokenExchangeHandler) HandleTokenEndpointRequest(ctx context.Context, r
func (t *tokenExchangeHandler) PopulateTokenEndpointResponse(ctx context.Context, requester fosite.AccessRequester, responder fosite.AccessResponder) error {
// Skip this request if it's for a different grant type.
if !t.CanHandleTokenEndpointRequest(ctx, requester) {
return errors.WithStack(fosite.ErrUnknownRequest)
return fosite.ErrUnknownRequest
}
// Get the requested audience parameter again, which was already validated by HandleTokenEndpointRequest() above.
@@ -111,7 +110,7 @@ func (t *tokenExchangeHandler) PopulateTokenEndpointResponse(ctx context.Context
// Use the original authorize request information, along with the requested audience, to mint a new JWT.
responseToken, err := t.mintJWT(ctx, requester, requestedNewAudience)
if err != nil {
return errors.WithStack(err)
return err
}
// Format the response parameters according to RFC8693.
@@ -212,7 +211,7 @@ func (t *tokenExchangeHandler) validateAccessToken(ctx context.Context, requeste
}
// Validate the access token using its stored session data, which includes its expiration time.
if err := t.accessTokenStrategy.ValidateAccessToken(ctx, originalRequester, accessToken); err != nil {
return nil, errors.WithStack(err)
return nil, err
}
return originalRequester, nil
}

View File

@@ -1,4 +1,4 @@
// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Package oidc contains common OIDC functionality needed by FederationDomains to implement
@@ -8,7 +8,6 @@ package oidc
import (
"crypto/subtle"
"errors"
"fmt"
"net/http"
"reflect"
"time"
@@ -16,7 +15,6 @@ import (
"github.com/felixge/httpsnoop"
"github.com/ory/fosite"
"github.com/ory/fosite/compose"
errorsx "github.com/pkg/errors"
oidcapi "go.pinniped.dev/generated/latest/apis/supervisor/oidc"
"go.pinniped.dev/internal/federationdomain/clientregistry"
@@ -402,18 +400,7 @@ func validateCSRFValue(state *UpstreamStateParamData, csrfCookieValue csrftoken.
// WriteAuthorizeError writes an authorization error as it should be returned by the authorization endpoint and other
// similar endpoints that are the end of the downstream authcode flow. Errors responses are written in the usual fosite style.
func WriteAuthorizeError(r *http.Request, w http.ResponseWriter, oauthHelper fosite.OAuth2Provider, authorizeRequester fosite.AuthorizeRequester, err error, isBrowserless bool) {
if plog.Enabled(plog.LevelTrace) {
// When trace level logging is enabled, include the stack trace in the log message.
keysAndValues := FositeErrorForLog(err)
errWithStack := errorsx.WithStack(err)
keysAndValues = append(keysAndValues, "errWithStack")
// klog always prints error values using %s, which does not include stack traces,
// so convert the error to a string which includes the stack trace here.
keysAndValues = append(keysAndValues, fmt.Sprintf("%+v", errWithStack))
plog.Trace("authorize response error", keysAndValues...)
} else {
plog.Info("authorize response error", FositeErrorForLog(err)...)
}
plog.Info("authorize response error", FositeErrorForLog(err)...)
if isBrowserless {
w = rewriteStatusSeeOtherToStatusFoundForBrowserless(w)
}

View File

@@ -1,4 +1,4 @@
// Copyright 2024 the Pinniped contributors. All Rights Reserved.
// Copyright 2024-2026 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package resolvedldap
@@ -9,7 +9,6 @@ import (
"net/http"
"github.com/ory/fosite"
errorsx "github.com/pkg/errors"
"go.pinniped.dev/generated/latest/apis/supervisor/idpdiscovery/v1alpha1"
"go.pinniped.dev/internal/authenticators"
@@ -193,7 +192,7 @@ func (p *FederationDomainResolvedLDAPIdentityProvider) UpstreamRefresh(
sessionData, ok := identity.IDPSpecificSessionData.(*psession.LDAPSessionData)
if !ok {
// This shouldn't really happen.
return nil, errorsx.WithStack(resolvedprovider.ErrMissingUpstreamSessionInternalError())
return nil, resolvedprovider.ErrMissingUpstreamSessionInternalError()
}
dn = sessionData.UserDN
additionalAttributes = sessionData.ExtraRefreshAttributes
@@ -201,7 +200,7 @@ func (p *FederationDomainResolvedLDAPIdentityProvider) UpstreamRefresh(
sessionData, ok := identity.IDPSpecificSessionData.(*psession.ActiveDirectorySessionData)
if !ok {
// This shouldn't really happen.
return nil, errorsx.WithStack(resolvedprovider.ErrMissingUpstreamSessionInternalError())
return nil, resolvedprovider.ErrMissingUpstreamSessionInternalError()
}
dn = sessionData.UserDN
additionalAttributes = sessionData.ExtraRefreshAttributes
@@ -215,7 +214,7 @@ func (p *FederationDomainResolvedLDAPIdentityProvider) UpstreamRefresh(
}
if dn == "" {
return nil, errorsx.WithStack(resolvedprovider.ErrMissingUpstreamSessionInternalError())
return nil, resolvedprovider.ErrMissingUpstreamSessionInternalError()
}
plog.Debug("attempting upstream refresh request",

View File

@@ -12,7 +12,6 @@ import (
"time"
"github.com/ory/fosite"
errorsx "github.com/pkg/errors"
"golang.org/x/oauth2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -228,7 +227,7 @@ func (p *FederationDomainResolvedOIDCIdentityProvider) UpstreamRefresh(
sessionData, ok := identity.IDPSpecificSessionData.(*psession.OIDCSessionData)
if !ok {
// This shouldn't really happen.
return nil, errorsx.WithStack(resolvedprovider.ErrMissingUpstreamSessionInternalError())
return nil, resolvedprovider.ErrMissingUpstreamSessionInternalError()
}
accessTokenStored := sessionData.UpstreamAccessToken != ""
@@ -237,7 +236,7 @@ func (p *FederationDomainResolvedOIDCIdentityProvider) UpstreamRefresh(
//nolint:staticcheck // De Morgan's doesn't make this more readable
exactlyOneTokenStored := (accessTokenStored || refreshTokenStored) && !(accessTokenStored && refreshTokenStored)
if !exactlyOneTokenStored {
return nil, errorsx.WithStack(resolvedprovider.ErrMissingUpstreamSessionInternalError())
return nil, resolvedprovider.ErrMissingUpstreamSessionInternalError()
}
plog.Debug("attempting upstream refresh request",

View File

@@ -1,4 +1,4 @@
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package strategy
@@ -10,7 +10,6 @@ import (
"github.com/ory/fosite"
"github.com/ory/fosite/compose"
fositeoauth2 "github.com/ory/fosite/handler/oauth2"
errorsx "github.com/pkg/errors"
"go.pinniped.dev/internal/federationdomain/storage"
)
@@ -72,8 +71,7 @@ func (s *DynamicOauth2HMACStrategy) GenerateAccessToken(
if err == nil {
if !strings.HasPrefix(token, oryAccessTokenPrefix) {
// This would only happen if fosite changed how it generates tokens. Defensive programming here.
return "", "", errorsx.WithStack(fosite.ErrInvalidTokenFormat.
WithDebugf("Generated token does not have expected prefix"))
return "", "", fosite.ErrInvalidTokenFormat.WithDebugf("Generated token does not have expected prefix")
}
token = replacePrefix(token, oryAccessTokenPrefix, pinAccessTokenPrefix)
}
@@ -86,8 +84,7 @@ func (s *DynamicOauth2HMACStrategy) ValidateAccessToken(
token string,
) error {
if !strings.HasPrefix(token, pinAccessTokenPrefix) {
return errorsx.WithStack(fosite.ErrInvalidTokenFormat.
WithDebugf("Access token did not have prefix %q", pinAccessTokenPrefix))
return fosite.ErrInvalidTokenFormat.WithDebugf("Access token did not have prefix %q", pinAccessTokenPrefix)
}
return s.delegate().ValidateAccessToken(ctx, requester, replacePrefix(token, pinAccessTokenPrefix, oryAccessTokenPrefix))
}
@@ -104,8 +101,7 @@ func (s *DynamicOauth2HMACStrategy) GenerateRefreshToken(
if err == nil {
if !strings.HasPrefix(token, oryRefreshTokenPrefix) {
// This would only happen if fosite changed how it generates tokens. Defensive programming here.
return "", "", errorsx.WithStack(fosite.ErrInvalidTokenFormat.
WithDebugf("Generated token does not have expected prefix"))
return "", "", fosite.ErrInvalidTokenFormat.WithDebugf("Generated token does not have expected prefix")
}
token = replacePrefix(token, oryRefreshTokenPrefix, pinRefreshTokenPrefix)
}
@@ -118,8 +114,7 @@ func (s *DynamicOauth2HMACStrategy) ValidateRefreshToken(
token string,
) error {
if !strings.HasPrefix(token, pinRefreshTokenPrefix) {
return errorsx.WithStack(fosite.ErrInvalidTokenFormat.
WithDebugf("Refresh token did not have prefix %q", pinRefreshTokenPrefix))
return fosite.ErrInvalidTokenFormat.WithDebugf("Refresh token did not have prefix %q", pinRefreshTokenPrefix)
}
return s.delegate().ValidateRefreshToken(ctx, requester, replacePrefix(token, pinRefreshTokenPrefix, oryRefreshTokenPrefix))
}
@@ -136,8 +131,7 @@ func (s *DynamicOauth2HMACStrategy) GenerateAuthorizeCode(
if err == nil {
if !strings.HasPrefix(authcode, oryAuthcodePrefix) {
// This would only happen if fosite changed how it generates tokens. Defensive programming here.
return "", "", errorsx.WithStack(fosite.ErrInvalidTokenFormat.
WithDebugf("Generated token does not have expected prefix"))
return "", "", fosite.ErrInvalidTokenFormat.WithDebugf("Generated token does not have expected prefix")
}
authcode = replacePrefix(authcode, oryAuthcodePrefix, pinAuthcodePrefix)
}
@@ -150,8 +144,7 @@ func (s *DynamicOauth2HMACStrategy) ValidateAuthorizeCode(
token string,
) error {
if !strings.HasPrefix(token, pinAuthcodePrefix) {
return errorsx.WithStack(fosite.ErrInvalidTokenFormat.
WithDebugf("Authorization code did not have prefix %q", pinAuthcodePrefix))
return fosite.ErrInvalidTokenFormat.WithDebugf("Authorization code did not have prefix %q", pinAuthcodePrefix)
}
return s.delegate().ValidateAuthorizeCode(ctx, requester, replacePrefix(token, pinAuthcodePrefix, oryAuthcodePrefix))
}