diff --git a/includes/webform.pages.inc b/includes/webform.pages.inc
index 172fad9..9727f3a 100644
--- a/includes/webform.pages.inc
+++ b/includes/webform.pages.inc
@@ -36,7 +36,7 @@ function webform_configure_form($form, &$form_state, $node) {
   $form['submission']['confirmation'] = array(
     '#type' => 'text_format',
     '#title' => t('Confirmation message'),
-    '#description' => t('Message to be shown upon successful submission. If the redirection location is set to <em>Confirmation page</em> it will be shown on its own page, otherwise this displays as a message.'),
+    '#description' => t('Message to be shown upon successful submission. If the redirection location is set to <em>Confirmation page</em> it will be shown on its own page, otherwise this displays as a message. Supports Webform token replacements.'),
     '#default_value' => $node->webform['confirmation'],
     '#cols' => 40,
     '#rows' => 10,
diff --git a/webform.module b/webform.module
index ab8b3aa..ce45697 100644
--- a/webform.module
+++ b/webform.module
@@ -117,8 +117,8 @@ function webform_menu() {
     'title' => 'Webform confirmation',
     'page callback' => '_webform_confirmation',
     'page arguments' => array(1),
-    'access callback' => 'node_access',
-    'access arguments' => array('view', 1),
+    'access callback' => 'webform_confirmation_page_access',
+    'access arguments' => array(1),
     'type' => MENU_CALLBACK,
   );
   $items['node/%webform_menu/webform'] = array(
@@ -438,6 +438,43 @@ function webform_menu_email_load($eid, $nid) {
   return $email;
 }
 
+function webform_confirmation_page_access($node) {
+  global $user;
+
+  // Make sure sid is a positive integer.
+  $sid = (!empty($_GET['sid']) && (int) $_GET['sid'] > 0) ? (int) $_GET['sid'] : NULL;
+
+  // If sid, load submission.
+  if ($sid) {
+    module_load_include('inc', 'webform', 'includes/webform.submissions');
+    $submission = webform_get_submission($node->nid, $sid);
+  }
+  else {
+    $submission = NULL;
+  }
+
+  if ($submission) {
+    // Logged-in users.
+    if ($user->uid) {
+      // User's own submission.
+      if ($submission->uid === $user->uid && node_access('view', $node)) {
+        return TRUE;
+      }
+      // User has results access to this submission.
+      elseif (webform_submission_access($node, $submission)) {
+        return TRUE;
+      }
+    }
+    // Anonymous user for their own submission. Submission must be from
+    // anonymous user at the same host within past few seconds.
+    elseif ((int) $user->uid === 0 && (int) $submission->uid === 0 && $submission->remote_addr === $user->hostname && (int) $submission->submitted + 5 > time()) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
 function webform_submission_access($node, $submission, $op = 'view', $account = NULL) {
   global $user;
   $account = isset($account) ? $account : $user;
@@ -2717,6 +2754,7 @@ function webform_client_form_submit($form, &$form_state) {
 
   // Strip out empty tags added by WYSIWYG editors if needed.
   $confirmation = strlen(trim(strip_tags($node->webform['confirmation']))) ? $node->webform['confirmation'] : '';
+  $confirmation = _webform_filter_values($confirmation, $node, $submission, NULL, FALSE, TRUE);
 
   // Clean up the redirect URL and filter it for webform tokens.
   $redirect_url = trim($node->webform['redirect_url']);
@@ -2849,6 +2887,12 @@ function template_preprocess_webform_form(&$vars) {
  */
 function template_preprocess_webform_confirmation(&$vars) {
   $confirmation = check_markup($vars['node']->webform['confirmation'], $vars['node']->webform['confirmation_format'], '', TRUE);
+
+  // Replace tokens.
+  module_load_include('inc', 'webform', 'includes/webform.submissions');
+  $submission = webform_get_submission($vars['node']->nid, $vars['sid']);
+  $confirmation = _webform_filter_values($confirmation, $vars['node'], $submission, NULL, FALSE, TRUE);
+
   // Strip out empty tags added by WYSIWYG editors if needed.
   $vars['confirmation_message'] = strlen(trim(strip_tags($confirmation))) ? $confirmation : '';
 }
