Identity v3 Authentication With TrustID (#24)

* delete auth_results

* v3 auth with trust

* define auth errors in gophercloud pkg

* AuthOptionsBuilder interface

* combine error files in gophercloud pkg
diff --git a/auth_options.go b/auth_options.go
index 2ef427a..3ee97df 100644
--- a/auth_options.go
+++ b/auth_options.go
@@ -47,11 +47,11 @@
 	// The way to limit the number of attempts is to provide a custom HTTP client to the provider client
 	// and provide a transport that implements the RoundTripper interface and stores the number of failed retries.
 	// For an example of this, see here: https://github.com/rackspace/rack/blob/1.0.0/auth/clients.go#L311
-	AllowReauth bool
+	AllowReauth bool `json:"-"`
 
 	// TokenID allows users to authenticate (possibly as another user) with an
 	// authentication token ID.
-	TokenID string
+	TokenID string `json:"-"`
 }
 
 // ToTokenV2CreateMap allows AuthOptions to satisfy the AuthOptionsBuilder
@@ -86,3 +86,246 @@
 
 	return map[string]interface{}{"auth": authMap}, nil
 }
+
+func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) {
+	type domainReq struct {
+		ID   *string `json:"id,omitempty"`
+		Name *string `json:"name,omitempty"`
+	}
+
+	type projectReq struct {
+		Domain *domainReq `json:"domain,omitempty"`
+		Name   *string    `json:"name,omitempty"`
+		ID     *string    `json:"id,omitempty"`
+	}
+
+	type userReq struct {
+		ID       *string    `json:"id,omitempty"`
+		Name     *string    `json:"name,omitempty"`
+		Password string     `json:"password"`
+		Domain   *domainReq `json:"domain,omitempty"`
+	}
+
+	type passwordReq struct {
+		User userReq `json:"user"`
+	}
+
+	type tokenReq struct {
+		ID string `json:"id"`
+	}
+
+	type identityReq struct {
+		Methods  []string     `json:"methods"`
+		Password *passwordReq `json:"password,omitempty"`
+		Token    *tokenReq    `json:"token,omitempty"`
+	}
+
+	type authReq struct {
+		Identity identityReq `json:"identity"`
+	}
+
+	type request struct {
+		Auth authReq `json:"auth"`
+	}
+
+	// Populate the request structure based on the provided arguments. Create and return an error
+	// if insufficient or incompatible information is present.
+	var req request
+
+	// Test first for unrecognized arguments.
+	if opts.TenantID != "" {
+		return nil, ErrTenantIDProvided{}
+	}
+	if opts.TenantName != "" {
+		return nil, ErrTenantNameProvided{}
+	}
+
+	if opts.Password == "" {
+		if opts.TokenID != "" {
+			// Because we aren't using password authentication, it's an error to also provide any of the user-based authentication
+			// parameters.
+			if opts.Username != "" {
+				return nil, ErrUsernameWithToken{}
+			}
+			if opts.UserID != "" {
+				return nil, ErrUserIDWithToken{}
+			}
+			if opts.DomainID != "" {
+				return nil, ErrDomainIDWithToken{}
+			}
+			if opts.DomainName != "" {
+				return nil, ErrDomainNameWithToken{}
+			}
+
+			// Configure the request for Token authentication.
+			req.Auth.Identity.Methods = []string{"token"}
+			req.Auth.Identity.Token = &tokenReq{
+				ID: opts.TokenID,
+			}
+		} else {
+			// If no password or token ID are available, authentication can't continue.
+			return nil, ErrMissingPassword{}
+		}
+	} else {
+		// Password authentication.
+		req.Auth.Identity.Methods = []string{"password"}
+
+		// At least one of Username and UserID must be specified.
+		if opts.Username == "" && opts.UserID == "" {
+			return nil, ErrUsernameOrUserID{}
+		}
+
+		if opts.Username != "" {
+			// If Username is provided, UserID may not be provided.
+			if opts.UserID != "" {
+				return nil, ErrUsernameOrUserID{}
+			}
+
+			// Either DomainID or DomainName must also be specified.
+			if opts.DomainID == "" && opts.DomainName == "" {
+				return nil, ErrDomainIDOrDomainName{}
+			}
+
+			if opts.DomainID != "" {
+				if opts.DomainName != "" {
+					return nil, ErrDomainIDOrDomainName{}
+				}
+
+				// Configure the request for Username and Password authentication with a DomainID.
+				req.Auth.Identity.Password = &passwordReq{
+					User: userReq{
+						Name:     &opts.Username,
+						Password: opts.Password,
+						Domain:   &domainReq{ID: &opts.DomainID},
+					},
+				}
+			}
+
+			if opts.DomainName != "" {
+				// Configure the request for Username and Password authentication with a DomainName.
+				req.Auth.Identity.Password = &passwordReq{
+					User: userReq{
+						Name:     &opts.Username,
+						Password: opts.Password,
+						Domain:   &domainReq{Name: &opts.DomainName},
+					},
+				}
+			}
+		}
+
+		if opts.UserID != "" {
+			// If UserID is specified, neither DomainID nor DomainName may be.
+			if opts.DomainID != "" {
+				return nil, ErrDomainIDWithUserID{}
+			}
+			if opts.DomainName != "" {
+				return nil, ErrDomainNameWithUserID{}
+			}
+
+			// Configure the request for UserID and Password authentication.
+			req.Auth.Identity.Password = &passwordReq{
+				User: userReq{ID: &opts.UserID, Password: opts.Password},
+			}
+		}
+	}
+
+	b, err := BuildRequestBody(req, "")
+	if err != nil {
+		return nil, err
+	}
+
+	if len(scope) != 0 {
+		b["auth"].(map[string]interface{})["scope"] = scope
+	}
+
+	return b, nil
+}
+
+func (opts *AuthOptions) ToTokenV3ScopeMap() (map[string]interface{}, error) {
+
+	var scope struct {
+		ProjectID   string
+		ProjectName string
+		DomainID    string
+		DomainName  string
+	}
+
+	if opts.TenantID != "" {
+		scope.ProjectID = opts.TenantID
+		opts.TenantID = ""
+		opts.TenantName = ""
+	} else {
+		if opts.TenantName != "" {
+			scope.ProjectName = opts.TenantName
+			scope.DomainID = opts.DomainID
+			scope.DomainName = opts.DomainName
+		}
+		opts.TenantName = ""
+	}
+
+	if scope.ProjectName != "" {
+		// ProjectName provided: either DomainID or DomainName must also be supplied.
+		// ProjectID may not be supplied.
+		if scope.DomainID == "" && scope.DomainName == "" {
+			return nil, ErrScopeDomainIDOrDomainName{}
+		}
+		if scope.ProjectID != "" {
+			return nil, ErrScopeProjectIDOrProjectName{}
+		}
+
+		if scope.DomainID != "" {
+			// ProjectName + DomainID
+			return map[string]interface{}{
+				"project": map[string]interface{}{
+					"name":   &scope.ProjectName,
+					"domain": map[string]interface{}{"id": &scope.DomainID},
+				},
+			}, nil
+		}
+
+		if scope.DomainName != "" {
+			// ProjectName + DomainName
+			return map[string]interface{}{
+				"project": map[string]interface{}{
+					"name":   &scope.ProjectName,
+					"domain": map[string]interface{}{"name": &scope.DomainName},
+				},
+			}, nil
+		}
+	} else if scope.ProjectID != "" {
+		// ProjectID provided. ProjectName, DomainID, and DomainName may not be provided.
+		if scope.DomainID != "" {
+			return nil, ErrScopeProjectIDAlone{}
+		}
+		if scope.DomainName != "" {
+			return nil, ErrScopeProjectIDAlone{}
+		}
+
+		// ProjectID
+		return map[string]interface{}{
+			"project": map[string]interface{}{
+				"id": &scope.ProjectID,
+			},
+		}, nil
+	} else if scope.DomainID != "" {
+		// DomainID provided. ProjectID, ProjectName, and DomainName may not be provided.
+		if scope.DomainName != "" {
+			return nil, ErrScopeDomainIDOrDomainName{}
+		}
+
+		// DomainID
+		return map[string]interface{}{
+			"domain": map[string]interface{}{
+				"id": &scope.DomainID,
+			},
+		}, nil
+	} else if scope.DomainName != "" {
+		return nil, ErrScopeDomainName{}
+	}
+
+	return nil, nil
+}
+
+func (opts AuthOptions) CanReauth() bool {
+	return opts.AllowReauth
+}
diff --git a/auth_results.go b/auth_results.go
deleted file mode 100644
index 856a233..0000000
--- a/auth_results.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package gophercloud
-
-import "time"
-
-// AuthResults [deprecated] is a leftover type from the v0.x days. It was
-// intended to describe common functionality among identity service results, but
-// is not actually used anywhere.
-type AuthResults interface {
-	// TokenID returns the token's ID value from the authentication response.
-	TokenID() (string, error)
-
-	// ExpiresAt retrieves the token's expiration time.
-	ExpiresAt() (time.Time, error)
-}
diff --git a/errors.go b/errors.go
index 978fcb5..e0fe7c1 100644
--- a/errors.go
+++ b/errors.go
@@ -274,3 +274,135 @@
 	e.DefaultErrString = fmt.Sprintf("Expected %s but got %s", e.Expected, e.Actual)
 	return e.choseErrString()
 }
