...

Source file src/github.com/MicahParks/keyfunc/given_test.go

Documentation: github.com/MicahParks/keyfunc

     1  package keyfunc_test
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"crypto/ed25519"
     6  	"crypto/elliptic"
     7  	"crypto/rand"
     8  	"crypto/rsa"
     9  	"crypto/sha256"
    10  	"fmt"
    11  	"testing"
    12  
    13  	"github.com/golang-jwt/jwt/v4"
    14  
    15  	"github.com/MicahParks/keyfunc"
    16  	"github.com/MicahParks/keyfunc/examples/custom/method"
    17  )
    18  
    19  const (
    20  	// algAttribute is the JSON attribute for the JWT encryption algorithm.
    21  	algAttribute = "alg"
    22  
    23  	// kidAttribute is the JSON attribute for the Key ID.
    24  	kidAttribute = "kid"
    25  
    26  	// testKID is the testing KID.
    27  	testKID = "testkid"
    28  )
    29  
    30  // TestNewGivenCustom tests that a custom jwt.SigningMethod can be used to create a JWKS and a proper jwt.Keyfunc.
    31  func TestNewGivenCustom(t *testing.T) {
    32  	jwt.RegisterSigningMethod(method.CustomAlg, func() jwt.SigningMethod {
    33  		return method.EmptyCustom{}
    34  	})
    35  
    36  	givenKeys := make(map[string]keyfunc.GivenKey)
    37  	key := addCustom(givenKeys, testKID)
    38  
    39  	jwks := keyfunc.NewGiven(givenKeys)
    40  
    41  	token := jwt.New(method.EmptyCustom{})
    42  	token.Header[algAttribute] = method.CustomAlg
    43  	token.Header[kidAttribute] = testKID
    44  
    45  	signParseValidate(t, token, key, jwks)
    46  }
    47  
    48  // TestNewGivenKeyECDSA tests that a generated ECDSA key can be added to the JWKS and create a proper jwt.Keyfunc.
    49  func TestNewGivenKeyECDSA(t *testing.T) {
    50  	givenKeys := make(map[string]keyfunc.GivenKey)
    51  	key, err := addECDSA(givenKeys, testKID)
    52  	if err != nil {
    53  		t.Fatalf(err.Error())
    54  	}
    55  
    56  	jwks := keyfunc.NewGiven(givenKeys)
    57  
    58  	token := jwt.New(jwt.SigningMethodES256)
    59  	token.Header[kidAttribute] = testKID
    60  
    61  	signParseValidate(t, token, key, jwks)
    62  }
    63  
    64  // TestNewGivenKeyEdDSA tests that a generated EdDSA key can be added to the JWKS and create a proper jwt.Keyfunc.
    65  func TestNewGivenKeyEdDSA(t *testing.T) {
    66  	givenKeys := make(map[string]keyfunc.GivenKey)
    67  	key, err := addEdDSA(givenKeys, testKID)
    68  	if err != nil {
    69  		t.Fatalf(err.Error())
    70  	}
    71  
    72  	jwks := keyfunc.NewGiven(givenKeys)
    73  
    74  	token := jwt.New(jwt.SigningMethodEdDSA)
    75  	token.Header[kidAttribute] = testKID
    76  
    77  	signParseValidate(t, token, key, jwks)
    78  }
    79  
    80  // TestNewGivenKeyHMAC tests that a generated HMAC key can be added to a JWKS and create a proper jwt.Keyfunc.
    81  func TestNewGivenKeyHMAC(t *testing.T) {
    82  	givenKeys := make(map[string]keyfunc.GivenKey)
    83  	key, err := addHMAC(givenKeys, testKID)
    84  	if err != nil {
    85  		t.Fatalf(err.Error())
    86  	}
    87  
    88  	jwks := keyfunc.NewGiven(givenKeys)
    89  
    90  	token := jwt.New(jwt.SigningMethodHS256)
    91  	token.Header[kidAttribute] = testKID
    92  
    93  	signParseValidate(t, token, key, jwks)
    94  }
    95  
    96  // TestNewGivenKeyRSA tests that a generated RSA key can be added to the JWKS and create a proper jwt.Keyfunc.
    97  func TestNewGivenKeyRSA(t *testing.T) {
    98  	givenKeys := make(map[string]keyfunc.GivenKey)
    99  	key, err := addRSA(givenKeys, testKID)
   100  	if err != nil {
   101  		t.Fatalf(err.Error())
   102  	}
   103  
   104  	jwks := keyfunc.NewGiven(givenKeys)
   105  
   106  	token := jwt.New(jwt.SigningMethodRS256)
   107  	token.Header[kidAttribute] = testKID
   108  
   109  	signParseValidate(t, token, key, jwks)
   110  }
   111  
   112  // addCustom adds a new key wto the given keys map. The new key is using a test jwt.SigningMethod.
   113  func addCustom(givenKeys map[string]keyfunc.GivenKey, kid string) (key string) {
   114  	key = ""
   115  	givenKeys[kid] = keyfunc.NewGivenCustom(key)
   116  	return key
   117  }
   118  
   119  // addECDSA adds a new ECDSA key to the given keys map.
   120  func addECDSA(givenKeys map[string]keyfunc.GivenKey, kid string) (key *ecdsa.PrivateKey, err error) {
   121  	key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   122  	if err != nil {
   123  		return nil, fmt.Errorf("failed to create ECDSA key: %w", err)
   124  	}
   125  
   126  	givenKeys[kid] = keyfunc.NewGivenECDSA(&key.PublicKey)
   127  
   128  	return key, nil
   129  }
   130  
   131  // addEdDSA adds a new EdDSA key to the given keys map.
   132  func addEdDSA(givenKeys map[string]keyfunc.GivenKey, kid string) (key ed25519.PrivateKey, err error) {
   133  	pub, key, err := ed25519.GenerateKey(rand.Reader)
   134  	if err != nil {
   135  		return nil, fmt.Errorf("failed to create ECDSA key: %w", err)
   136  	}
   137  
   138  	givenKeys[kid] = keyfunc.NewGivenEdDSA(pub)
   139  
   140  	return key, nil
   141  }
   142  
   143  // addHMAC creates a new HMAC secret stuff.
   144  func addHMAC(givenKeys map[string]keyfunc.GivenKey, kid string) (secret []byte, err error) {
   145  	secret = make([]byte, sha256.BlockSize)
   146  	_, err = rand.Read(secret)
   147  	if err != nil {
   148  		return nil, fmt.Errorf("failed to create HMAC secret: %w", err)
   149  	}
   150  
   151  	givenKeys[kid] = keyfunc.NewGivenHMAC(secret)
   152  
   153  	return secret, nil
   154  }
   155  
   156  // addRSA adds a new RSA key to the given keys map.
   157  func addRSA(givenKeys map[string]keyfunc.GivenKey, kid string) (key *rsa.PrivateKey, err error) {
   158  	key, err = rsa.GenerateKey(rand.Reader, 2048)
   159  	if err != nil {
   160  		return nil, fmt.Errorf("failed to create RSA key: %w", err)
   161  	}
   162  
   163  	givenKeys[kid] = keyfunc.NewGivenRSA(&key.PublicKey)
   164  
   165  	return key, nil
   166  }
   167  
   168  // signParseValidate signs the JWT, parses it using the given JWKS, then validates it.
   169  func signParseValidate(t *testing.T, token *jwt.Token, key interface{}, jwks *keyfunc.JWKS) {
   170  	jwtB64, err := token.SignedString(key)
   171  	if err != nil {
   172  		t.Fatalf(logFmt, "Failed to sign the JWT.", err)
   173  	}
   174  
   175  	parsed, err := jwt.Parse(jwtB64, jwks.Keyfunc)
   176  	if err != nil {
   177  		t.Fatalf(logFmt, "Failed to parse the JWT.", err)
   178  	}
   179  
   180  	if !parsed.Valid {
   181  		t.Fatalf("The JWT was not valid.")
   182  	}
   183  }
   184  

View as plain text