allow EndpointOpts to search catalog for Identity clients
diff --git a/openstack/client.go b/openstack/client.go
index 680a782..fdaee49 100644
--- a/openstack/client.go
+++ b/openstack/client.go
@@ -3,6 +3,7 @@
 import (
 	"fmt"
 	"net/url"
+	"reflect"
 
 	"github.com/gophercloud/gophercloud"
 	tokens2 "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens"
@@ -215,37 +216,37 @@
 
 // NewIdentityV2 creates a ServiceClient that may be used to interact with the v2 identity service.
 func NewIdentityV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
-	v2Endpoint := client.IdentityBase + "v2.0/"
-	/*
+	endpoint := client.IdentityBase + "v2.0/"
+	var err error
+	if !reflect.DeepEqual(eo, gophercloud.EndpointOpts{}) {
 		eo.ApplyDefaults("identity")
-		url, err := client.EndpointLocator(eo)
+		endpoint, err = client.EndpointLocator(eo)
 		if err != nil {
 			return nil, err
 		}
-	*/
+	}
 
 	return &gophercloud.ServiceClient{
 		ProviderClient: client,
-		Endpoint:       v2Endpoint,
-		//Endpoint: url,
+		Endpoint:       endpoint,
 	}, nil
 }
 
 // NewIdentityV3 creates a ServiceClient that may be used to access the v3 identity service.
 func NewIdentityV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
-	v3Endpoint := client.IdentityBase + "v3/"
-	/*
+	endpoint := client.IdentityBase + "v3/"
+	var err error
+	if !reflect.DeepEqual(eo, gophercloud.EndpointOpts{}) {
 		eo.ApplyDefaults("identity")
-		url, err := client.EndpointLocator(eo)
+		endpoint, err = client.EndpointLocator(eo)
 		if err != nil {
 			return nil, err
 		}
-	*/
+	}
 
 	return &gophercloud.ServiceClient{
 		ProviderClient: client,
-		Endpoint:       v3Endpoint,
-		//Endpoint: url,
+		Endpoint:       endpoint,
 	}, nil
 }
 
diff --git a/openstack/identity/v3/tokens/results.go b/openstack/identity/v3/tokens/results.go
index 7dd2c0b..d6917f9 100644
--- a/openstack/identity/v3/tokens/results.go
+++ b/openstack/identity/v3/tokens/results.go
@@ -24,17 +24,13 @@
 // Note: when looking for the desired service, try, whenever possible, to key off the type field.
 // Otherwise, you'll tie the representation of the service to a specific provider.
 type CatalogEntry struct {
-
 	// Service ID
 	ID string `json:"id"`
-
 	// Name will contain the provider-specified name for the service.
 	Name string `json:"name"`
-
 	// Type will contain a type string if OpenStack defines a type for the service.
 	// Otherwise, for provider-specific services, the provider may assign their own type strings.
 	Type string `json:"type"`
-
 	// Endpoints will let the caller iterate over all the different endpoints that may exist for
 	// the service.
 	Endpoints []Endpoint `json:"endpoints"`
@@ -60,7 +56,7 @@
 func (r commonResult) ExtractToken() (*Token, error) {
 	var s struct {
 		Token struct {
-			ExpiresAt string `json:"expires_at"`
+			ExpiresAt gophercloud.JSONRFC3339Milli `json:"expires_at"`
 		} `json:"token"`
 	}
 
@@ -74,8 +70,7 @@
 		return nil, err
 	}
 
-	// Attempt to parse the timestamp.
-	token.ExpiresAt, err = time.Parse(gophercloud.RFC3339Milli, s.Token.ExpiresAt)
+	token.ExpiresAt = time.Time(s.Token.ExpiresAt)
 
 	return &token, err
 }
diff --git a/openstack/testing/client_test.go b/openstack/testing/client_test.go
index 37e63c1..93f4d7c 100644
--- a/openstack/testing/client_test.go
+++ b/openstack/testing/client_test.go
@@ -10,12 +10,12 @@
 	th "github.com/gophercloud/gophercloud/testhelper"
 )
 
