Convert ListImages to use reauth.

This commit does not work -- acceptance test 08-... is broken.
diff --git a/acceptance/08-reauthentication.go b/acceptance/08-reauthentication.go
index 31c1fe8..10cd73a 100644
--- a/acceptance/08-reauthentication.go
+++ b/acceptance/08-reauthentication.go
@@ -4,6 +4,7 @@
 	"fmt"
 	"flag"
 	"github.com/rackspace/gophercloud"
+	"time"
 )
 
 var quiet = flag.Bool("quiet", false, "Quiet mode for acceptance testing.  $? non-zero on error though.")
@@ -19,6 +20,7 @@
 		gophercloud.AuthOptions{
 			Username: username,
 			Password: password,
+			AllowReauth: true,		// This enables reauthentication.
 		},
 	)
 	if err != nil {
@@ -47,6 +49,10 @@
 
 	// Revoke our current authentication token.
 	auth.Revoke(auth.AuthToken())
+	time.Sleep(15 * time.Second)
+
+	auth.Reauthenticate()
+	fmt.Println("OLD: ", token1, "\nNEW: ", auth.AuthToken())
 
 	// Attempt to list images again.  This should _succeed_, because we enabled re-authentication.
 	_, err = servers.ListImages()
diff --git a/authenticate.go b/authenticate.go
index edd447c..f98c4cc 100644
--- a/authenticate.go
+++ b/authenticate.go
@@ -2,6 +2,7 @@
 
 import (
 	"github.com/racker/perigee"
+	"fmt"
 )
 
 // AuthOptions lets anyone calling Authenticate() supply the required access credentials.
@@ -16,6 +17,13 @@
 
 	// The TenantId field is optional for the Identity V2 API.
 	TenantId string
+
+	// 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 false, it will not cache
+	// these settings, but re-authentication will not be possible.  This setting defaults
+	// to false.
+	AllowReauth bool
 }
 
 // AuthContainer provides a JSON encoding wrapper for passing credentials to the Identity
@@ -45,6 +53,8 @@
 	ServiceCatalog []CatalogEntry
 	User           User
 	provider       Provider `json:"-"`
+	options        AuthOptions `json:"-"`
+	context        *Context `json:"-"`
 }
 
 // Token encapsulates an authentication token and when it expires.  It also includes
@@ -86,30 +96,18 @@
 	VersionId, VersionInfo, VersionList string
 }
 
