Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions authentication/authentication_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package authentication

import (
"context"
"errors"
"net/http"
"testing"
"time"

"github.com/coreos/go-oidc/v3/oidc"
"github.com/go-kit/log"
grpc_middleware_auth "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth"
"github.com/mitchellh/mapstructure"
Expand Down Expand Up @@ -109,3 +112,63 @@ func TestNewAuthentication(t *testing.T) {
}
})
}

func TestTokenExpiredErrorHandling(t *testing.T) {
// Test the error handling logic for TokenExpiredError
t.Run("TokenExpiredError is correctly identified", func(t *testing.T) {
// Create a TokenExpiredError
expiredErr := &oidc.TokenExpiredError{
Expiry: time.Now().Add(-time.Hour), // Expired an hour ago
}

// Test direct error
var tokenExpiredErr *oidc.TokenExpiredError
if !errors.As(expiredErr, &tokenExpiredErr) {
t.Error("errors.As should identify TokenExpiredError")
}

// Test wrapped error
wrappedErr := &wrappedError{
msg: "verification failed",
err: expiredErr,
}

if !errors.As(wrappedErr, &tokenExpiredErr) {
t.Error("errors.As should identify wrapped TokenExpiredError")
}
})

t.Run("Other errors are not identified as TokenExpiredError", func(t *testing.T) {
// Test with a generic error
genericErr := errors.New("generic verification error")

var tokenExpiredErr *oidc.TokenExpiredError
if errors.As(genericErr, &tokenExpiredErr) {
t.Error("errors.As should not identify generic error as TokenExpiredError")
}

// Test with wrapped generic error
wrappedGenericErr := &wrappedError{
msg: "verification failed",
err: genericErr,
}

if errors.As(wrappedGenericErr, &tokenExpiredErr) {
t.Error("errors.As should not identify wrapped generic error as TokenExpiredError")
}
})
}

// Helper type to wrap errors for testing.
type wrappedError struct {
msg string
err error
}

func (e *wrappedError) Error() string {
return e.msg
}

func (e *wrappedError) Unwrap() error {
return e.err
}
6 changes: 6 additions & 0 deletions authentication/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"crypto/tls"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"net"
"net/http"
Expand Down Expand Up @@ -359,6 +360,11 @@ func (a oidcAuthenticator) checkAuth(ctx context.Context, token string) (context
// We log it to allow the possibility of debugging this.
level.Debug(a.logger).Log("msg", msg, "err", err)

var tokenExpiredErr *oidc.TokenExpiredError
if errors.As(err, &tokenExpiredErr) {
return ctx, "token is expired", http.StatusForbidden, codes.Unauthenticated
}

// The original HTTP implementation returned StatusInternalServerError.
// For gRPC we return Unknown, as we can't really
// be sure the problem is internal and not deserving Unauthenticated or InvalidArgument.
Expand Down