veyron/services/identity: Code cleanup

- Collapse multiple options into a single, more understandable one
- Remove some dead code
- Get rid of "--generate" and "--identity" flags from identityd
  so that we don't have multiple programs that can generate identities.

Change-Id: I9e34e96708450e40bb43ea8a086523dd963ca304
diff --git a/services/identity/googleoauth/handler.go b/services/identity/googleoauth/handler.go
index 2ce6fee..6ddc455 100644
--- a/services/identity/googleoauth/handler.go
+++ b/services/identity/googleoauth/handler.go
@@ -26,14 +26,11 @@
 )
 
 type HandlerArgs struct {
-	// Whether the HTTP server is using TLS or not.
-	UseTLS bool
-	// Fully-qualified address (host:port) that the HTTP server is
-	// listening on (and where redirect requests from Google will come to).
+	// URL at which the hander is installed.
+	// e.g. http://host:port/google/
+	// This is where the handler is installed and where redirect requests
+	// from Google will come to.
 	Addr string
-	// Address prefix (including trailing slash) on which the Google OAuth
-	// based Identity generator should run.
-	Prefix string
 	// client_id and client_secret registered with the Google Developer
 	// Console for API access.
 	ClientID, ClientSecret string
@@ -47,24 +44,19 @@
 	RestrictEmailDomain string
 }
 
-func (a *HandlerArgs) redirectURL() string {
-	scheme := "http"
-	if a.UseTLS {
-		scheme = "https"
-	}
-	return fmt.Sprintf("%s://%s%soauth2callback", scheme, a.Addr, a.Prefix)
-}
+func (a *HandlerArgs) redirectURL() string { return path.Join(a.Addr, "oauth2callback") }
 
-// URL used to verify GoogleIDTokens.
-// (From https://developers.google.com/accounts/docs/OAuth2Login#validatinganidtoken)
-const VerifyURL = "https://www.googleapis.com/oauth2/v1/tokeninfo?id_token="
+// URL used to verify google tokens.
+// (From https://developers.google.com/accounts/docs/OAuth2Login#validatinganidtoken
+// and https://developers.google.com/accounts/docs/OAuth2UserAgent#validatetoken)
+const verifyURL = "https://www.googleapis.com/oauth2/v1/tokeninfo?"
 
-// NewHandler returns an http.Handler that expects to be rooted at args.Prefix
+// NewHandler returns an http.Handler that expects to be rooted at args.Addr
 // and can be used to use OAuth 2.0 to authenticate with Google, mint a new
 // identity and bless it with the Google email address.
 func NewHandler(args HandlerArgs) http.Handler {
 	config := NewOAuthConfig(args.ClientID, args.ClientSecret, args.redirectURL())
-	return &handler{config, args.Addr, args.MinExpiryDays, util.NewCSRFCop(), args.Runtime, args.RestrictEmailDomain}
+	return &handler{config, args.MinExpiryDays, util.NewCSRFCop(), args.Runtime, args.RestrictEmailDomain}
 }
 
 // NewOAuthConfig returns the oauth.Config required for obtaining just the email address from Google using OAuth 2.0.
