hipchat: Generate Config for Connect integrations

Adds a function to generate a clientcredentials.Config from a HipChat
Connect addon's capability descriptor and a provided application secret.
Useful when writing addons.

Change-Id: I4578f5683aa9ed728e503cb3b08ff0bf743a62a4
Reviewed-on: https://go-review.googlesource.com/22397
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/hipchat/hipchat.go b/hipchat/hipchat.go
index d061c56..594fe07 100644
--- a/hipchat/hipchat.go
+++ b/hipchat/hipchat.go
@@ -6,7 +6,11 @@
 package hipchat // import "golang.org/x/oauth2/hipchat"
 
 import (
+	"encoding/json"
+	"errors"
+
 	"golang.org/x/oauth2"
+	"golang.org/x/oauth2/clientcredentials"
 )
 
 // Endpoint is HipChat's OAuth 2.0 endpoint.
@@ -23,3 +27,34 @@
 		TokenURL: "https://" + host + "/v2/oauth/token",
 	}
 }
+
+// ClientCredentialsConfigFromCaps generates a Config from a HipChat API
+// capabilities descriptor. It does not verify the scopes against the
+// capabilities document at this time.
+//
+// For more information see: https://www.hipchat.com/docs/apiv2/method/get_capabilities
+func ClientCredentialsConfigFromCaps(capsJSON []byte, clientID, clientSecret string, scopes ...string) (*clientcredentials.Config, error) {
+	var caps struct {
+		Caps struct {
+			Endpoint struct {
+				TokenURL string `json:"tokenUrl"`
+			} `json:"oauth2Provider"`
+		} `json:"capabilities"`
+	}
+
+	if err := json.Unmarshal(capsJSON, &caps); err != nil {
+		return nil, err
+	}
+
+	// Verify required fields.
+	if caps.Caps.Endpoint.TokenURL == "" {
+		return nil, errors.New("oauth2/hipchat: missing OAuth2 token URL in the capabilities descriptor JSON")
+	}
+
+	return &clientcredentials.Config{
+		ClientID:     clientID,
+		ClientSecret: clientSecret,
+		Scopes:       scopes,
+		TokenURL:     caps.Caps.Endpoint.TokenURL,
+	}, nil
+}