Index: wp-login.php
===================================================================
--- wp-login.php	(revision 21027)
+++ wp-login.php	(working copy)
@@ -82,6 +82,10 @@
 	$login_header_url   = apply_filters( 'login_headerurl',   $login_header_url   );
 	$login_header_title = apply_filters( 'login_headertitle', $login_header_title );
 
+	// Don't allow interim logins to navigate away from the page.
+	if ( $interim_login )
+		$login_header_url = '#';
+
 	?>
 	</head>
 	<body class="login<?php if ( wp_is_mobile() ) echo ' mobile'; ?>">
@@ -126,8 +130,13 @@
  * @param string $input_id Which input to auto-focus
  */
 function login_footer($input_id = '') {
-	?>
+	global $interim_login;
+
+	// Don't allow interim logins to navigate away from the page.
+	if ( ! $interim_login ): ?>
 	<p id="backtoblog"><a href="<?php echo esc_url( home_url( '/' ) ); ?>" title="<?php esc_attr_e( 'Are you lost?' ); ?>"><?php printf( __( '&larr; Back to %s' ), get_bloginfo( 'title', 'display' ) ); ?></a></p>
+	<?php endif; ?>
+
 	</div>
 
 	<?php if ( !empty($input_id) ) : ?>
@@ -555,6 +564,9 @@
 default:
 	$secure_cookie = '';
 	$interim_login = isset($_REQUEST['interim-login']);
+	$customize_login = isset( $_REQUEST['customize-login'] );
+	if ( $customize_login )
+		wp_enqueue_script( 'customize-base' );
 
 	// If the user wants ssl but the session is not ssl, force a secure cookie.
 	if ( !empty($_POST['log']) && !force_ssl_admin() ) {
@@ -592,10 +604,18 @@
 		if ( $interim_login ) {
 			$message = '<p class="message">' . __('You have logged in successfully.') . '</p>';
 			login_header( '', $message ); ?>
+
+			<?php if ( ! $customize_login ) : ?>
 			<script type="text/javascript">setTimeout( function(){window.close()}, 8000);</script>
 			<p class="alignright">
 			<input type="button" class="button-primary" value="<?php esc_attr_e('Close'); ?>" onclick="window.close()" /></p>
-			</div></body></html>
+			<?php endif; ?>
+			</div>
+			<?php do_action( 'login_footer' ); ?>
+			<?php if ( $customize_login ) : ?>
+				<script type="text/javascript">setTimeout( function(){ new wp.customize.Messenger({ url: '<?php echo wp_customize_url(); ?>', channel: 'login' }).send('login') }, 1000 );</script>
+			<?php endif; ?>
+			</body></html>
 <?php		exit;
 		}
 
@@ -666,6 +686,9 @@
 <?php	} else { ?>
 		<input type="hidden" name="redirect_to" value="<?php echo esc_attr($redirect_to); ?>" />
 <?php 	} ?>
+<?php   if ( $customize_login ) : ?>
+		<input type="hidden" name="customize-login" value="1" />
+<?php   endif; ?>
 		<input type="hidden" name="testcookie" value="1" />
 	</p>
 </form>
Index: wp-includes/class-wp-customize-manager.php
===================================================================
--- wp-includes/class-wp-customize-manager.php	(revision 21027)
+++ wp-includes/class-wp-customize-manager.php	(working copy)
@@ -17,6 +17,8 @@
 	protected $sections = array();
 	protected $controls = array();
 
+	protected $nonce_tick;
+
 	protected $customized;
 
 	private $_post_values;
@@ -31,6 +33,8 @@
 		require( ABSPATH . WPINC . '/class-wp-customize-section.php' );
 		require( ABSPATH . WPINC . '/class-wp-customize-control.php' );
 
+		add_filter( 'wp_die_handler', array( $this, 'wp_die_handler' ) );
+
 		add_action( 'setup_theme',  array( $this, 'setup_theme' ) );
 		add_action( 'wp_loaded',    array( $this, 'wp_loaded' ) );
 
@@ -53,6 +57,43 @@
 	}
 
 	/**
+	 * Return true if it's an AJAX request.
+	 *
+	 * @since 3.4.0
+	 */
+	public function doing_ajax() {
+		return isset( $_POST['customized'] ) || ( defined( 'DOING_AJAX' ) && DOING_AJAX );
+	}
+
+	/**
+	 * Custom wp_die wrapper. Returns either the standard message for UI
+	 * or the AJAX message.
+	 *
+	 * @param  mixed $ajax_message AJAX return
+	 * @param  mixed $message      UI message
+	 *
+	 * @since 3.4.0
+	 */
+	private function wp_die( $ajax_message, $message ) {
+		if ( $this->doing_ajax() )
+			wp_die( $ajax_message );
+
+		wp_die( $message );
+	}
+
+	/**
+	 * Return the AJAX wp_die() handler if it's a customized request.
+	 *
+	 * @since 3.4.0
+	 */
+	public function wp_die_handler() {
+		if ( $this->doing_ajax() )
+			return '_ajax_wp_die_handler';
+
+		return '_default_wp_die_handler';
+	}
+
+	/**
 	 * Start preview and customize theme.
 	 *
 	 * Check if customize query variable exist. Init filters to filter the current theme.
@@ -60,8 +101,10 @@
 	 * @since 3.4.0
 	 */
 	public function setup_theme() {
-		if ( is_admin() && ! defined( 'DOING_AJAX' ) )
-			auth_redirect();
+		if ( is_admin() && ! $this->doing_ajax() )
+		    auth_redirect();
+		elseif ( $this->doing_ajax() && ! is_user_logged_in() )
+		    wp_die( 0 );
 
 		send_origin_headers();
 
@@ -71,14 +114,17 @@
 
 		// You can't preview a theme if it doesn't exist, or if it is not allowed (unless active).
 		if ( ! $this->theme->exists() )
-			wp_die( __( 'Cheatin&#8217; uh?' ) );
+			$this->wp_die( -1, __( 'Cheatin&#8217; uh?' ) );
 
 		if ( $this->theme->get_stylesheet() != get_stylesheet() && ( ! $this->theme()->is_allowed() || ! current_user_can( 'switch_themes' ) ) )
-			wp_die( __( 'Cheatin&#8217; uh?' ) );
+			$this->wp_die( -1, __( 'Cheatin&#8217; uh?' ) );
 
 		if ( ! current_user_can( 'edit_theme_options' ) )
-			wp_die( __( 'Cheatin&#8217; uh?' ) );
+			$this->wp_die( -1, __( 'Cheatin&#8217; uh?' ) );
 
+		if ( $this->doing_ajax() && ! defined( 'DOING_AJAX' ) ) // Fire on previews.
+			$this->nonce_tick = check_ajax_referer( 'customize_preview-' . $this->get_stylesheet(), 'nonce' );
+
 		$this->start_previewing_theme();
 		show_admin_bar( false );
 	}
