Skip to content

Token without ExpiresAt runs panic #223

@82andre

Description

@82andre

Token without ExpiresAt runs panic, the panic has a recovery, but it would be better have an error.

Sample code: Code in Playground

package main

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"
	"time"

	"github.com/golang-jwt/jwt/v4"
)

func main() {
	fmt.Println("RUN createToken")
	token, err := createToken()
	fatal(err)
	runTest(token) //this RUN OK

	fmt.Println("RUN createTokenThatNotExpire")
	tokenNotExpire, err := createTokenThatNotExpire()
	fatal(err)
	runTest(tokenNotExpire) //this call panic at parser.go:85
	fmt.Println("finish")
}
func runTest(token string) {
	req := httptest.NewRequest("GET", "http://localhost/test", nil)
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", token))
	w := httptest.NewRecorder()
	err := auth(w, req)
	fatal(err)
	res := w.Result()
	// Read the response body
	buf := new(bytes.Buffer)
	io.Copy(buf, res.Body)
	res.Body.Close()
	fmt.Println(buf.String())
	fmt.Println(token)
	fmt.Println("end.")
}

func createToken() (string, error) {
	t := jwt.New(jwt.GetSigningMethod("HS256"))
	t.Claims = &tokenClaims{
		&jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 1)),
		},
		tokenInfo{"test", "1.0", "[email protected]"},
	}
	return t.SignedString(mySigningKey)
}
func createTokenThatNotExpire() (string, error) {
	t := jwt.New(jwt.GetSigningMethod("HS256"))
	t.Claims = &tokenClaims{
		&jwt.RegisteredClaims{
			//ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 1)),
		},
		tokenInfo{"test", "1.0", "[email protected]"},
	}
	return t.SignedString(mySigningKey)
}

func auth(w http.ResponseWriter, r *http.Request) error {
	tokenStr, ok := r.Header["Authorization"]
	if !ok || len(tokenStr) != 1 {
		fatal(errors.New("authorization token not found"))
	}
	st := strings.Split(tokenStr[0], " ")
	if len(st) > 0 && strings.TrimSpace(st[0]) != "Bearer" {
		fatal(errors.New(`token should contain "Bearer"`))
	}
	token, err := jwt.ParseWithClaims(st[1], &tokenClaims{}, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, errors.New("signing method invalid")
		}
		return mySigningKey, nil
	})
	fatal(err)
	if !token.Valid {
		fatal(errors.New("invalid token"))
	}
	return nil
}

func fatal(err error) {
	if err != nil {
		log.Fatal("Test error: %s \n", err)
	}
}

type tokenInfo struct {
	System  string `json:"system"`
	Version string `json:"version"`
	Email   string `json:"email"`
}

type tokenClaims struct {
	*jwt.RegisteredClaims
	tokenInfo
}

var mySigningKey = []byte("MyPassword")

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions