Completely untested code for tokens and tenants.
diff --git a/openstack/identity/v2/tokens/requests.go b/openstack/identity/v2/tokens/requests.go
new file mode 100644
index 0000000..c0441ab
--- /dev/null
+++ b/openstack/identity/v2/tokens/requests.go
@@ -0,0 +1,72 @@
+package tokens
+
+import (
+	"github.com/racker/perigee"
+	"github.com/rackspace/gophercloud"
+)
+
+// Create authenticates to the identity service and attempts to acquire a Token.
+// If successful, the CreateResult
+// Generally, rather than interact with this call directly, end users should call openstack.AuthenticatedClient(),
+// which abstracts all of the gory details about navigating service catalogs and such.
+func Create(client *gophercloud.ServiceClient, auth gophercloud.AuthOptions) CreateResult {
+	var request struct {
+		Auth struct {
+			PasswordCredentials struct {
+				Username string `json:"username"`
+				Password string `json:"password"`
+			} `json:"passwordCredentials,omitempty"`
+			APIKeyCredentials struct {
+				Username string `json:"username"`
+				APIKey   string `json:"apiKey"`
+			} `json:"RAX-KSKEY:apiKeyCredentials,omitempty"`
+			TenantID   string `json:"tenantId,omitempty"`
+			TenantName string `json:"tenantName,omitempty"`
+		} `json:"auth"`
+	}
+
+	// Error out if an unsupported auth option is present.
+	if auth.UserID != "" {
+		return createErr(ErrUserIDProvided)
+	}
+	if auth.DomainID != "" {
+		return createErr(ErrDomainIDProvided)
+	}
+	if auth.DomainName != "" {
+		return createErr(ErrDomainNameProvided)
+	}
+
+	// Username is always required.
+	if auth.Username == "" {
+		return createErr(ErrUsernameRequired)
+	}
+
+	// Populate either PasswordCredentials or APIKeyCredentials
+	if auth.Password != "" {
+		if auth.APIKey != "" {
+			return createErr(ErrPasswordOrAPIKey)
+		}
+
+		// Username + Password
+		request.Auth.PasswordCredentials.Username = auth.Username
+		request.Auth.PasswordCredentials.Password = auth.Password
+	} else if auth.APIKey != "" {
+		// API key authentication.
+		request.Auth.APIKeyCredentials.Username = auth.Username
+		request.Auth.APIKeyCredentials.APIKey = auth.APIKey
+	} else {
+		return createErr(ErrPasswordOrAPIKey)
+	}
+
+	// Populate the TenantName or TenantID, if provided.
+	request.Auth.TenantID = auth.TenantID
+	request.Auth.TenantName = auth.TenantName
+
+	var result CreateResult
+	_, result.Err = perigee.Request("POST", listURL(client), perigee.Options{
+		ReqBody: &request,
+		Results: &result.Resp,
+		OkCodes: []int{200, 203},
+	})
+	return result
+}