예제 #1
0
func TestHandler(t *testing.T) {
	mockKeys := mockValidKeys()
	kl := &mockKeyLoader{theKeys: mockKeys}
	h := NewHandler(kl)

	w := httptest.NewRecorder()
	r, _ := http.NewRequest("GET", "http://example.com/oauth2/v3/keys", nil)

	h.ServeHTTP(w, r)

	if w.Code != http.StatusOK {
		t.Errorf("Wrong status code. Wanted %q, got %q", http.StatusText(http.StatusOK), http.StatusText(w.Code))
	}

	jwks := new(jwk.JSONWebKeySet)
	if err := json.NewDecoder(w.Body).Decode(jwks); err != nil {
		t.Error("Failed to recover the response to a JWKS object")
	}

	m := jwks.ToMap()
	if !reflect.DeepEqual(m, mockKeys) {
		t.Error("JWKS doesn't match the original")
	}
}
예제 #2
0
// Example: https://www.googleapis.com/oauth2/v3/certs
func (kl *cachingOpenIDProviderLoader) refreshKeys() {
	log.Println("Refreshing keys..")

	log.Println("Loading configuration..")
	c, err := kl.loadConfiguration()
	if err != nil {
		log.Printf("Failed to get configuration from %q. %s\n", kl.url, err)
		return
	}

	log.Println("Configuration loaded successfully, loading JWKS..")
	resp, err := breaker.Get("loadKeys", c.JwksURI)
	if err != nil {
		log.Println("Failed to get JWKS from ", c.JwksURI)
		return
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Failed to read JWKS response body from %q: %v\n", c.JwksURI, err)
		return
	}

	log.Println("JWKS loaded successfully, parsing JWKS..")
	jwks := new(jwk.JSONWebKeySet)
	if err = json.Unmarshal(body, jwks); err != nil {
		log.Println("Failed to parse JWKS: ", err)
		return
	}

	// safety first: only remove public keys if our newly
	// received list contains at least one public key!
	// (we don't want our tokeninfo to run out of public keys
	// just because somebody cleared the provider database)
	numKeys := len(jwks.Keys)
	if numKeys < 1 {
		log.Println("No JWKS currently in the OpenID provider")
		if c, ok := metrics.DefaultRegistry.GetOrRegister(metricsNoKeysError, metrics.NewCounter).(metrics.Counter); ok {
			c.Inc(1)
		}
		return
	}

	if g, ok := metrics.DefaultRegistry.GetOrRegister(metricsNumKeys, metrics.NewGauge).(metrics.Gauge); ok {
		g.Update(int64(numKeys))
	}

	newKeys := jwks.ToMap()
	for kid, k := range newKeys {
		key := k.(jwk.JSONWebKey)
		existing := kl.keyCache.Get(kid)
		if existing == nil {
			log.Printf("Received new public key %q (%s)\n", kid, key.Algorithm)
		} else if !reflect.DeepEqual(existing, key) {
			// this is potentially dangerous: the key contents changed..
			// (but maybe the key wasn't used for signing yet, so it might be ok)
			log.Printf("Received a replacement public key for existing key %q (%s)", kid, key.Algorithm)
		}
	}

	log.Printf("Resetting key cache with %d key(s)..", numKeys)
	kl.keyCache.Reset(newKeys)
	log.Println("Refresh done..")
}