@@ -300,6 +346,11 @@
 			'backgroundImageHasDefault' => current_theme_supports( 'custom-background', 'default-image' ),
 		);
 
+		if ( 2 == $this->nonce_tick ) {
+			$settings['customize-controls-nonce'] = wp_create_nonce( 'customize-controls-' . $this->get_stylesheet() );
+			$settings['customize-preview-nonce'] = wp_create_nonce( 'customize_preview-' . $this->get_stylesheet() );
+		}
+
 		foreach ( $this->settings as $id => $setting ) {
 			$settings['values'][ $id ] = $setting->js_value();
 		}
@@ -949,4 +1000,4 @@
 		return '#' . $unhashed;
 
 	return $color;
-}
\ No newline at end of file
+}
Index: wp-includes/script-loader.php
===================================================================
--- wp-includes/script-loader.php	(revision 21027)
+++ wp-includes/script-loader.php	(working copy)
@@ -305,6 +305,7 @@
 		'saved'     => __( 'Saved' ),
 		'cancel'    => __( 'Cancel' ),
 		'close'     => __( 'Close' ),
+		'cheatin'   => __( 'Cheatin&#8217; uh?' ),
 	) );
 
 	if ( is_admin() ) {
Index: wp-admin/customize.php
===================================================================
--- wp-admin/customize.php	(revision 21027)
+++ wp-admin/customize.php	(working copy)
@@ -7,6 +7,8 @@
  * @since 3.4.0
  */
 
+define( 'IFRAME_REQUEST', true );
+
 require_once( './admin.php' );
 if ( ! current_user_can( 'edit_theme_options' ) )
 	wp_die( __( 'Cheatin&#8217; uh?' ) );
@@ -57,7 +59,8 @@
 <body class="<?php echo esc_attr( $body_class ); ?>">
 <div class="wp-full-overlay expanded">
 	<form id="customize-controls" class="wrap wp-full-overlay-sidebar">
-		<?php wp_nonce_field( 'customize_controls-' . $wp_customize->get_stylesheet() ); ?>
+		<?php wp_nonce_field( 'customize_controls-' . $wp_customize->get_stylesheet(), 'customize-controls-nonce', false ); ?>
+		<?php wp_nonce_field( 'customize_preview-' . $wp_customize->get_stylesheet(), 'customize-preview-nonce', false ); ?>
 		<div id="customize-header-actions" class="wp-full-overlay-header">
 			<?php
 				$save_text = $wp_customize->is_theme_active() ? __( 'Save &amp; Publish' ) : __( 'Save &amp; Activate' );
@@ -140,6 +143,11 @@
 		'TB_iframe'      => 'true'
 	), home_url( '/' ) );
 