+const ID = "0123456789"
+
 func TestAuthenticatedClientV3(t *testing.T) {
 	th.SetupHTTP()
 	defer th.TeardownHTTP()
 
-	const ID = "0123456789"
-
 	th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
 		fmt.Fprintf(w, `
 			{
@@ -160,3 +160,132 @@
 	th.AssertNoErr(t, err)
 	th.CheckEquals(t, "01234567890", client.TokenID)
 }
+
+func TestIdentityAdminV3Client(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+		fmt.Fprintf(w, `
+			{
+				"versions": {
+					"values": [
+						{
+							"status": "stable",
+							"id": "v3.0",
+							"links": [
+								{ "href": "%s", "rel": "self" }
+							]
+						},
+						{
+							"status": "stable",
+							"id": "v2.0",
+							"links": [
+								{ "href": "%s", "rel": "self" }
+							]
+						}
+					]
+				}
+			}
+		`, th.Endpoint()+"v3/", th.Endpoint()+"v2.0/")
+	})
+
+	th.Mux.HandleFunc("/v3/auth/tokens", func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Add("X-Subject-Token", ID)
+
+		w.WriteHeader(http.StatusCreated)
+		fmt.Fprintf(w, `
+	{
+    "token": {
+        "audit_ids": ["VcxU2JYqT8OzfUVvrjEITQ", "qNUTIJntTzO1-XUk5STybw"],
+        "catalog": [
+            {
+                "endpoints": [
+                    {
+                        "id": "39dc322ce86c4111b4f06c2eeae0841b",
+                        "interface": "public",
+                        "region": "RegionOne",
+                        "url": "http://localhost:5000"
+                    },
+                    {
+                        "id": "ec642f27474842e78bf059f6c48f4e99",
+                        "interface": "internal",
+                        "region": "RegionOne",
+                        "url": "http://localhost:5000"
+                    },
+                    {
+                        "id": "c609fc430175452290b62a4242e8a7e8",
+                        "interface": "admin",
+                        "region": "RegionOne",
+                        "url": "http://localhost:35357"
+                    }
+                ],
+                "id": "4363ae44bdf34a3981fde3b823cb9aa2",
+                "type": "identity",
+                "name": "keystone"
+            }
+        ],
+        "expires_at": "2013-02-27T18:30:59.999999Z",
+        "is_domain": false,
+        "issued_at": "2013-02-27T16:30:59.999999Z",
+        "methods": [
+            "password"
+        ],
+        "project": {
+            "domain": {
+                "id": "1789d1",
+                "name": "example.com"
+            },
+            "id": "263fd9",
+            "name": "project-x"
+        },
+        "roles": [
+            {
+                "id": "76e72a",
+                "name": "admin"
+            },
+            {
+                "id": "f4f392",
+                "name": "member"
+            }
+        ],
+        "service_providers": [
+            {
+                "auth_url":"https://example.com:5000/v3/OS-FEDERATION/identity_providers/acme/protocols/saml2/auth",
+                "id": "sp1",
+                "sp_url": "https://example.com:5000/Shibboleth.sso/SAML2/ECP"
+            },
+            {
+                "auth_url":"https://other.example.com:5000/v3/OS-FEDERATION/identity_providers/acme/protocols/saml2/auth",
+                "id": "sp2",
+                "sp_url": "https://other.example.com:5000/Shibboleth.sso/SAML2/ECP"
+            }
+        ],
+        "user": {
+            "domain": {
+                "id": "1789d1",
+                "name": "example.com"
+            },
+            "id": "0ca8f6",
+            "name": "Joe",
+            "password_expires_at": "2016-11-06T15:32:17.000000"
+        }
+    }
+}
+	`)
+	})
+
+	options := gophercloud.AuthOptions{
+		Username:         "me",
+		Password:         "secret",
+		DomainID:         "12345",
+		IdentityEndpoint: th.Endpoint(),
+	}
+	pc, err := openstack.AuthenticatedClient(options)
+	th.AssertNoErr(t, err)
+	sc, err := openstack.NewIdentityV3(pc, gophercloud.EndpointOpts{
+		Availability: gophercloud.AvailabilityAdmin,
+	})
+	th.AssertNoErr(t, err)
+	th.CheckEquals(t, "http://localhost:35357/", sc.Endpoint)
+}