Skip to content
Merged
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
7 changes: 7 additions & 0 deletions internal/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ func (c *cli) setupWithAuthentication(ctx context.Context) error {
}
}

if errors.Is(err, config.ErrMalformedToken) {
return fmt.Errorf("authentication token is corrupted, please run: %s\n\n%s",
ansi.Cyan("auth0 logout && auth0 login"),
ansi.Yellow("Note: Token handling was enhanced in v1.18.0+ to prevent malformed tokens."),
)
}

api, err := initializeManagementClient(tenant.Domain, tenant.GetAccessToken())
if err != nil {
return err
Expand Down
15 changes: 12 additions & 3 deletions internal/config/tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"slices"
"time"

"github.com/lestrrat-go/jwx/v2/jwt"

"github.com/auth0/auth0-cli/internal/auth"
"github.com/auth0/auth0-cli/internal/keyring"
)
Expand All @@ -17,6 +19,8 @@ const accessTokenExpThreshold = 5 * time.Minute
var (
// ErrInvalidToken is thrown when the token is invalid.
ErrInvalidToken = errors.New("token is invalid")
// ErrMalformedToken indicates a corrupted JWT token was found in keyring.
ErrMalformedToken = errors.New("corrupted authentication token detected")
)

type ErrTokenMissingRequiredScopes struct {
Expand Down Expand Up @@ -115,11 +119,16 @@ func (t *Tenant) CheckAuthenticationStatus() error {
}

accessToken := t.GetAccessToken()
if accessToken != "" && !t.HasExpiredToken() {
return nil
if accessToken == "" || t.HasExpiredToken() {
return ErrInvalidToken
}

// Validate that the access token is a well-formed JWT token.
if _, err := jwt.ParseInsecure([]byte(accessToken)); err != nil {
return ErrMalformedToken
}

return ErrInvalidToken
return nil
}

// RegenerateAccessToken regenerates the access token for the tenant.
Expand Down
10 changes: 10 additions & 0 deletions internal/keyring/keyring.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ func DeleteSecretsForTenant(tenant string) error {
}

func StoreAccessToken(tenant, value string) error {
// First, clear any existing chunks to prevent concatenation issues.
for i := 0; i < secretAccessTokenMaxChunks; i++ {
if err := keyring.Delete(secretClientSecret, tenant); err != nil {
if !errors.Is(err, keyring.ErrNotFound) {
return fmt.Errorf("failed to delete client secret from keyring: %s", err)
}
}
}

// Now store the new token in chunks.
chunks := chunk(value, secretAccessTokenChunkSizeInBytes)

for i := 0; i < len(chunks); i++ {
Expand Down
Loading