-// Authenticate() grants access to the OpenStack-compatible provider API.
-//
-// Providers are identified through a unique key string.
-// See the RegisterProvider() method for more details.
-//
-// The supplied AuthOptions instance allows the client to specify only those credentials
-// relevant for the authentication request.  At present, support exists for OpenStack
-// Identity V2 API only; support for V3 will become available as soon as documentation for it
-// becomes readily available.
-//
-// For Identity V2 API requirements, you must provide at least the Username and Password
-// options.  The TenantId field is optional, and defaults to "".
-func (c *Context) Authenticate(provider string, options AuthOptions) (*Access, error) {
+// papersPlease contains the common logic between authentication and re-authentication.
+// The name, obviously a joke on the process of authentication, was chosen because
+// of how many other entities exist in the program containing the word Auth or Authorization.
+// I didn't need another one.
+func (c *Context) papersPlease(p Provider, options AuthOptions) (*Access, error) {
 	var access *Access
 
-	p, err := c.ProviderByName(provider)
-	if err != nil {
-		return nil, err
-	}
 	if (options.Username == "") || (options.Password == "") {
 		return nil, ErrCredentials
 	}
 
-	err = perigee.Post(p.AuthEndpoint, perigee.Options{
+	err := perigee.Post(p.AuthEndpoint, perigee.Options{
 		CustomClient: c.httpClient,
 		ReqBody: &AuthContainer{
 			Auth: Auth{
@@ -127,11 +125,51 @@
 		},
 	})
 	if err == nil {
+		access.options = options
 		access.provider = p
+		access.context = c
 	}
 	return access, err
 }
 
+// Authenticate() grants access to the OpenStack-compatible provider API.
+//
+// Providers are identified through a unique key string.
+// See the RegisterProvider() method for more details.
+//
+// The supplied AuthOptions instance allows the client to specify only those credentials
+// relevant for the authentication request.  At present, support exists for OpenStack
+// Identity V2 API only; support for V3 will become available as soon as documentation for it
+// becomes readily available.
+//
+// For Identity V2 API requirements, you must provide at least the Username and Password
+// options.  The TenantId field is optional, and defaults to "".
+func (c *Context) Authenticate(provider string, options AuthOptions) (*Access, error) {
+	p, err := c.ProviderByName(provider)
+	if err != nil {
+		return nil, err
+	}
+	return c.papersPlease(p, options)
+}
+
+// Reauthenticate attempts to reauthenticate using the configured access credentials, if
+// allowed.  This method takes no action unless your AuthOptions has the AllowReauth flag
+// set to true.
+func (a *Access) Reauthenticate() error {
+	var other *Access
+	var err error
+
+	fmt.Printf("**\n  %#v\n", a.options)
+	if a.options.AllowReauth {
+		other, err = a.context.papersPlease(a.provider, a.options)
+		if err != nil {
+			fmt.Println("NEW NEW: ", other.AuthToken())
+			*a = *other
+		}
+	}
+	return err
+}
+
 // See AccessProvider interface definition for details.
 func (a *Access) FirstEndpointUrlByCriteria(ac ApiCriteria) string {
 	ep := FindFirstEndpointByCriteria(a.ServiceCatalog, ac)
diff --git a/context.go b/context.go
index 2c70ba5..ebad36c 100644
--- a/context.go
+++ b/context.go
@@ -49,6 +49,9 @@
 	return &Context{
 		providerMap: make(map[string]Provider),
 		httpClient:  &http.Client{},
+		reauthHandler: func(acc AccessProvider) error {
+			return acc.Reauthenticate()
+		},
 	}
 }
 
diff --git a/images.go b/images.go
index 9126b93..cc3f6e2 100644
--- a/images.go
+++ b/images.go
@@ -7,13 +7,15 @@
 // See the CloudImagesProvider interface for details.
 func (gsp *genericServersProvider) ListImages() ([]Image, error) {
 	var is []Image
-	url := gsp.endpoint + "/images"
-	err := perigee.Get(url, perigee.Options{
-		CustomClient: gsp.context.httpClient,
-		Results:      &struct{ Images *[]Image }{&is},
-		MoreHeaders: map[string]string{
-			"X-Auth-Token": gsp.access.AuthToken(),
-		},
+	err := gsp.context.WithReauth(gsp.access, func() error {
+		url := gsp.endpoint + "/images"
+		return perigee.Get(url, perigee.Options{
+			CustomClient: gsp.context.httpClient,
+			Results:      &struct{ Images *[]Image }{&is},
+			MoreHeaders: map[string]string{
+				"X-Auth-Token": gsp.access.AuthToken(),
+			},
+		})
 	})
 	return is, err
 }
diff --git a/interfaces.go b/interfaces.go
index ed16afe..b73a118 100644
--- a/interfaces.go
+++ b/interfaces.go
@@ -15,6 +15,10 @@
 
 	// Revoke allows you to terminate any program's access to the OpenStack API by token ID.
 	Revoke(string) error
+
+	// Reauthenticate attempts to acquire a new authentication token, if the feature is enabled by
+	// AuthOptions.AllowReauth.
+	Reauthenticate() error
 }
 
 // CloudServersProvider instances encapsulate a Cloud Servers API, should one exist in the service catalog
diff --git a/reauth_test.go b/reauth_test.go
index 62d3e7e..e6ccb17 100644
--- a/reauth_test.go
+++ b/reauth_test.go
@@ -110,6 +110,9 @@
 func (my *MyAccess) Revoke(string) error {
 	return nil
 }
+func (my *MyAccess) Reauthenticate() error {
+	return nil
+}
 
 func TestReauthHandlerUsesSameAccessProvider(t *testing.T) {
 	fakeAccess := &MyAccess{}
diff --git a/servers_test.go b/servers_test.go
index d95fa40..60c71c8 100644
--- a/servers_test.go
+++ b/servers_test.go
@@ -24,6 +24,10 @@
 	return nil
 }
 
+func (ta *testAccess) Reauthenticate() error {
+	return nil
+}
+
 func TestGetServersApi(t *testing.T) {
 	c := TestContext().UseCustomClient(&http.Client{Transport: newTransport().WithResponse("Hello")})