@@ -81,7 +73,6 @@
 
 type handler struct {
 	config        *oauth.Config
-	issuer        string
 	minExpiryDays int
 	csrfCop       *util.CSRFCop
 	rt            veyron2.Runtime
@@ -158,9 +149,9 @@
 	if t.Extra == nil || len(t.Extra["id_token"]) == 0 {
 		return "", fmt.Errorf("no GoogleIDToken found in OAuth token")
 	}
-	tinfo, err := http.Get(VerifyURL + t.Extra["id_token"])
+	tinfo, err := http.Get(verifyURL + "id_token=" + t.Extra["id_token"])
 	if err != nil {
-		return "", fmt.Errorf("failed to talk to GoogleIDToken verifier (%q): %v", VerifyURL, err)
+		return "", fmt.Errorf("failed to talk to GoogleIDToken verifier (%q): %v", verifyURL, err)
 	}
 	if tinfo.StatusCode != http.StatusOK {
 		return "", fmt.Errorf("failed to verify GoogleIDToken: %s", tinfo.Status)
diff --git a/services/identity/identityd/main.go b/services/identity/identityd/main.go
index ad17360..39d3b9d 100644
--- a/services/identity/identityd/main.go
+++ b/services/identity/identityd/main.go
@@ -15,7 +15,6 @@
 	"veyron/services/identity/blesser"
 	"veyron/services/identity/googleoauth"
 	"veyron/services/identity/handlers"
-	"veyron/services/identity/util"
 	"veyron2"
 	"veyron2/ipc"
 	"veyron2/rt"
@@ -34,10 +33,7 @@
 
 	googleConfigWeb       = flag.String("google_config_web", "", "Path to the JSON-encoded file containing the ClientID for web applications registered with the Google Developer Console. (Use the 'Download JSON' link on the Google APIs console).")
 	googleConfigInstalled = flag.String("google_config_installed", "", "Path to the JSON-encoded file containing the ClientID for installed applications registered with the Google Developer console. (Use the 'Download JSON' link on the Google APIs console).")
-
-	googleDomain = flag.String("google_domain", "", "An optional domain name. When set, only email addresses from this domain are allowed to authenticate via Google OAuth")
-	generate     = flag.String("generate", "", "If non-empty, instead of running an HTTP server, a new identity will be created with the provided name and saved to --identity (if specified) and dumped to STDOUT in base64-encoded-vom")
-	identity     = flag.String("identity", "", "Path to the file where the VOM-encoded security.PrivateID created with --generate will be written.")
+	googleDomain          = flag.String("google_domain", "", "An optional domain name. When set, only email addresses from this domain are allowed to authenticate via Google OAuth")
 )
 
 func main() {
@@ -46,11 +42,6 @@
 	r := rt.Init()
 	defer r.Cleanup()
 
-	if len(*generate) > 0 {
-		generateAndSaveIdentity()
-		return
-	}
-
 	// Setup handlers
 	http.Handle("/pubkey/", handlers.Object{r.Identity().PublicID().PublicKey()}) // public key of this identity server
 	if enableRandomHandler() {
@@ -68,15 +59,9 @@
 		defer ipcServer.Stop()
 	}
 	if enabled, clientID, clientSecret := enableGoogleOAuth(*googleConfigWeb); enabled {
-		_, port, err := net.SplitHostPort(*httpaddr)
-		if err != nil {
-			vlog.Fatalf("Failed to parse %q: %v", *httpaddr, err)
-		}
 		n := "/google/"
 		http.Handle(n, googleoauth.NewHandler(googleoauth.HandlerArgs{
-			UseTLS:              enableTLS(),
-			Addr:                fmt.Sprintf("%s:%s", *host, port),
-			Prefix:              n,
+			Addr:                fmt.Sprintf("%s%s", httpaddress(), n),
 			ClientID:            clientID,
 			ClientSecret:        clientSecret,
 			MinExpiryDays:       *minExpiryDays,
@@ -101,6 +86,7 @@
 			vlog.Info("Failed to render template:", err)
 		}
 	})
+	vlog.Infof("Running HTTP server at: %v", httpaddress())
 	go runHTTPServer(*httpaddr)
 	<-signals.ShutdownOnSignals()
 }
@@ -144,7 +130,6 @@
 
 func runHTTPServer(addr string) {
 	if !enableTLS() {
-		vlog.Infof("Starting HTTP server (without TLS) at http://%v", addr)
 		if err := http.ListenAndServe(addr, nil); err != nil {
 			vlog.Fatalf("http.ListenAndServe failed: %v", err)
 		}
@@ -166,6 +151,10 @@
 To generate TLS certificates so the HTTP server can use SSL:
 go run $GOROOT/src/pkg/crypto/tls/generate_cert.go --host <IP address>
 
+To generate an identity for this service itself, use:
+go install veyron/tools/identity && ./bin/identity generate <name> ><filename>
+and set the VEYRON_IDENTITY environment variable when running this application.
+
 To enable use of Google APIs to use Google OAuth for authorization, set --google_config,
 which must point to the contents of a JSON file obtained after registering your application
 with the Google Developer Console at:
@@ -186,33 +175,16 @@
 	return host
 }
 
-func generateAndSaveIdentity() {
-	id, err := rt.R().NewIdentity(*generate)
+func httpaddress() string {
+	_, port, err := net.SplitHostPort(*httpaddr)
 	if err != nil {
-		vlog.Fatalf("Runtime.NewIdentity(%q) failed: %v", *generate, err)
+		vlog.Fatalf("Failed to parse %q: %v", *httpaddr, err)
 	}
-	if len(*identity) > 0 {
-		if err = saveIdentity(*identity, id); err != nil {
-			vlog.Fatalf("SaveIdentity %v: %v", *identity, err)
-		}
+	scheme := "http"
+	if enableTLS() {
+		scheme = "https"
 	}
-	b64, err := util.Base64VomEncode(id)
-	if err != nil {
-		vlog.Fatalf("Base64VomEncode(%q) failed: %v", id, err)
-	}
-	fmt.Println(b64)
-}
-
-func saveIdentity(filePath string, id security.PrivateID) error {
-	f, err := os.OpenFile(filePath, os.O_WRONLY, 0600)
-	if err != nil {
-		return err
-	}
-	defer f.Close()
-	if err := security.SaveIdentity(f, id); err != nil {
-		return err
-	}
-	return nil
+	return fmt.Sprintf("%s://%s:%v", scheme, *host, port)
 }
 
 var tmpl = template.Must(template.New("main").Parse(`<!doctype html>
diff --git a/tools/identity/main.go b/tools/identity/main.go
index 861d85f..bdc007f 100644
--- a/tools/identity/main.go
+++ b/tools/identity/main.go
@@ -219,7 +219,7 @@
 				if err != nil {
 					vlog.Infof("Failed to get blessing from %q: %v, will try again in %v", flagSeekBlessingFrom, err, wait)
 					time.Sleep(wait)
-					if wait = wait + 2; wait > maxWait {
+					if wait = wait + 2*time.Second; wait > maxWait {
 						wait = maxWait
 					}
 					continue