+
+func unacceptedAttributeErr(attribute string) string {
+	return fmt.Sprintf("The base Identity V3 API does not accept authentication by %s", attribute)
+}
+
+func redundantWithTokenErr(attribute string) string {
+	return fmt.Sprintf("%s may not be provided when authenticating with a TokenID", attribute)
+}
+
+func redundantWithUserID(attribute string) string {
+	return fmt.Sprintf("%s may not be provided when authenticating with a UserID", attribute)
+}
+
+// ErrAPIKeyProvided indicates that an APIKey was provided but can't be used.
+type ErrAPIKeyProvided struct{ BaseError }
+
+func (e ErrAPIKeyProvided) Error() string {
+	return unacceptedAttributeErr("APIKey")
+}
+
+// ErrTenantIDProvided indicates that a TenantID was provided but can't be used.
+type ErrTenantIDProvided struct{ BaseError }
+
+func (e ErrTenantIDProvided) Error() string {
+	return unacceptedAttributeErr("TenantID")
+}
+
+// ErrTenantNameProvided indicates that a TenantName was provided but can't be used.
+type ErrTenantNameProvided struct{ BaseError }
+
+func (e ErrTenantNameProvided) Error() string {
+	return unacceptedAttributeErr("TenantName")
+}
+
+// ErrUsernameWithToken indicates that a Username was provided, but token authentication is being used instead.
+type ErrUsernameWithToken struct{ BaseError }
+
+func (e ErrUsernameWithToken) Error() string {
+	return redundantWithTokenErr("Username")
+}
+
+// ErrUserIDWithToken indicates that a UserID was provided, but token authentication is being used instead.
+type ErrUserIDWithToken struct{ BaseError }
+
+func (e ErrUserIDWithToken) Error() string {
+	return redundantWithTokenErr("UserID")
+}
+
+// ErrDomainIDWithToken indicates that a DomainID was provided, but token authentication is being used instead.
+type ErrDomainIDWithToken struct{ BaseError }
+
+func (e ErrDomainIDWithToken) Error() string {
+	return redundantWithTokenErr("DomainID")
+}
+
+// ErrDomainNameWithToken indicates that a DomainName was provided, but token authentication is being used instead.s
+type ErrDomainNameWithToken struct{ BaseError }
+
+func (e ErrDomainNameWithToken) Error() string {
+	return redundantWithTokenErr("DomainName")
+}
+
+// ErrUsernameOrUserID indicates that neither username nor userID are specified, or both are at once.
+type ErrUsernameOrUserID struct{ BaseError }
+
+func (e ErrUsernameOrUserID) Error() string {
+	return "Exactly one of Username and UserID must be provided for password authentication"
+}
+
+// ErrDomainIDWithUserID indicates that a DomainID was provided, but unnecessary because a UserID is being used.
+type ErrDomainIDWithUserID struct{ BaseError }
+
+func (e ErrDomainIDWithUserID) Error() string {
+	return redundantWithUserID("DomainID")
+}
+
+// ErrDomainNameWithUserID indicates that a DomainName was provided, but unnecessary because a UserID is being used.
+type ErrDomainNameWithUserID struct{ BaseError }
+
+func (e ErrDomainNameWithUserID) Error() string {
+	return redundantWithUserID("DomainName")
+}
+
+// ErrDomainIDOrDomainName indicates that a username was provided, but no domain to scope it.
+// It may also indicate that both a DomainID and a DomainName were provided at once.
+type ErrDomainIDOrDomainName struct{ BaseError }
+
+func (e ErrDomainIDOrDomainName) Error() string {
+	return "You must provide exactly one of DomainID or DomainName to authenticate by Username"
+}
+
+// ErrMissingPassword indicates that no password was provided and no token is available.
+type ErrMissingPassword struct{ BaseError }
+
+func (e ErrMissingPassword) Error() string {
+	return "You must provide a password to authenticate"
+}
+
+// ErrScopeDomainIDOrDomainName indicates that a domain ID or Name was required in a Scope, but not present.
+type ErrScopeDomainIDOrDomainName struct{ BaseError }
+
+func (e ErrScopeDomainIDOrDomainName) Error() string {
+	return "You must provide exactly one of DomainID or DomainName in a Scope with ProjectName"
+}
+
+// ErrScopeProjectIDOrProjectName indicates that both a ProjectID and a ProjectName were provided in a Scope.
+type ErrScopeProjectIDOrProjectName struct{ BaseError }
+
+func (e ErrScopeProjectIDOrProjectName) Error() string {
+	return "You must provide at most one of ProjectID or ProjectName in a Scope"
+}
+
+// ErrScopeProjectIDAlone indicates that a ProjectID was provided with other constraints in a Scope.
+type ErrScopeProjectIDAlone struct{ BaseError }
+
+func (e ErrScopeProjectIDAlone) Error() string {
+	return "ProjectID must be supplied alone in a Scope"
+}
+
+// ErrScopeDomainName indicates that a DomainName was provided alone in a Scope.
+type ErrScopeDomainName struct{ BaseError }
+
+func (e ErrScopeDomainName) Error() string {
+	return "DomainName must be supplied with a ProjectName or ProjectID in a Scope"
+}
+
+// ErrScopeEmpty indicates that no credentials were provided in a Scope.
+type ErrScopeEmpty struct{ BaseError }
+
+func (e ErrScopeEmpty) Error() string {
+	return "You must provide either a Project or Domain in a Scope"
+}
diff --git a/openstack/client.go b/openstack/client.go
index ebad6dc..a45b538 100644
--- a/openstack/client.go
+++ b/openstack/client.go
@@ -78,7 +78,7 @@
 	case v20:
 		return v2auth(client, endpoint, options, gophercloud.EndpointOpts{})
 	case v30:
-		return v3auth(client, endpoint, options, gophercloud.EndpointOpts{})
+		return v3auth(client, endpoint, &options, gophercloud.EndpointOpts{})
 	default:
 		// The switch statement must be out of date from the versions list.
 		return fmt.Errorf("Unrecognized identity version: %s", chosen.ID)
@@ -137,11 +137,11 @@
 }
 
 // AuthenticateV3 explicitly authenticates against the identity v3 service.
-func AuthenticateV3(client *gophercloud.ProviderClient, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error {
+func AuthenticateV3(client *gophercloud.ProviderClient, options tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error {
 	return v3auth(client, "", options, eo)
 }
 
-func v3auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error {
+func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error {
 	// Override the generated service endpoint with the one returned by the version endpoint.
 	v3Client, err := NewIdentityV3(client, eo)
 	if err != nil {
@@ -152,42 +152,7 @@
 		v3Client.Endpoint = endpoint
 	}
 
-	// copy the auth options to a local variable that we can change. `options`
-	// needs to stay as-is for reauth purposes
-	v3Options := options
-
-	var scope *tokens3.Scope
-	if options.TenantID != "" {
-		scope = &tokens3.Scope{
-			ProjectID: options.TenantID,
-		}
-		v3Options.TenantID = ""
-		v3Options.TenantName = ""
-	} else {
-		if options.TenantName != "" {
-			scope = &tokens3.Scope{
-				ProjectName: options.TenantName,
-				DomainID:    options.DomainID,
-				DomainName:  options.DomainName,
-			}
-			v3Options.TenantName = ""
-		}
-	}
-
-	v3Opts := tokens3.AuthOptions{
-		IdentityEndpoint: v3Options.IdentityEndpoint,
-		Username:         v3Options.Username,
-		UserID:           v3Options.UserID,
-		Password:         v3Options.Password,
-		DomainID:         v3Options.DomainID,
-		DomainName:       v3Options.DomainName,
-		TenantID:         v3Options.TenantID,
-		TenantName:       v3Options.TenantName,
-		AllowReauth:      v3Options.AllowReauth,
-		TokenID:          v3Options.TokenID,
-	}
-
-	result := tokens3.Create(v3Client, v3Opts, scope)
+	result := tokens3.Create(v3Client, opts)
 
 	token, err := result.ExtractToken()
 	if err != nil {
@@ -201,10 +166,10 @@
 
 	client.TokenID = token.ID
 
-	if options.AllowReauth {
+	if opts.CanReauth() {
 		client.ReauthFunc = func() error {
 			client.TokenID = ""
-			return v3auth(client, endpoint, options, eo)
+			return v3auth(client, endpoint, opts, eo)
 		}
 	}
 	client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
diff --git a/openstack/identity/v3/extensions/trusts/requests.go b/openstack/identity/v3/extensions/trusts/requests.go
new file mode 100644
index 0000000..999dd73
--- /dev/null
+++ b/openstack/identity/v3/extensions/trusts/requests.go
@@ -0,0 +1,34 @@
+package trusts
+
+import "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
+
+type AuthOptsExt struct {
+	tokens.AuthOptionsBuilder
+	TrustID string `json:"id"`
+}
+
+func (opts AuthOptsExt) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) {
+	return opts.AuthOptionsBuilder.ToTokenV3CreateMap(scope)
+}
+
+func (opts AuthOptsExt) ToTokenV3ScopeMap() (map[string]interface{}, error) {
+	b, err := opts.AuthOptionsBuilder.ToTokenV3ScopeMap()
+	if err != nil {
+		return nil, err
+	}
+
+	if opts.TrustID != "" {
+		if b == nil {
+			b = make(map[string]interface{})
+		}
+		b["OS-TRUST:trust"] = map[string]interface{}{
+			"id": opts.TrustID,
+		}
+	}
+
+	return b, nil
+}
+
+func (opts AuthOptsExt) CanReauth() bool {
+	return opts.AuthOptionsBuilder.CanReauth()
+}
diff --git a/openstack/identity/v3/extensions/trusts/testing/fixtures.go b/openstack/identity/v3/extensions/trusts/testing/fixtures.go
new file mode 100644
index 0000000..15d5f3f
--- /dev/null
+++ b/openstack/identity/v3/extensions/trusts/testing/fixtures.go
@@ -0,0 +1,41 @@
+package testing
+
+import (
+	"fmt"
+	"net/http"
+	"testing"
+
+	"github.com/gophercloud/gophercloud"
+	"github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
+	"github.com/gophercloud/gophercloud/testhelper"
+)
+
+// HandleCreateTokenWithTrustID verifies that providing certain AuthOptions and Scope results in an expected JSON structure.
+func HandleCreateTokenWithTrustID(t *testing.T, options tokens.AuthOptionsBuilder, requestJSON string) {
+	testhelper.SetupHTTP()
+	defer testhelper.TeardownHTTP()
+
+	client := gophercloud.ServiceClient{
+		ProviderClient: &gophercloud.ProviderClient{},
+		Endpoint:       testhelper.Endpoint(),
+	}
+
+	testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) {
+		testhelper.TestMethod(t, r, "POST")
+		testhelper.TestHeader(t, r, "Content-Type", "application/json")
+		testhelper.TestHeader(t, r, "Accept", "application/json")
+		testhelper.TestJSONRequest(t, r, requestJSON)
+
+		w.WriteHeader(http.StatusCreated)
+		fmt.Fprintf(w, `{
+			"token": {
+				"expires_at": "2014-10-02T13:45:00.000000Z"
+			}
+		}`)
+	})
+
+	_, err := tokens.Create(&client, options).Extract()
+	if err != nil {
+		t.Errorf("Create returned an error: %v", err)
+	}
+}
diff --git a/openstack/identity/v3/extensions/trusts/testing/requests_test.go b/openstack/identity/v3/extensions/trusts/testing/requests_test.go
new file mode 100644
index 0000000..f0e41dc
--- /dev/null
+++ b/openstack/identity/v3/extensions/trusts/testing/requests_test.go
@@ -0,0 +1,35 @@
+package testing
+
+import (
+	"testing"
+
+	"github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts"
+	"github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
+)
+
+func TestCreateUserIDPasswordTrustID(t *testing.T) {
+	ao := trusts.AuthOptsExt{
+		TrustID: "de0945a",
+		AuthOptionsBuilder: &tokens.AuthOptions{
+			UserID:   "me",
+			Password: "squirrel!",
+		},
+	}
+	HandleCreateTokenWithTrustID(t, ao, `
+		{
+			"auth": {
+				"identity": {
+					"methods": ["password"],
+					"password": {
+						"user": { "id": "me", "password": "squirrel!" }
+					}
+				},
+        "scope": {
+            "OS-TRUST:trust": {
+                "id": "de0945a"
+            }
+        }
+			}
+		}
+	`)
+}
diff --git a/openstack/identity/v3/tokens/errors.go b/openstack/identity/v3/tokens/errors.go
deleted file mode 100644
index 9cc1d59..0000000
--- a/openstack/identity/v3/tokens/errors.go
+++ /dev/null
@@ -1,139 +0,0 @@
-package tokens
-
-import (
-	"fmt"
-
-	"github.com/gophercloud/gophercloud"
-)
-
-func unacceptedAttributeErr(attribute string) string {
-	return fmt.Sprintf("The base Identity V3 API does not accept authentication by %s", attribute)
-}
-
-func redundantWithTokenErr(attribute string) string {
-	return fmt.Sprintf("%s may not be provided when authenticating with a TokenID", attribute)
-}
-
-func redundantWithUserID(attribute string) string {
-	return fmt.Sprintf("%s may not be provided when authenticating with a UserID", attribute)
-}
-
-// ErrAPIKeyProvided indicates that an APIKey was provided but can't be used.
-type ErrAPIKeyProvided struct{ gophercloud.BaseError }
-
-func (e ErrAPIKeyProvided) Error() string {
-	return unacceptedAttributeErr("APIKey")
-}
-
-// ErrTenantIDProvided indicates that a TenantID was provided but can't be used.
-type ErrTenantIDProvided struct{ gophercloud.BaseError }
-
-func (e ErrTenantIDProvided) Error() string {
-	return unacceptedAttributeErr("TenantID")
-}
-
-// ErrTenantNameProvided indicates that a TenantName was provided but can't be used.
-type ErrTenantNameProvided struct{ gophercloud.BaseError }
-
-func (e ErrTenantNameProvided) Error() string {
-	return unacceptedAttributeErr("TenantName")
-}
-
-// ErrUsernameWithToken indicates that a Username was provided, but token authentication is being used instead.
-type ErrUsernameWithToken struct{ gophercloud.BaseError }
-
-func (e ErrUsernameWithToken) Error() string {
-	return redundantWithTokenErr("Username")
-}
-
-// ErrUserIDWithToken indicates that a UserID was provided, but token authentication is being used instead.
-type ErrUserIDWithToken struct{ gophercloud.BaseError }
-
-func (e ErrUserIDWithToken) Error() string {
-	return redundantWithTokenErr("UserID")
-}
-
-// ErrDomainIDWithToken indicates that a DomainID was provided, but token authentication is being used instead.
-type ErrDomainIDWithToken struct{ gophercloud.BaseError }
-
-func (e ErrDomainIDWithToken) Error() string {
-	return redundantWithTokenErr("DomainID")
-}
-
-// ErrDomainNameWithToken indicates that a DomainName was provided, but token authentication is being used instead.s
-type ErrDomainNameWithToken struct{ gophercloud.BaseError }
-
-func (e ErrDomainNameWithToken) Error() string {
-	return redundantWithTokenErr("DomainName")
-}
-
-// ErrUsernameOrUserID indicates that neither username nor userID are specified, or both are at once.
-type ErrUsernameOrUserID struct{ gophercloud.BaseError }
-
-func (e ErrUsernameOrUserID) Error() string {
-	return "Exactly one of Username and UserID must be provided for password authentication"
-}
-
-// ErrDomainIDWithUserID indicates that a DomainID was provided, but unnecessary because a UserID is being used.
-type ErrDomainIDWithUserID struct{ gophercloud.BaseError }
-
-func (e ErrDomainIDWithUserID) Error() string {
-	return redundantWithUserID("DomainID")
-}
-
-// ErrDomainNameWithUserID indicates that a DomainName was provided, but unnecessary because a UserID is being used.
-type ErrDomainNameWithUserID struct{ gophercloud.BaseError }
-
-func (e ErrDomainNameWithUserID) Error() string {
-	return redundantWithUserID("DomainName")
-}
-
-// ErrDomainIDOrDomainName indicates that a username was provided, but no domain to scope it.
-// It may also indicate that both a DomainID and a DomainName were provided at once.
-type ErrDomainIDOrDomainName struct{ gophercloud.BaseError }
-
-func (e ErrDomainIDOrDomainName) Error() string {
-	return "You must provide exactly one of DomainID or DomainName to authenticate by Username"
-}
-
-// ErrMissingPassword indicates that no password was provided and no token is available.
-type ErrMissingPassword struct{ gophercloud.BaseError }
-
-func (e ErrMissingPassword) Error() string {
-	return "You must provide a password to authenticate"
-}
-
-// ErrScopeDomainIDOrDomainName indicates that a domain ID or Name was required in a Scope, but not present.
-type ErrScopeDomainIDOrDomainName struct{ gophercloud.BaseError }
-
-func (e ErrScopeDomainIDOrDomainName) Error() string {
-	return "You must provide exactly one of DomainID or DomainName in a Scope with ProjectName"
-}
-
-// ErrScopeProjectIDOrProjectName indicates that both a ProjectID and a ProjectName were provided in a Scope.
-type ErrScopeProjectIDOrProjectName struct{ gophercloud.BaseError }
-
-func (e ErrScopeProjectIDOrProjectName) Error() string {
-	return "You must provide at most one of ProjectID or ProjectName in a Scope"
-}
-
-// ErrScopeProjectIDAlone indicates that a ProjectID was provided with other constraints in a Scope.
-type ErrScopeProjectIDAlone struct{ gophercloud.BaseError }
-
-func (e ErrScopeProjectIDAlone) Error() string {
-	return "ProjectID must be supplied alone in a Scope"
-}
-
-// ErrScopeDomainName indicates that a DomainName was provided alone in a Scope.
-type ErrScopeDomainName struct{ gophercloud.BaseError }
-
-func (e ErrScopeDomainName) Error() string {
-	return "DomainName must be supplied with a ProjectName or ProjectID in a Scope"
-}
-
-// ErrScopeEmpty indicates that no credentials were provided in a Scope.
-type ErrScopeEmpty struct{ gophercloud.BaseError }
-
-func (e ErrScopeEmpty) Error() string {
-	return "You must provide either a Project or Domain in a Scope"
-}
diff --git a/openstack/identity/v3/tokens/requests.go b/openstack/identity/v3/tokens/requests.go
index 856c363..b65de02 100644
--- a/openstack/identity/v3/tokens/requests.go
+++ b/openstack/identity/v3/tokens/requests.go
@@ -14,7 +14,9 @@
 type AuthOptionsBuilder interface {
 	// ToTokenV3CreateMap assembles the Create request body, returning an error if parameters are
 	// missing or inconsistent.
-	ToTokenV3CreateMap(*Scope) (map[string]interface{}, error)
+	ToTokenV3CreateMap(map[string]interface{}) (map[string]interface{}, error)
+	ToTokenV3ScopeMap() (map[string]interface{}, error)
+	CanReauth() bool
 }
 
 type AuthOptions struct {
@@ -37,13 +39,6 @@
 	DomainID   string `json:"id,omitempty"`
 	DomainName string `json:"name,omitempty"`
 
-	// The TenantID and TenantName fields are optional for the Identity V2 API.
-	// Some providers allow you to specify a TenantName instead of the TenantId.
-	// Some require both. Your provider's authentication policies will determine
-	// how these fields influence authentication.
-	TenantID   string `json:"tenantId,omitempty"`
-	TenantName string `json:"tenantName,omitempty"`
-
 	// AllowReauth should be set to true if you grant permission for Gophercloud to
 	// cache your credentials in memory, and to allow Gophercloud to attempt to
 	// re-authenticate automatically if/when your token expires.  If you set it to
@@ -53,223 +48,91 @@
 
 	// TokenID allows users to authenticate (possibly as another user) with an
 	// authentication token ID.
-	TokenID string
+	TokenID string `json:"-"`
+
+	Scope Scope `json:"-"`
 }
 
-func (opts AuthOptions) ToTokenV3CreateMap(scope *Scope) (map[string]interface{}, error) {
-	type domainReq struct {
-		ID   *string `json:"id,omitempty"`
-		Name *string `json:"name,omitempty"`
+func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) {
+	gophercloudAuthOpts := gophercloud.AuthOptions{
+		Username:    opts.Username,
+		UserID:      opts.UserID,
+		Password:    opts.Password,
+		DomainID:    opts.DomainID,
+		DomainName:  opts.DomainName,
+		AllowReauth: opts.AllowReauth,
+		TokenID:     opts.TokenID,
 	}
 
-	type projectReq struct {
-		Domain *domainReq `json:"domain,omitempty"`
-		Name   *string    `json:"name,omitempty"`
-		ID     *string    `json:"id,omitempty"`
-	}
+	return gophercloudAuthOpts.ToTokenV3CreateMap(scope)
+}
 
-	type userReq struct {
-		ID       *string    `json:"id,omitempty"`
-		Name     *string    `json:"name,omitempty"`
-		Password string     `json:"password"`
-		Domain   *domainReq `json:"domain,omitempty"`
-	}
-
-	type passwordReq struct {
-		User userReq `json:"user"`
-	}
-
-	type tokenReq struct {
-		ID string `json:"id"`
-	}
-
-	type identityReq struct {
-		Methods  []string     `json:"methods"`
-		Password *passwordReq `json:"password,omitempty"`
-		Token    *tokenReq    `json:"token,omitempty"`
-	}
-
-	type scopeReq struct {
-		Domain  *domainReq  `json:"domain,omitempty"`
-		Project *projectReq `json:"project,omitempty"`
-	}
-
-	type authReq struct {
-		Identity identityReq `json:"identity"`
-		Scope    *scopeReq   `json:"scope,omitempty"`
-	}
-
-	type request struct {
-		Auth authReq `json:"auth"`
-	}
-
-	// Populate the request structure based on the provided arguments. Create and return an error
-	// if insufficient or incompatible information is present.
-	var req request
-
-	// Test first for unrecognized arguments.
-	if opts.TenantID != "" {
-		return nil, ErrTenantIDProvided{}
-	}
-	if opts.TenantName != "" {
-		return nil, ErrTenantNameProvided{}
-	}
-
-	if opts.Password == "" {
-		if opts.TokenID != "" {
-			// Because we aren't using password authentication, it's an error to also provide any of the user-based authentication
-			// parameters.
-			if opts.Username != "" {
-				return nil, ErrUsernameWithToken{}
-			}
-			if opts.UserID != "" {
-				return nil, ErrUserIDWithToken{}
-			}
-			if opts.DomainID != "" {
-				return nil, ErrDomainIDWithToken{}
-			}
-			if opts.DomainName != "" {
-				return nil, ErrDomainNameWithToken{}
-			}
-
-			// Configure the request for Token authentication.
-			req.Auth.Identity.Methods = []string{"token"}
-			req.Auth.Identity.Token = &tokenReq{
-				ID: opts.TokenID,
-			}
-		} else {
-			// If no password or token ID are available, authentication can't continue.
-			return nil, ErrMissingPassword{}
+func (opts *AuthOptions) ToTokenV3ScopeMap() (map[string]interface{}, error) {
+	if opts.Scope.ProjectName != "" {
+		// ProjectName provided: either DomainID or DomainName must also be supplied.
+		// ProjectID may not be supplied.
+		if opts.Scope.DomainID == "" && opts.Scope.DomainName == "" {
+			return nil, gophercloud.ErrScopeDomainIDOrDomainName{}
 		}
-	} else {
-		// Password authentication.
-		req.Auth.Identity.Methods = []string{"password"}
-
-		// At least one of Username and UserID must be specified.
-		if opts.Username == "" && opts.UserID == "" {
-			return nil, ErrUsernameOrUserID{}
+		if opts.Scope.ProjectID != "" {
+			return nil, gophercloud.ErrScopeProjectIDOrProjectName{}
 		}
 
-		if opts.Username != "" {
-			// If Username is provided, UserID may not be provided.
-			if opts.UserID != "" {
-				return nil, ErrUsernameOrUserID{}
-			}
-
-			// Either DomainID or DomainName must also be specified.
-			if opts.DomainID == "" && opts.DomainName == "" {
-				return nil, ErrDomainIDOrDomainName{}
-			}
-
-			if opts.DomainID != "" {
-				if opts.DomainName != "" {
-					return nil, ErrDomainIDOrDomainName{}
-				}
-
-				// Configure the request for Username and Password authentication with a DomainID.
-				req.Auth.Identity.Password = &passwordReq{
-					User: userReq{
-						Name:     &opts.Username,
-						Password: opts.Password,
-						Domain:   &domainReq{ID: &opts.DomainID},
-					},
-				}
-			}
-
-			if opts.DomainName != "" {
-				// Configure the request for Username and Password authentication with a DomainName.
-				req.Auth.Identity.Password = &passwordReq{
-					User: userReq{
-						Name:     &opts.Username,
-						Password: opts.Password,
-						Domain:   &domainReq{Name: &opts.DomainName},
-					},
-				}
-			}
+		if opts.Scope.DomainID != "" {
+			// ProjectName + DomainID
+			return map[string]interface{}{
+				"project": map[string]interface{}{
+					"name":   &opts.Scope.ProjectName,
+					"domain": map[string]interface{}{"id": &opts.Scope.DomainID},
+				},
+			}, nil
 		}
 
-		if opts.UserID != "" {
-			// If UserID is specified, neither DomainID nor DomainName may be.
-			if opts.DomainID != "" {
-				return nil, ErrDomainIDWithUserID{}
-			}
-			if opts.DomainName != "" {
-				return nil, ErrDomainNameWithUserID{}
-			}
-
-			// Configure the request for UserID and Password authentication.
-			req.Auth.Identity.Password = &passwordReq{
-				User: userReq{ID: &opts.UserID, Password: opts.Password},
-			}
+		if opts.Scope.DomainName != "" {
+			// ProjectName + DomainName
+			return map[string]interface{}{
+				"project": map[string]interface{}{
+					"name":   &opts.Scope.ProjectName,
+					"domain": map[string]interface{}{"name": &opts.Scope.DomainName},
+				},
+			}, nil
 		}
-	}
-
-	// Add a "scope" element if a Scope has been provided.
-	if scope != nil {
-		if scope.ProjectName != "" {
-			// ProjectName provided: either DomainID or DomainName must also be supplied.
-			// ProjectID may not be supplied.
-			if scope.DomainID == "" && scope.DomainName == "" {
-				return nil, ErrScopeDomainIDOrDomainName{}
-			}
-			if scope.ProjectID != "" {
-				return nil, ErrScopeProjectIDOrProjectName{}
-			}
-
-			if scope.DomainID != "" {
-				// ProjectName + DomainID
-				req.Auth.Scope = &scopeReq{
-					Project: &projectReq{
-						Name:   &scope.ProjectName,
-						Domain: &domainReq{ID: &scope.DomainID},
-					},
-				}
-			}
-
-			if scope.DomainName != "" {
-				// ProjectName + DomainName
-				req.Auth.Scope = &scopeReq{
-					Project: &projectReq{
-						Name:   &scope.ProjectName,
-						Domain: &domainReq{Name: &scope.DomainName},
-					},
-				}
-			}
-		} else if scope.ProjectID != "" {
-			// ProjectID provided. ProjectName, DomainID, and DomainName may not be provided.
-			if scope.DomainID != "" {
-				return nil, ErrScopeProjectIDAlone{}
-			}
-			if scope.DomainName != "" {
-				return nil, ErrScopeProjectIDAlone{}
-			}
-
-			// ProjectID
-			req.Auth.Scope = &scopeReq{
-				Project: &projectReq{ID: &scope.ProjectID},
-			}
-		} else if scope.DomainID != "" {
-			// DomainID provided. ProjectID, ProjectName, and DomainName may not be provided.
-			if scope.DomainName != "" {
-				return nil, ErrScopeDomainIDOrDomainName{}
-			}
-
-			// DomainID
-			req.Auth.Scope = &scopeReq{
-				Domain: &domainReq{ID: &scope.DomainID},
-			}
-		} else if scope.DomainName != "" {
-			return nil, ErrScopeDomainName{}
-		} else {
-			return nil, ErrScopeEmpty{}
+	} else if opts.Scope.ProjectID != "" {
+		// ProjectID provided. ProjectName, DomainID, and DomainName may not be provided.
+		if opts.Scope.DomainID != "" {
+			return nil, gophercloud.ErrScopeProjectIDAlone{}
 		}
+		if opts.Scope.DomainName != "" {
+			return nil, gophercloud.ErrScopeProjectIDAlone{}
+		}
+
+		// ProjectID
+		return map[string]interface{}{
+			"project": map[string]interface{}{
+				"id": &opts.Scope.ProjectID,
+			},
+		}, nil
+	} else if opts.Scope.DomainID != "" {
+		// DomainID provided. ProjectID, ProjectName, and DomainName may not be provided.
+		if opts.Scope.DomainName != "" {
+			return nil, gophercloud.ErrScopeDomainIDOrDomainName{}
+		}
+
+		// DomainID
+		return map[string]interface{}{
+			"domain": map[string]interface{}{
+				"id": &opts.Scope.DomainID,
+			},
+		}, nil
+	} else if opts.Scope.DomainName != "" {
+		return nil, gophercloud.ErrScopeDomainName{}
 	}
 
-	b, err2 := gophercloud.BuildRequestBody(req, "")
-	if err2 != nil {
-		return nil, err2
-	}
-	return b, nil
+	return nil, nil
+}
+
+func (opts *AuthOptions) CanReauth() bool {
+	return opts.AllowReauth
 }
 
 func subjectTokenHeaders(c *gophercloud.ServiceClient, subjectToken string) map[string]string {
@@ -279,12 +142,19 @@
 }
 
 // Create authenticates and either generates a new token, or changes the Scope of an existing token.
-func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder, scopeOpts *Scope) (r CreateResult) {
-	b, err := opts.ToTokenV3CreateMap(scopeOpts)
+func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) {
+	scope, err := opts.ToTokenV3ScopeMap()
 	if err != nil {
 		r.Err = err
 		return
 	}
+
+	b, err := opts.ToTokenV3CreateMap(scope)
+	if err != nil {
+		r.Err = err
+		return
+	}
+
 	resp, err := c.Post(tokenURL(c), b, &r.Body, &gophercloud.RequestOpts{
 		MoreHeaders: map[string]string{"X-Auth-Token": ""},
 	})
diff --git a/openstack/identity/v3/tokens/testing/requests_test.go b/openstack/identity/v3/tokens/testing/requests_test.go
index cbb675f..481d05c 100644
--- a/openstack/identity/v3/tokens/testing/requests_test.go
+++ b/openstack/identity/v3/tokens/testing/requests_test.go
@@ -35,7 +35,11 @@
 		}`)
 	})
 
-	_, err := tokens.Create(&client, options, scope).Extract()
+	if scope != nil {
+		options.Scope = *scope
+	}
+
+	_, err := tokens.Create(&client, &options).Extract()
 	if err != nil {
 		t.Errorf("Create returned an error: %v", err)
 	}
@@ -53,7 +57,11 @@
 		client.TokenID = "abcdef123456"
 	}
 
-	_, err := tokens.Create(&client, options, scope).Extract()
+	if scope != nil {
+		options.Scope = *scope
+	}
+
+	_, err := tokens.Create(&client, &options).Extract()
 	if err == nil {
 		t.Errorf("Create did NOT return an error")
 	}
@@ -261,7 +269,7 @@
 	})
 
 	options := tokens.AuthOptions{UserID: "me", Password: "shhh"}
-	token, err := tokens.Create(&client, options, nil).Extract()
+	token, err := tokens.Create(&client, &options).Extract()
 	if err != nil {
 		t.Fatalf("Create returned an error: %v", err)
 	}
@@ -272,36 +280,28 @@
 }
 
 func TestCreateFailureEmptyAuth(t *testing.T) {
-	authTokenPostErr(t, tokens.AuthOptions{}, nil, false, tokens.ErrMissingPassword{})
-}
-
-func TestCreateFailureTenantID(t *testing.T) {
-	authTokenPostErr(t, tokens.AuthOptions{TenantID: "something"}, nil, false, tokens.ErrTenantIDProvided{})
-}
-
-func TestCreateFailureTenantName(t *testing.T) {
-	authTokenPostErr(t, tokens.AuthOptions{TenantName: "something"}, nil, false, tokens.ErrTenantNameProvided{})
+	authTokenPostErr(t, tokens.AuthOptions{}, nil, false, gophercloud.ErrMissingPassword{})
 }
 
 func TestCreateFailureTokenIDUsername(t *testing.T) {
-	authTokenPostErr(t, tokens.AuthOptions{Username: "something", TokenID: "12345"}, nil, true, tokens.ErrUsernameWithToken{})
+	authTokenPostErr(t, tokens.AuthOptions{Username: "something", TokenID: "12345"}, nil, true, gophercloud.ErrUsernameWithToken{})
 }
 
 func TestCreateFailureTokenIDUserID(t *testing.T) {
-	authTokenPostErr(t, tokens.AuthOptions{UserID: "something", TokenID: "12345"}, nil, true, tokens.ErrUserIDWithToken{})
+	authTokenPostErr(t, tokens.AuthOptions{UserID: "something", TokenID: "12345"}, nil, true, gophercloud.ErrUserIDWithToken{})
 }
 
 func TestCreateFailureTokenIDDomainID(t *testing.T) {
-	authTokenPostErr(t, tokens.AuthOptions{DomainID: "something", TokenID: "12345"}, nil, true, tokens.ErrDomainIDWithToken{})
+	authTokenPostErr(t, tokens.AuthOptions{DomainID: "something", TokenID: "12345"}, nil, true, gophercloud.ErrDomainIDWithToken{})
 }
 
 func TestCreateFailureTokenIDDomainName(t *testing.T) {
-	authTokenPostErr(t, tokens.AuthOptions{DomainName: "something", TokenID: "12345"}, nil, true, tokens.ErrDomainNameWithToken{})
+	authTokenPostErr(t, tokens.AuthOptions{DomainName: "something", TokenID: "12345"}, nil, true, gophercloud.ErrDomainNameWithToken{})
 }
 
 func TestCreateFailureMissingUser(t *testing.T) {
 	options := tokens.AuthOptions{Password: "supersecure"}
-	authTokenPostErr(t, options, nil, false, tokens.ErrUsernameOrUserID{})
+	authTokenPostErr(t, options, nil, false, gophercloud.ErrUsernameOrUserID{})
 }
 
 func TestCreateFailureBothUser(t *testing.T) {
@@ -310,7 +310,7 @@
 		Username: "oops",
 		UserID:   "redundancy",
 	}
-	authTokenPostErr(t, options, nil, false, tokens.ErrUsernameOrUserID{})
+	authTokenPostErr(t, options, nil, false, gophercloud.ErrUsernameOrUserID{})
 }
 
 func TestCreateFailureMissingDomain(t *testing.T) {
@@ -318,7 +318,7 @@
 		Password: "supersecure",
 		Username: "notuniqueenough",
 	}
-	authTokenPostErr(t, options, nil, false, tokens.ErrDomainIDOrDomainName{})
+	authTokenPostErr(t, options, nil, false, gophercloud.ErrDomainIDOrDomainName{})
 }
 
 func TestCreateFailureBothDomain(t *testing.T) {
@@ -328,7 +328,7 @@
 		DomainID:   "hurf",
 		DomainName: "durf",
 	}
-	authTokenPostErr(t, options, nil, false, tokens.ErrDomainIDOrDomainName{})
+	authTokenPostErr(t, options, nil, false, gophercloud.ErrDomainIDOrDomainName{})
 }
 
 func TestCreateFailureUserIDDomainID(t *testing.T) {
@@ -337,7 +337,7 @@
 		Password: "stuff",
 		DomainID: "oops",
 	}
-	authTokenPostErr(t, options, nil, false, tokens.ErrDomainIDWithUserID{})
+	authTokenPostErr(t, options, nil, false, gophercloud.ErrDomainIDWithUserID{})
 }
 
 func TestCreateFailureUserIDDomainName(t *testing.T) {
@@ -346,50 +346,52 @@
 		Password:   "sssh",
 		DomainName: "oops",
 	}
-	authTokenPostErr(t, options, nil, false, tokens.ErrDomainNameWithUserID{})
+	authTokenPostErr(t, options, nil, false, gophercloud.ErrDomainNameWithUserID{})
 }
 
 func TestCreateFailureScopeProjectNameAlone(t *testing.T) {
 	options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"}
 	scope := &tokens.Scope{ProjectName: "notenough"}
-	authTokenPostErr(t, options, scope, false, tokens.ErrScopeDomainIDOrDomainName{})
+	authTokenPostErr(t, options, scope, false, gophercloud.ErrScopeDomainIDOrDomainName{})
 }
 
 func TestCreateFailureScopeProjectNameAndID(t *testing.T) {
 	options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"}
 	scope := &tokens.Scope{ProjectName: "whoops", ProjectID: "toomuch", DomainID: "1234"}
-	authTokenPostErr(t, options, scope, false, tokens.ErrScopeProjectIDOrProjectName{})
+	authTokenPostErr(t, options, scope, false, gophercloud.ErrScopeProjectIDOrProjectName{})
 }
 
 func TestCreateFailureScopeProjectIDAndDomainID(t *testing.T) {
 	options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"}
 	scope := &tokens.Scope{ProjectID: "toomuch", DomainID: "notneeded"}
-	authTokenPostErr(t, options, scope, false, tokens.ErrScopeProjectIDAlone{})
+	authTokenPostErr(t, options, scope, false, gophercloud.ErrScopeProjectIDAlone{})
 }
 
 func TestCreateFailureScopeProjectIDAndDomainNAme(t *testing.T) {
 	options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"}
 	scope := &tokens.Scope{ProjectID: "toomuch", DomainName: "notneeded"}
-	authTokenPostErr(t, options, scope, false, tokens.ErrScopeProjectIDAlone{})
+	authTokenPostErr(t, options, scope, false, gophercloud.ErrScopeProjectIDAlone{})
 }
 
 func TestCreateFailureScopeDomainIDAndDomainName(t *testing.T) {
 	options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"}
 	scope := &tokens.Scope{DomainID: "toomuch", DomainName: "notneeded"}
-	authTokenPostErr(t, options, scope, false, tokens.ErrScopeDomainIDOrDomainName{})
+	authTokenPostErr(t, options, scope, false, gophercloud.ErrScopeDomainIDOrDomainName{})
 }
 
 func TestCreateFailureScopeDomainNameAlone(t *testing.T) {
 	options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"}
 	scope := &tokens.Scope{DomainName: "notenough"}
-	authTokenPostErr(t, options, scope, false, tokens.ErrScopeDomainName{})
+	authTokenPostErr(t, options, scope, false, gophercloud.ErrScopeDomainName{})
 }
 
+/*
 func TestCreateFailureEmptyScope(t *testing.T) {
 	options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"}
 	scope := &tokens.Scope{}
-	authTokenPostErr(t, options, scope, false, tokens.ErrScopeEmpty{})
+	authTokenPostErr(t, options, scope, false, gophercloud.ErrScopeEmpty{})
 }
+*/
 
 func TestGetRequest(t *testing.T) {
 	testhelper.SetupHTTP()