- 28 Jan 2025
- 4 Minutes to read
- Print
- DarkLight
Addressing Security-Related Errors for iPhone Users
- Updated on 28 Jan 2025
- 4 Minutes to read
- Print
- DarkLight
This document outlines a solution to resolve security-related errors encountered when using TouchNet as a Payment Gateway within an iframe on Apple devices. This approach leverages client-side JavaScript to adapt the behavior based on the device type, ensuring a seamless user experience.
Background
The Problem
Apple device users experience a security-related error and cannot continue registering for an Event when the Event is in an iframe, and the Payment Gateway is TouchNet. The security restrictions (e.g., cross-site scripting rules) prevent cross-domain redirects within iframes, which results in the following.
- Session cookies and security headers are blocked.
- An error interrupts the user’s ability to complete transactions.
In short, TouchNet’s architecture includes a redirect that occurs within an iframe, which is considered a security issue and blocked by Apple.
Sample Use Case:
An organization’s mobile app uses iframes to display Events. Because of Apple’s restrictions, TouchNet's redirect flow fails, requiring an alternative solution.
Recommended Solution
We suggest customers use client-side JavaScript to:
- Detect if the potential Attendee is on an iPhone.
- Open the Event in a new window for iPhone users.
- Continue loading the Event in an iframe for other devices.
Technical Solution
Why TouchNet and Iframes Don’t Work on Apple Devices
TouchNet’s cross-domain redirect flow is incompatible with iframes on Apple devices because:
- Session cookies and security headers cannot be securely shared across domains in an iframe.
- Apple's browser policies block such redirects for security reasons.
Key Elements of the Solution
- Device Detection: Check the
navigator.userAgent
to identify iPhone users. - Dynamic Behavior:
- For iPhone users, open the Event in a new window using
window.open
. - For other devices, load the TouchNet script dynamically into an iframe.
- For iPhone users, open the Event in a new window using
- Responsiveness: The script ensures a consistent and user-friendly interface on all devices.
How It Works
- Device Detection: The
isIPhone
function checks thenavigator.userAgent
to identify iPhone users. - Dynamic Behavior:
- For iPhone Users:
- Users see a message and the Open Event button.
- After clicking the Open Event button, the Event opens in a new window using
window.open
.
- For Other Devices:
- The TouchNet script is dynamically added to the page, and the page loads in an iframe.
- For iPhone Users:
Implementation Steps
The script must be added to the hosting page and cannot be managed within the Blackthorn Events application.
- Update HTML: Replace your existing iframe setup with the provided HTML structure and script.
- Customize Parameters: Replace
scriptPath
with the data path specific to your Event. - Deploy and Test:
- Upload the updated HTML to your server.
- Test the implementation on both iPhone and non-iPhone devices.
Sample Code
Copy and paste this code in the body
tag.
<div id="ios-message" style="display: none;">
<p id="iphone-message">
To register for this event, please click the button below to open the event in a new window.
</p>
<button id="open-event-button">Open Event</button>
</div>
<div id="event-container"></div>
<script>
// Function to detect if the device is an iPhone
function isIPhone() {
return /iPhone/i.test(navigator.userAgent);
}
// Function to initialize the event loader
function initializeEventLoader(eventUrl, scriptPath) {
if (isIPhone()) {
handleIPhoneCase(eventUrl, scriptPath);
} else {
loadEventScript(eventUrl, scriptPath);
}
}
// Function to handle the iPhone-specific case
function handleIPhoneCase(eventUrl, scriptPath) {
const message = document.getElementById("ios-message");
const button = document.getElementById("open-event-button");
const finalUrl = `${eventUrl}${scriptPath}`;
// Show the message and button
message.style.display = "block";
// Attach the click event to the button
button.addEventListener("click", () => {
window.open(finalUrl, "_blank", "noopener,noreferrer");
});
}
// Function to load the event script for non-iPhone devices
function loadEventScript(eventUrl, scriptPath) {
const script = document.createElement("script");
script.src = `${eventUrl}/loader`;
script.setAttribute("data-path", scriptPath);
// Append the script to the container
const eventContainer = document.getElementById("event-container");
eventContainer.appendChild(script);
}
// Initialize on page load
document.addEventListener("DOMContentLoaded", () => {
const eventUrl = "https://events.blackthorn.io";
const eventPath = "/5e53zvb7/5a195eDuv9X"; // <<< Change this to your event path
initializeEventLoader(eventUrl, eventPath);
});
</script>
Here is the complete HTML code with the solution embedded and some CSS changes.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background-color: #cdcdcd;
}
#ios-message {
background-color: #ffffff;
border: 1px solid #cdcdcd;
padding: 1rem;
border-radius: 5px;
margin-bottom: 20px;
text-align: center;
padding-top: 0;
}
#iphone-message {
font-size: 16px;
line-height: 1.5;
color: #333;
text-align: center;
margin-bottom: 1rem;
}
#open-event-button {
padding: 10px 20px;
font-size: 16px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
margin: 0 auto;
}
#open-event-button:hover {
background-color: #0056b3;
}
#event-container {
height: 900px;
margin-top: 20px;
}
</style>
</head>
<body>
<h1>Iframe Demo</h1>
<div id="ios-message" style="display: none;">
<p id="iphone-message">
To register for this event, please click the button below to open the event in a new window.
</p>
<button id="open-event-button">Open Event</button>
</div>
<div id="event-container"></div>
<script>
// Function to detect if the device is an iPhone
function isIPhone() {
return /iPhone/i.test(navigator.userAgent);
}
// Function to initialize the event loader
function initializeEventLoader(eventUrl, scriptPath) {
if (isIPhone()) {
handleIPhoneCase(eventUrl, scriptPath);
} else {
loadEventScript(eventUrl, scriptPath);
}
}
// Function to handle the iPhone-specific case
function handleIPhoneCase(eventUrl, scriptPath) {
const message = document.getElementById("ios-message");
const button = document.getElementById("open-event-button");
const finalUrl = `${eventUrl}${scriptPath}`;
// Show the message and button
message.style.display = "block";
// Attach the click event to the button
button.addEventListener("click", () => {
window.open(finalUrl, "_blank", "noopener,noreferrer");
});
}
// Function to load the event script for non-iPhone devices
function loadEventScript(eventUrl, scriptPath) {
const script = document.createElement("script");
script.src = `${eventUrl}/loader`;
script.setAttribute("data-path", scriptPath);
// Append the script to the container
const eventContainer = document.getElementById("event-container");
eventContainer.appendChild(script);
}
// Initialize on page load
document.addEventListener("DOMContentLoaded", () => {
const eventUrl = "https://events.blackthorn.io";
const eventPath = "/5e53zvb7/5a195eDuv9X"; // <<< Change this to your event path
initializeEventLoader(eventUrl, eventPath);
});
</script>
</body>
Testing and Validation
Pre-requisite: Ensure pop-ups are not blocked for iPhone users.
Test Scenarios
- iPhone Devices:
- Open the page and verify that the message and Open Event button are displayed.
- Click Open Event and confirm the Event opens in a new browser window.
- Non-iPhone Devices:
- Open the page and verify that the Event loads directly in an iframe.
End-User Experience
- iPhone Users: The Event opens seamlessly in a new browser window, bypassing Apple’s security restrictions.
- Other Users: The Event continues to load within the iframe as before.