Override request body generation for API keys.
diff --git a/openstack/identity/v2/tokens/requests.go b/openstack/identity/v2/tokens/requests.go
index 96c28cf..c25a72b 100644
--- a/openstack/identity/v2/tokens/requests.go
+++ b/openstack/identity/v2/tokens/requests.go
@@ -19,6 +19,11 @@
 	gophercloud.AuthOptions
 }
 
+// WrapOptions embeds a root AuthOptions struct in a package-specific one.
+func WrapOptions(original gophercloud.AuthOptions) AuthOptions {
+	return AuthOptions{AuthOptions: original}
+}
+
 // ToTokenCreateMap converts AuthOptions into nested maps that can be serialized into a JSON
 // request.
 func (auth AuthOptions) ToTokenCreateMap() (map[string]interface{}, error) {
diff --git a/rackspace/identity/v2/tokens/delegate.go b/rackspace/identity/v2/tokens/delegate.go
index 6a5c1b3..4f9885a 100644
--- a/rackspace/identity/v2/tokens/delegate.go
+++ b/rackspace/identity/v2/tokens/delegate.go
@@ -1,50 +1,60 @@
 package tokens
 
 import (
-	"github.com/racker/perigee"
+	"errors"
+
 	"github.com/rackspace/gophercloud"
 	os "github.com/rackspace/gophercloud/openstack/identity/v2/tokens"
 )
 
+var (
+	// ErrPasswordProvided is returned if both a password and an API key are provided to Create.
+	ErrPasswordProvided = errors.New("Please provide either a password or an API key.")
+)
+
+// AuthOptions wraps the OpenStack AuthOptions struct to be able to customize the request body
+// when API key authentication is used.
+type AuthOptions struct {
+	os.AuthOptions
+}
+
+// WrapOptions embeds a root AuthOptions struct in a package-specific one.
+func WrapOptions(original gophercloud.AuthOptions) AuthOptions {
+	return AuthOptions{AuthOptions: os.WrapOptions(original)}
+}
+
+// ToTokenCreateMap serializes an AuthOptions into a request body. If an API key is provided, it
+// will be used, otherwise
+func (auth AuthOptions) ToTokenCreateMap() (map[string]interface{}, error) {
+	if auth.APIKey == "" {
+		return auth.AuthOptions.ToTokenCreateMap()
+	}
+
+	// Verify that other required attributes are present.
+	if auth.Username == "" {
+		return nil, os.ErrUsernameRequired
+	}
+
+	authMap := make(map[string]interface{})
+
+	authMap["RAX-KSKEY:apiKeyCredentials"] = map[string]interface{}{
+		"username": auth.Username,
+		"apiKey":   auth.APIKey,
+	}
+
+	if auth.TenantID != "" {
+		authMap["tenantId"] = auth.TenantID
+	}
+	if auth.TenantName != "" {
+		authMap["tenantName"] = auth.TenantName
+	}
+
+	return map[string]interface{}{"auth": authMap}, nil
+}
+
 // Create authenticates to Rackspace's identity service and attempts to acquire a Token. Rather
 // than interact with this service directly, users should generally call
 // rackspace.AuthenticatedClient().
-func Create(client *gophercloud.ServiceClient, auth gophercloud.AuthOptions) os.CreateResult {
-	if auth.APIKey != "" {
-		// Authenticate with the provided API key.
-
-		if auth.Username == "" {
-			return createErr(os.ErrUsernameRequired)
-		}
-
-		var request struct {
-			Auth struct {
-				APIKeyCredentials struct {
-					Username string `json:"username"`
-					APIKey   string `json:"apiKey"`
-				} `json:"RAX-KSKEY:apiKeyCredentials"`
-				TenantID   string `json:"tenantId,omitempty"`
-				TenantName string `json:"tenantName,omitempty"`
-			} `json:"auth"`
-		}
-
-		request.Auth.APIKeyCredentials.Username = auth.Username
-		request.Auth.APIKeyCredentials.APIKey = auth.APIKey
-		request.Auth.TenantID = auth.TenantID
-		request.Auth.TenantName = auth.TenantName
-
-		var result os.CreateResult
-		_, result.Err = perigee.Request("POST", os.CreateURL(client), perigee.Options{
-			ReqBody: &request,
-			Results: &result.Resp,
-			OkCodes: []int{200, 203},
-		})
-		return result
-	}
-
+func Create(client *gophercloud.ServiceClient, auth AuthOptions) os.CreateResult {
 	return os.Create(client, auth)
 }
-
-func createErr(err error) os.CreateResult {
-	return os.CreateResult{CommonResult: gophercloud.CommonResult{Err: err}}
-}
diff --git a/rackspace/identity/v2/tokens/delegate_test.go b/rackspace/identity/v2/tokens/delegate_test.go
index c289947..9f9b321 100644
--- a/rackspace/identity/v2/tokens/delegate_test.go
+++ b/rackspace/identity/v2/tokens/delegate_test.go
@@ -110,7 +110,7 @@
     `)
 	})
 
-	return Create(&client, options)
+	return Create(&client, WrapOptions(options))
 }
 
 func tokenPostErr(t *testing.T, options gophercloud.AuthOptions, expectedErr error) {
@@ -128,7 +128,7 @@
 		fmt.Fprintf(w, `{}`)
 	})
 
-	actualErr := Create(&client, options).Err
+	actualErr := Create(&client, WrapOptions(options)).Err
 	th.CheckEquals(t, expectedErr, actualErr)
 }