2019-02-20 19:59:22 +00:00
|
|
|
package fetch
|
2019-02-08 01:26:45 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/ecdsa"
|
|
|
|
"crypto/rsa"
|
|
|
|
"errors"
|
|
|
|
"testing"
|
2019-02-20 19:26:37 +00:00
|
|
|
"time"
|
2019-02-20 19:59:22 +00:00
|
|
|
|
|
|
|
keypairs "github.com/big-squid/go-keypairs"
|
2019-02-08 01:26:45 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestFetchOIDCPublicKeys(t *testing.T) {
|
|
|
|
urls := []string{
|
|
|
|
//"https://bigsquid.auth0.com/.well-known/jwks.json",
|
|
|
|
"https://bigsquid.auth0.com/",
|
|
|
|
}
|
|
|
|
for i := range urls {
|
|
|
|
url := urls[i]
|
2019-02-19 23:50:46 +00:00
|
|
|
_, keys, err := fetchOIDCPublicKeys(url)
|
2019-02-08 01:26:45 +00:00
|
|
|
if nil != err {
|
|
|
|
t.Fatal(url, err)
|
|
|
|
}
|
|
|
|
|
2019-02-08 23:53:29 +00:00
|
|
|
for kid := range keys {
|
|
|
|
switch key := keys[kid].Key().(type) {
|
2019-02-08 01:26:45 +00:00
|
|
|
case *rsa.PublicKey:
|
2019-02-20 19:59:22 +00:00
|
|
|
_ = keypairs.ThumbprintRSAPublicKey(key)
|
2019-02-08 01:26:45 +00:00
|
|
|
case *ecdsa.PublicKey:
|
2019-02-20 19:59:22 +00:00
|
|
|
_ = keypairs.ThumbprintECPublicKey(key)
|
2019-02-08 01:26:45 +00:00
|
|
|
default:
|
|
|
|
t.Fatal(errors.New("unsupported interface type"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-02-19 23:50:46 +00:00
|
|
|
|
|
|
|
func TestCachesKey(t *testing.T) {
|
2019-02-20 19:26:37 +00:00
|
|
|
url := "https://bigsquid.auth0.com/"
|
|
|
|
|
2019-02-19 23:50:46 +00:00
|
|
|
// Raw fetch a key and get KID and Thumbprint
|
2019-02-20 19:26:37 +00:00
|
|
|
_, keys, err := fetchOIDCPublicKeys(url)
|
|
|
|
if nil != err {
|
|
|
|
t.Fatal(url, err)
|
|
|
|
}
|
|
|
|
if 0 == len(keys) {
|
|
|
|
t.Fatal("Should discover 1 or more keys via", url)
|
|
|
|
}
|
|
|
|
|
2019-02-20 19:59:22 +00:00
|
|
|
var key keypairs.PublicKey
|
2019-02-20 19:26:37 +00:00
|
|
|
for i := range keys {
|
|
|
|
key = keys[i]
|
|
|
|
break
|
|
|
|
}
|
|
|
|
thumb := key.Thumbprint()
|
|
|
|
|
2019-02-19 23:50:46 +00:00
|
|
|
// Look in cache for each (and fail)
|
2019-02-20 19:26:37 +00:00
|
|
|
if _, ok := hasPublicKeyByThumbprint(thumb); ok {
|
|
|
|
t.Fatal("SANITY: Should not have any key cached by thumbprint")
|
|
|
|
}
|
|
|
|
if _, ok := hasPublicKey(key.KeyID(), url); ok {
|
|
|
|
t.Fatal("SANITY: Should not have any key cached by kid")
|
|
|
|
}
|
|
|
|
|
2019-02-19 23:50:46 +00:00
|
|
|
// Get with caching
|
2019-02-20 19:26:37 +00:00
|
|
|
k2, err := GetPublicKey(thumb, url)
|
|
|
|
if nil != err {
|
|
|
|
t.Fatal("Error fetching and caching key:", err)
|
|
|
|
}
|
|
|
|
|
2019-02-19 23:50:46 +00:00
|
|
|
// Look in cache for each (and succeed)
|
2019-02-20 19:26:37 +00:00
|
|
|
if _, ok := hasPublicKeyByThumbprint(thumb); !ok {
|
|
|
|
t.Fatal("key was not properly cached by thumbprint")
|
|
|
|
}
|
|
|
|
if "" != k2.KeyID() {
|
|
|
|
if _, ok := hasPublicKeyByThumbprint(thumb); !ok {
|
|
|
|
t.Fatal("key was not properly cached by thumbprint")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t.Log("Key did not have an explicit KeyID")
|
|
|
|
}
|
|
|
|
|
2019-02-19 23:50:46 +00:00
|
|
|
// Get again (should be sub-ms instant)
|
2019-02-20 19:26:37 +00:00
|
|
|
now := time.Now()
|
|
|
|
_, err = GetPublicKey(thumb, url)
|
|
|
|
if nil != err {
|
|
|
|
t.Fatal("SANITY: Failed to get the key we just got...", err)
|
|
|
|
}
|
|
|
|
if time.Now().Sub(now) > time.Millisecond {
|
|
|
|
t.Fatal("Failed to cache key by thumbprint...", time.Now().Sub(now))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sanity check that the kid and thumb match
|
|
|
|
if key.KeyID() != k2.KeyID() || key.Thumbprint() != k2.Thumbprint() {
|
|
|
|
t.Fatal("SANITY: KeyIDs or Thumbprints do not match:", key.KeyID(), k2.KeyID(), key.Thumbprint(), k2.Thumbprint())
|
|
|
|
}
|
2019-02-19 23:50:46 +00:00
|
|
|
}
|