Shuffle around authentication methods.

I'd like to be able to explicitly authenticated with a certain version.
diff --git a/openstack/client.go b/openstack/client.go
index 7e3850e..98092c8 100644
--- a/openstack/client.go
+++ b/openstack/client.go
@@ -18,46 +18,84 @@
 	v30 = "v3.0"
 )
 
-// NewClient authenticates to an OpenStack cloud with the provided credentials.
+// AuthenticatedClient logs in to an OpenStack cloud found at the identity endpoint specified by authOptions, acquires a token, and
+// returns a Client instance that's ready to operate.
 // It first queries the root identity endpoint to determine which versions of the identity service are supported, then chooses
 // the most recent identity service available to proceed.
-func NewClient(authOptions gophercloud.AuthOptions) (*Client, error) {
+func AuthenticatedClient(authOptions gophercloud.AuthOptions) (*Client, error) {
+	client := NewClient(authOptions)
+	err := client.Authenticate()
+	if err != nil {
+		return nil, err
+	}
+	return client, nil
+}
+
+// NewClient prepares an unauthenticated Client instance.
+// Most users will probably prefer using the AuthenticatedClient function instead.
+// This is useful if you wish to explicitly control the version of the identity service that's used for authentication explicitly,
+// for example.
+func NewClient(authOptions gophercloud.AuthOptions) *Client {
+	return &Client{
+		ProviderClient: gophercloud.ProviderClient{
+			Options: authOptions,
+		},
+	}
+}
+
+// Authenticate or re-authenticate against the most recent identity service supported at the provided endpoint.
+func (client *Client) Authenticate() error {
 	versions := []*utils.Version{
 		&utils.Version{ID: v20, Priority: 20},
 		&utils.Version{ID: v30, Priority: 30},
 	}
 
-	chosen, endpoint, err := utils.ChooseVersion(authOptions.IdentityEndpoint, versions)
+	chosen, endpoint, err := utils.ChooseVersion(client.ProviderClient.Options.IdentityEndpoint, versions)
 	if err != nil {
-		return nil, err
-	}
-
-	client := Client{
-		ProviderClient: gophercloud.ProviderClient{
-			IdentityEndpoint: endpoint,
-			Options:          authOptions,
-		},
+		return err
 	}
 
 	switch chosen.ID {
 	case v20:
+		return client.authenticateV2(endpoint)
 	case v30:
-		identityClient := identity3.NewClient(&client.ProviderClient)
-		token, err := identityClient.Authenticate(authOptions)
-		if err != nil {
-			return nil, err
-		}
-
-		client.ProviderClient.TokenID = token.ID
+		return client.authenticateV3(endpoint)
 	default:
-		// The switch must be out of sync with "versions".
-		return nil, errors.New("Wat")
+		// The switch statement must be out of date from the versions list.
+		return errors.New("Wat")
+	}
+}
+
+// AuthenticateV2 acquires a token explicitly from the v2.0 identity API.
+func (client *Client) AuthenticateV2() error {
+	endpoint := client.ProviderClient.Options.IdentityEndpoint + "/v2.0"
+	return client.authenticateV2(endpoint)
+}
+
+func (client *Client) authenticateV2(endpoint string) error {
+	return errors.New("Not implemented yet.")
+}
+
+// AuthenticateV3 acquires a token explicitly from the v3.0 identity API.
+func (client *Client) AuthenticateV3() error {
+	endpoint := client.ProviderClient.Options.IdentityEndpoint + "/v3"
+	return client.authenticateV3(endpoint)
+}
+
+func (client *Client) authenticateV3(endpoint string) error {
+	identityClient := identity3.NewClient(&client.ProviderClient, endpoint)
+	token, err := identityClient.GetToken(client.ProviderClient.Options)
+	if err != nil {
+		return err
 	}
 
-	return &client, nil
+	client.ProviderClient.TokenID = token.ID
+
+	return nil
 }
 
 // NewIdentityV3 explicitly accesses the v3 identity service.
 func (client *Client) NewIdentityV3() (*identity3.Client, error) {
-	return identity3.NewClient(&client.ProviderClient), nil
+	endpoint := client.ProviderClient.Options.IdentityEndpoint + "/v3"
+	return identity3.NewClient(&client.ProviderClient, endpoint), nil
 }