diff --git a/connector/oidc/oidc.go b/connector/oidc/oidc.go
index 0310266c7c5f80dadf57f993284ef012ef8ba607..db9c641f21e93f4979fc637603479795d5e9d466 100644
--- a/connector/oidc/oidc.go
+++ b/connector/oidc/oidc.go
@@ -117,6 +117,7 @@ func (c *Config) Open(logger logrus.FieldLogger) (conn connector.Connector, err
 
 var (
 	_ connector.CallbackConnector = (*oidcConnector)(nil)
+	_ connector.RefreshConnector  = (*oidcConnector)(nil)
 )
 
 type oidcConnector struct {
@@ -188,3 +189,8 @@ func (c *oidcConnector) HandleCallback(s connector.Scopes, r *http.Request) (ide
 	}
 	return identity, nil
 }
+
+// Refresh is implemented for backwards compatibility, even though it's a no-op.
+func (c *oidcConnector) Refresh(ctx context.Context, s connector.Scopes, identity connector.Identity) (connector.Identity, error) {
+	return identity, nil
+}
diff --git a/connector/saml/saml.go b/connector/saml/saml.go
index a7b01734b56ff587808d32293b879c07843583b5..7fad1cc38ad7270de5399431068d4c7b368cd674 100644
--- a/connector/saml/saml.go
+++ b/connector/saml/saml.go
@@ -241,12 +241,6 @@ type provider struct {
 
 func (p *provider) POSTData(s connector.Scopes, id string) (action, value string, err error) {
 
-	// NOTE(ericchiang): If we can't follow up with the identity provider, can we
-	// support refresh tokens?
-	if s.OfflineAccess {
-		return "", "", fmt.Errorf("SAML does not support offline access")
-	}
-
 	r := &authnRequest{
 		ProtocolBinding: bindingPOST,
 		ID:              id,
diff --git a/server/handlers.go b/server/handlers.go
index c7da2d5b140ac7fa5c5a341dc134ed64b3e11cbf..5bd469c6d93a9c81b9c35ac3f8c256a5d48e3434 100644
--- a/server/handlers.go
+++ b/server/handlers.go
@@ -646,6 +646,20 @@ func (s *Server) handleAuthCode(w http.ResponseWriter, r *http.Request, client s
 	}
 
 	reqRefresh := func() bool {
+		// Ensure the connector supports refresh tokens.
+		//
+		// Connectors like `samlExperimental` do not implement RefreshConnector.
+		conn, ok := s.connectors[authCode.ConnectorID]
+		if !ok {
+			s.logger.Errorf("connector ID not found: %q", authCode.ConnectorID)
+			s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError)
+			return false
+		}
+		_, ok = conn.Connector.(connector.RefreshConnector)
+		if !ok {
+			return false
+		}
+
 		for _, scope := range authCode.Scopes {
 			if scope == scopeOfflineAccess {
 				return true