diff --git a/distribution/registry.go b/distribution/registry.go
index b2f3b52617..98b82fbaeb 100644
--- a/distribution/registry.go
+++ b/distribution/registry.go
@@ -4,7 +4,6 @@ import (
 	"fmt"
 	"net"
 	"net/http"
-	"net/url"
 	"time"
 
 	"github.com/docker/distribution"
@@ -19,21 +18,6 @@ import (
 	"golang.org/x/net/context"
 )
 
-type dumbCredentialStore struct {
-	auth *types.AuthConfig
-}
-
-func (dcs dumbCredentialStore) Basic(*url.URL) (string, string) {
-	return dcs.auth.Username, dcs.auth.Password
-}
-
-func (dcs dumbCredentialStore) RefreshToken(*url.URL, string) string {
-	return dcs.auth.IdentityToken
-}
-
-func (dcs dumbCredentialStore) SetRefreshToken(*url.URL, string, string) {
-}
-
 // NewV2Repository returns a repository (v2 only). It creates an HTTP transport
 // providing timeout settings and authentication support, and also verifies the
 // remote API version.
@@ -68,7 +52,7 @@ func NewV2Repository(ctx context.Context, repoInfo *registry.RepositoryInfo, end
 	modifiers := registry.DockerHeaders(dockerversion.DockerUserAgent(ctx), metaHeaders)
 	authTransport := transport.NewTransport(base, modifiers...)
 
-	challengeManager, foundVersion, err := registry.PingV2Registry(endpoint, authTransport)
+	challengeManager, foundVersion, err := registry.PingV2Registry(endpoint.URL, authTransport)
 	if err != nil {
 		transportOK := false
 		if responseErr, ok := err.(registry.PingResponseError); ok {
@@ -86,7 +70,7 @@ func NewV2Repository(ctx context.Context, repoInfo *registry.RepositoryInfo, end
 		passThruTokenHandler := &existingTokenHandler{token: authConfig.RegistryToken}
 		modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, passThruTokenHandler))
 	} else {
-		creds := dumbCredentialStore{auth: authConfig}
+		creds := registry.NewStaticCredentialStore(authConfig)
 		tokenHandlerOptions := auth.TokenHandlerOptions{
 			Transport:   authTransport,
 			Credentials: creds,
diff --git a/hack/vendor.sh b/hack/vendor.sh
index 3c799745f8..00ef56b362 100755
--- a/hack/vendor.sh
+++ b/hack/vendor.sh
@@ -87,7 +87,7 @@ clone git github.com/boltdb/bolt v1.2.1
 clone git github.com/miekg/dns 75e6e86cc601825c5dbcd4e0c209eab180997cd7
 
 # get graph and distribution packages
-clone git github.com/docker/distribution 4e17ab5d319ac5b70b2769442947567a83386fbc
+clone git github.com/docker/distribution 07f32ac1831ed0fc71960b7da5d6bb83cb6881b5
 clone git github.com/vbatts/tar-split v0.9.11
 
 # get go-zfs packages
diff --git a/registry/auth.go b/registry/auth.go
index c5663f58c6..0b5257182e 100644
--- a/registry/auth.go
+++ b/registry/auth.go
@@ -91,6 +91,35 @@ func (lcs loginCredentialStore) SetRefreshToken(u *url.URL, service, token strin
 	lcs.authConfig.IdentityToken = token
 }
 
+type staticCredentialStore struct {
+	auth *types.AuthConfig
+}
+
+// NewStaticCredentialStore returns a credential store
+// which always returns the same credential values.
+func NewStaticCredentialStore(auth *types.AuthConfig) auth.CredentialStore {
+	return staticCredentialStore{
+		auth: auth,
+	}
+}
+
+func (scs staticCredentialStore) Basic(*url.URL) (string, string) {
+	if scs.auth == nil {
+		return "", ""
+	}
+	return scs.auth.Username, scs.auth.Password
+}
+
+func (scs staticCredentialStore) RefreshToken(*url.URL, string) string {
+	if scs.auth == nil {
+		return ""
+	}
+	return scs.auth.IdentityToken
+}
+
+func (scs staticCredentialStore) SetRefreshToken(*url.URL, string, string) {
+}
+
 type fallbackError struct {
 	err error
 }
@@ -108,33 +137,14 @@ func loginV2(authConfig *types.AuthConfig, endpoint APIEndpoint, userAgent strin
 	modifiers := DockerHeaders(userAgent, nil)
 	authTransport := transport.NewTransport(NewTransport(endpoint.TLSConfig), modifiers...)
 
-	challengeManager, foundV2, err := PingV2Registry(endpoint, authTransport)
-	if err != nil {
-		if !foundV2 {
-			err = fallbackError{err: err}
-		}
-		return "", "", err
-	}
-
 	credentialAuthConfig := *authConfig
 	creds := loginCredentialStore{
 		authConfig: &credentialAuthConfig,
 	}
 
-	tokenHandlerOptions := auth.TokenHandlerOptions{
-		Transport:     authTransport,
-		Credentials:   creds,
-		OfflineAccess: true,
-		ClientID:      AuthClientID,
-	}
-	tokenHandler := auth.NewTokenHandlerWithOptions(tokenHandlerOptions)
-	basicHandler := auth.NewBasicHandler(creds)
-	modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler))
-	tr := transport.NewTransport(authTransport, modifiers...)
-
-	loginClient := &http.Client{
-		Transport: tr,
-		Timeout:   15 * time.Second,
+	loginClient, foundV2, err := v2AuthHTTPClient(endpoint.URL, authTransport, modifiers, creds, nil)
+	if err != nil {
+		return "", "", err
 	}
 
 	endpointStr := strings.TrimRight(endpoint.URL.String(), "/") + "/v2/"
@@ -168,6 +178,34 @@ func loginV2(authConfig *types.AuthConfig, endpoint APIEndpoint, userAgent strin
 
 }
 
+func v2AuthHTTPClient(endpoint *url.URL, authTransport http.RoundTripper, modifiers []transport.RequestModifier, creds auth.CredentialStore, scopes []auth.Scope) (*http.Client, bool, error) {
+	challengeManager, foundV2, err := PingV2Registry(endpoint, authTransport)
+	if err != nil {
+		if !foundV2 {
+			err = fallbackError{err: err}
+		}
+		return nil, foundV2, err
+	}
+
+	tokenHandlerOptions := auth.TokenHandlerOptions{
+		Transport:     authTransport,
+		Credentials:   creds,
+		OfflineAccess: true,
+		ClientID:      AuthClientID,
+		Scopes:        scopes,
+	}
+	tokenHandler := auth.NewTokenHandlerWithOptions(tokenHandlerOptions)
+	basicHandler := auth.NewBasicHandler(creds)
+	modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler))
+	tr := transport.NewTransport(authTransport, modifiers...)
+
+	return &http.Client{
+		Transport: tr,
+		Timeout:   15 * time.Second,
+	}, foundV2, nil
+
+}
+
 // ResolveAuthConfig matches an auth configuration to a server address or a URL
 func ResolveAuthConfig(authConfigs map[string]types.AuthConfig, index *registrytypes.IndexInfo) types.AuthConfig {
 	configKey := GetAuthConfigKey(index)
@@ -215,7 +253,7 @@ func (err PingResponseError) Error() string {
 // challenge manager for the supported authentication types and
 // whether v2 was confirmed by the response. If a response is received but
 // cannot be interpreted a PingResponseError will be returned.
-func PingV2Registry(endpoint APIEndpoint, transport http.RoundTripper) (auth.ChallengeManager, bool, error) {
+func PingV2Registry(endpoint *url.URL, transport http.RoundTripper) (auth.ChallengeManager, bool, error) {
 	var (
 		foundV2   = false
 		v2Version = auth.APIVersion{
@@ -228,7 +266,7 @@ func PingV2Registry(endpoint APIEndpoint, transport http.RoundTripper) (auth.Cha
 		Transport: transport,
 		Timeout:   15 * time.Second,
 	}
-	endpointStr := strings.TrimRight(endpoint.URL.String(), "/") + "/v2/"
+	endpointStr := strings.TrimRight(endpoint.String(), "/") + "/v2/"
 	req, err := http.NewRequest("GET", endpointStr, nil)
 	if err != nil {
 		return nil, false, err
diff --git a/registry/service.go b/registry/service.go
index 25b4990e80..dbc16284f0 100644
--- a/registry/service.go
+++ b/registry/service.go
@@ -10,6 +10,7 @@ import (
 	"golang.org/x/net/context"
 
 	"github.com/Sirupsen/logrus"
+	"github.com/docker/distribution/registry/client/auth"
 	"github.com/docker/docker/reference"
 	"github.com/docker/engine-api/types"
 	registrytypes "github.com/docker/engine-api/types/registry"
@@ -132,11 +133,44 @@ func (s *DefaultService) Search(ctx context.Context, term string, limit int, aut
 		return nil, err
 	}
 
-	r, err := NewSession(endpoint.client, authConfig, endpoint)
-	if err != nil {
-		return nil, err
+	var client *http.Client
+	if authConfig != nil && authConfig.IdentityToken != "" && authConfig.Username != "" {
+		creds := NewStaticCredentialStore(authConfig)
+		scopes := []auth.Scope{
+			auth.RegistryScope{
+				Name:    "catalog",
+				Actions: []string{"search"},
+			},
+		}
+
+		modifiers := DockerHeaders(userAgent, nil)
+		v2Client, foundV2, err := v2AuthHTTPClient(endpoint.URL, endpoint.client.Transport, modifiers, creds, scopes)
+		if err != nil {
+			if fErr, ok := err.(fallbackError); ok {
+				logrus.Errorf("Cannot use identity token for search, v2 auth not supported: %v", fErr.err)
+			} else {
+				return nil, err
+			}
+		} else if foundV2 {
+			// Copy non transport http client features
+			v2Client.Timeout = endpoint.client.Timeout
+			v2Client.CheckRedirect = endpoint.client.CheckRedirect
+			v2Client.Jar = endpoint.client.Jar
+
+			logrus.Debugf("using v2 client for search to %s", endpoint.URL)
+			client = v2Client
+		}
 	}
 
+	if client == nil {
+		client = endpoint.client
+		if err := authorizeClient(client, authConfig, endpoint); err != nil {
+			return nil, err
+		}
+	}
+
+	r := newSession(client, authConfig, endpoint)
+
 	if index.Official {
 		localName := remoteName
 		if strings.HasPrefix(localName, "library/") {
diff --git a/registry/session.go b/registry/session.go
index bb51c7eb6e..d48b9e8d20 100644
--- a/registry/session.go
+++ b/registry/session.go
@@ -161,16 +161,7 @@ func (tr *authTransport) CancelRequest(req *http.Request) {
 	}
 }
 
-// NewSession creates a new session
-// TODO(tiborvass): remove authConfig param once registry client v2 is vendored
-func NewSession(client *http.Client, authConfig *types.AuthConfig, endpoint *V1Endpoint) (r *Session, err error) {
-	r = &Session{
-		authConfig:    authConfig,
-		client:        client,
-		indexEndpoint: endpoint,
-		id:            stringid.GenerateRandomID(),
-	}
-
+func authorizeClient(client *http.Client, authConfig *types.AuthConfig, endpoint *V1Endpoint) error {
 	var alwaysSetBasicAuth bool
 
 	// If we're working with a standalone private registry over HTTPS, send Basic Auth headers
@@ -178,7 +169,7 @@ func NewSession(client *http.Client, authConfig *types.AuthConfig, endpoint *V1E
 	if endpoint.String() != IndexServer && endpoint.URL.Scheme == "https" {
 		info, err := endpoint.Ping()
 		if err != nil {
-			return nil, err
+			return err
 		}
 		if info.Standalone && authConfig != nil {
 			logrus.Debugf("Endpoint %s is eligible for private registry. Enabling decorator.", endpoint.String())
@@ -192,11 +183,30 @@ func NewSession(client *http.Client, authConfig *types.AuthConfig, endpoint *V1E
 
 	jar, err := cookiejar.New(nil)
 	if err != nil {
-		return nil, errors.New("cookiejar.New is not supposed to return an error")
+		return errors.New("cookiejar.New is not supposed to return an error")
 	}
 	client.Jar = jar
 
-	return r, nil
+	return nil
+}
+
+func newSession(client *http.Client, authConfig *types.AuthConfig, endpoint *V1Endpoint) *Session {
+	return &Session{
+		authConfig:    authConfig,
+		client:        client,
+		indexEndpoint: endpoint,
+		id:            stringid.GenerateRandomID(),
+	}
+}
+
+// NewSession creates a new session
+// TODO(tiborvass): remove authConfig param once registry client v2 is vendored
+func NewSession(client *http.Client, authConfig *types.AuthConfig, endpoint *V1Endpoint) (*Session, error) {
+	if err := authorizeClient(client, authConfig, endpoint); err != nil {
+		return nil, err
+	}
+
+	return newSession(client, authConfig, endpoint), nil
 }
 
 // ID returns this registry session's ID.
diff --git a/vendor/src/github.com/docker/distribution/registry/client/auth/session.go b/vendor/src/github.com/docker/distribution/registry/client/auth/session.go
index f3497b17ad..d03d8ff0ed 100644
--- a/vendor/src/github.com/docker/distribution/registry/client/auth/session.go
+++ b/vendor/src/github.com/docker/distribution/registry/client/auth/session.go
@@ -72,15 +72,19 @@ type endpointAuthorizer struct {
 }
 
 func (ea *endpointAuthorizer) ModifyRequest(req *http.Request) error {
-	v2Root := strings.Index(req.URL.Path, "/v2/")
-	if v2Root == -1 {
+	pingPath := req.URL.Path
+	if v2Root := strings.Index(req.URL.Path, "/v2/"); v2Root != -1 {
+		pingPath = pingPath[:v2Root+4]
+	} else if v1Root := strings.Index(req.URL.Path, "/v1/"); v1Root != -1 {
+		pingPath = pingPath[:v1Root] + "/v2/"
+	} else {
 		return nil
 	}
 
 	ping := url.URL{
 		Host:   req.URL.Host,
 		Scheme: req.URL.Scheme,
-		Path:   req.URL.Path[:v2Root+4],
+		Path:   pingPath,
 	}
 
 	challenges, err := ea.challenges.GetChallenges(ping)
@@ -151,6 +155,19 @@ func (rs RepositoryScope) String() string {
 	return fmt.Sprintf("repository:%s:%s", rs.Repository, strings.Join(rs.Actions, ","))
 }
 
+// RegistryScope represents a token scope for access
+// to resources in the registry.
+type RegistryScope struct {
+	Name    string
+	Actions []string
+}
+
+// String returns the string representation of the user
+// using the scope grammar
+func (rs RegistryScope) String() string {
+	return fmt.Sprintf("registry:%s:%s", rs.Name, strings.Join(rs.Actions, ","))
+}
+
 // TokenHandlerOptions is used to configure a new token handler
 type TokenHandlerOptions struct {
 	Transport   http.RoundTripper