diff --git a/server/api_test.go b/server/api_test.go
index a7891208d35e8e6d9ed1781ec5582b196a49b799..80a224861db631de0db429beb72730c8bd278494 100644
--- a/server/api_test.go
+++ b/server/api_test.go
@@ -259,6 +259,7 @@ func TestRefreshToken(t *testing.T) {
 			EmailVerified: true,
 			Groups:        []string{"a", "b"},
 		},
+		ConnectorData: []byte(`{"some":"data"}`),
 	}
 
 	if err := s.CreateRefresh(r); err != nil {
diff --git a/server/handlers.go b/server/handlers.go
index a4db71cb30bd5f3d3f613d777f6f5b91d3b891ec..80965daf1bb7a08f62588cdd804bac9c70afab57 100644
--- a/server/handlers.go
+++ b/server/handlers.go
@@ -490,6 +490,7 @@ func (s *Server) finalizeLogin(identity connector.Identity, authReq storage.Auth
 	updater := func(a storage.AuthRequest) (storage.AuthRequest, error) {
 		a.LoggedIn = true
 		a.Claims = claims
+		a.ConnectorData = identity.ConnectorData
 		return a, nil
 	}
 	if err := s.storage.UpdateAuthRequest(authReq.ID, updater); err != nil {
@@ -621,14 +622,15 @@ func (s *Server) sendCodeResponse(w http.ResponseWriter, r *http.Request, authRe
 		switch responseType {
 		case responseTypeCode:
 			code = storage.AuthCode{
-				ID:          storage.NewID(),
-				ClientID:    authReq.ClientID,
-				ConnectorID: authReq.ConnectorID,
-				Nonce:       authReq.Nonce,
-				Scopes:      authReq.Scopes,
-				Claims:      authReq.Claims,
-				Expiry:      s.now().Add(time.Minute * 30),
-				RedirectURI: authReq.RedirectURI,
+				ID:            storage.NewID(),
+				ClientID:      authReq.ClientID,
+				ConnectorID:   authReq.ConnectorID,
+				Nonce:         authReq.Nonce,
+				Scopes:        authReq.Scopes,
+				Claims:        authReq.Claims,
+				Expiry:        s.now().Add(time.Minute * 30),
+				RedirectURI:   authReq.RedirectURI,
+				ConnectorData: authReq.ConnectorData,
 			}
 			if err := s.storage.CreateAuthCode(code); err != nil {
 				s.logger.Errorf("Failed to create auth code: %v", err)
@@ -824,15 +826,16 @@ func (s *Server) handleAuthCode(w http.ResponseWriter, r *http.Request, client s
 	var refreshToken string
 	if reqRefresh {
 		refresh := storage.RefreshToken{
-			ID:          storage.NewID(),
-			Token:       storage.NewID(),
-			ClientID:    authCode.ClientID,
-			ConnectorID: authCode.ConnectorID,
-			Scopes:      authCode.Scopes,
-			Claims:      authCode.Claims,
-			Nonce:       authCode.Nonce,
-			CreatedAt:   s.now(),
-			LastUsed:    s.now(),
+			ID:            storage.NewID(),
+			Token:         storage.NewID(),
+			ClientID:      authCode.ClientID,
+			ConnectorID:   authCode.ConnectorID,
+			Scopes:        authCode.Scopes,
+			Claims:        authCode.Claims,
+			Nonce:         authCode.Nonce,
+			ConnectorData: authCode.ConnectorData,
+			CreatedAt:     s.now(),
+			LastUsed:      s.now(),
 		}
 		token := &internal.RefreshToken{
 			RefreshId: refresh.ID,
diff --git a/storage/storage.go b/storage/storage.go
index 85a60965c0be44abff53e2212b5158435a64231b..cb2a7e0cdd368e7fea258b9c65fadc8c136ebe8b 100644
--- a/storage/storage.go
+++ b/storage/storage.go
@@ -181,7 +181,8 @@ type AuthRequest struct {
 
 	// The connector used to login the user and any data the connector wishes to persists.
 	// Set when the user authenticates.
-	ConnectorID string
+	ConnectorID   string
+	ConnectorData []byte
 }
 
 // AuthCode represents a code which can be exchanged for an OAuth2 token response.
@@ -212,8 +213,9 @@ type AuthCode struct {
 	Scopes []string
 
 	// Authentication data provided by an upstream source.
-	ConnectorID string
-	Claims      Claims
+	ConnectorID   string
+	ConnectorData []byte
+	Claims        Claims
 
 	Expiry time.Time
 }
@@ -235,8 +237,9 @@ type RefreshToken struct {
 	ClientID string
 
 	// Authentication data provided by an upstream source.
-	ConnectorID string
-	Claims      Claims
+	ConnectorID   string
+	ConnectorData []byte
+	Claims        Claims
 
 	// Scopes present in the initial request. Refresh requests may specify a set
 	// of scopes different from the initial request when refreshing a token,