+	$login_url = add_query_arg( array(
+		'interim-login' => 1,
+		'customize-login' => 1
+	), wp_login_url() );
+
 	$settings = array(
 		'theme'    => array(
 			'stylesheet' => $wp_customize->get_stylesheet(),
@@ -153,6 +161,7 @@
 			'allowed'       => array_map( 'esc_url', $allowed_urls ),
 			'isCrossDomain' => $cross_domain,
 			'fallback'      => $fallback_url,
+			'login'         => $login_url,
 		),
 		'browser'  => array(
 			'mobile' => wp_is_mobile(),
Index: wp-admin/js/customize-controls.dev.js
===================================================================
--- wp-admin/js/customize-controls.dev.js	(revision 21027)
+++ wp-admin/js/customize-controls.dev.js	(working copy)
@@ -334,6 +334,18 @@
 					return;
 				}
 
+				// Check if the user is not logged in.
+				if ( '0' === response ) {
+					deferred.rejectWith( self, [ 'logged out' ] );
+					return;
+				}
+
+				// Check for cheaters.
+				if ( '-1' === response ) {
+					deferred.rejectWith( self, [ 'cheatin' ] );
+					return;
+				}
+
 				// Check for a signature in the request.
 				index = response.lastIndexOf( signature );
 				if ( -1 === index || index < response.lastIndexOf('</html>') ) {
@@ -541,7 +553,52 @@
 			this.loading.fail( function( reason, location ) {
 				if ( 'redirect' === reason && location )
 					self.url( location );
+
+				if ( 'logged out' === reason ) {
+					if ( self.iframe ) {
+						self.iframe.destroy();
+						delete self.iframe;
+					}
+
+					self.login().done( self.refresh );
+				}
+
+				if ( 'cheatin' === reason )
+					self.cheatin();
 			});
+		},
+
+		login: function() {
+			var previewer = this,
+				deferred, messenger, iframe;
+
+			if ( this._login )
+				return this._login;
+
+			deferred = $.Deferred();
+			this._login = deferred.promise();
+
+			messenger = new api.Messenger({
+				channel: 'login',
+				url:     api.settings.url.login
+			});
+
+			iframe = $('<iframe src="' + api.settings.url.login + '" />').appendTo( this.container );
+
+			messenger.targetWindow( iframe[0].contentWindow );
+
+			messenger.bind( 'login', function() {
+				iframe.remove();
+				messenger.destroy();
+				delete previewer._login;
+				deferred.resolve();
+			});
+
+			return this._login;
+		},
+
+		cheatin: function() {
+			$( document.body ).empty().addClass('cheatin').append( '<p>' + api.l10n.cheatin + '</p>' );
 		}
 	});
 
@@ -587,20 +644,25 @@
 			url:         api.settings.url.preview,
 			allowedUrls: api.settings.url.allowed
 		}, {
+
+			p_nonce: $('#customize-preview-nonce').val(),
+			c_nonce: $('#customize-controls-nonce').val(),
+
 			query: function() {
 				return {
 					wp_customize: 'on',
 					theme:        api.settings.theme.stylesheet,
-					customized:   JSON.stringify( api.get() )
+					customized:   JSON.stringify( api.get() ),
+					nonce:        this.p_nonce
+					
 				};
 			},
 
-			nonce: $('#_wpnonce').val(),
-
 			save: function() {
-				var query = $.extend( this.query(), {
+				var self  = this,
+					query = $.extend( this.query(), {
 						action: 'customize_save',
-						nonce:  this.nonce
+						nonce:  this.c_nonce
 					}),
 					request = $.post( api.settings.url.ajax, query );
 
@@ -612,7 +674,23 @@
 					body.removeClass('saving');
 				});
 
-				request.done( function() {
+				request.done( function( response ) {
+					// Check if the user is logged out.
+					if ( '0' === response ) {
+						self.iframe.iframe.hide();
+						self.login().done( function() {
+							self.save();
+							self.iframe.iframe.show();
+						});
+						return;
+					}
+
+					// Check for cheaters.
+					if ( '-1' === response ) {
+						self.cheatin();
+						return;
+					}
+
 					api.trigger( 'saved' );
 				});
 			}
Index: wp-admin/css/customize-controls.dev.css
===================================================================
--- wp-admin/css/customize-controls.dev.css	(revision 21027)
+++ wp-admin/css/customize-controls.dev.css	(working copy)
@@ -514,3 +514,24 @@
 	-webkit-overflow-scrolling: touch;
 }
 
+/**
+ * Handle cheaters.
+ */
+body.cheatin {
+	min-width: 0;
+	background: #f9f9f9;
+	padding: 50px;
+}
+
+body.cheatin p {
+	max-width: 700px;
+	margin: 0 auto;
+	padding: 2em;
+	font-size: 14px;
+
+	background: #fff;
+	border: 1px solid #dfdfdf;
+
+	-webkit-border-radius: 3px;
+	border-radius:         3px;
+}
\ No newline at end of file
