
Implementing Cross-Platform Push Notifications in Sakai
A Deep Dive into iOS Safari and Web Push
Implementing Cross-Platform Push Notifications in Sakai: A Deep Dive into iOS Safari and Web Push
Introduction
Push notifications have become an essential feature for modern learning management systems, keeping students and instructors connected to their coursework even when they’re not actively browsing the platform. However, implementing push notifications across different platforms, especially Apple’s iOS Safari, presents challenges that require careful attention.
In this post, we’ll walk through our journey of enhancing Sakai’s push notification system to support iOS Safari, the intricacies we discovered, the problems we solved, and the debugging techniques that made it work.
The Challenge: iOS Safari and Web Push
When we began investigating push notifications for iOS Safari users, we thought we’d need to subscribe to Apple’s developer services and manage APNs certificates. However, we discovered that iOS 16.4+ introduced support for the Web Push Protocol in Progressive Web Apps (PWAs), which uses the same VAPID (Voluntary Application Server Identification) authentication as other browsers, no APNs certificates required!
Key Discovery: PWA Requirement
The critical insight was that iOS Safari requires the site to be installed as a PWA before push notifications will work. This is different from Android browsers and desktop Safari, which can receive push notifications directly in the browser.
Platform-Specific Implementation
iOS Safari PWA Requirements
- iOS 16.4+ minimum version
- PWA installation mandatory (add to home screen)
- User interaction required for permission requests
- Strict VAPID subject validation
Android Chrome/Firefox
- No PWA required - works directly in browser
- Background support for notifications
- Firebase Cloud Messaging (FCM) backend integration
Desktop Browsers
- Universal support across Chrome, Firefox, Safari, Edge
- Standard Web Push Protocol implementation
The Implementation Journey
1. VAPID Subject Configuration Issues
Our first major hurdle was Apple’s strict VAPID subject validation. We discovered that Apple’s push service returns 403 Forbidden for improperly formatted subjects.
Problem: Default configuration used empty string
# This caused 403 errors from Apple
portal.notifications.push.subject=""
Solution: Smart defaults with proper formatting
String defaultSubject = "https://" + serverConfigurationService.getServerName();
String pushSubject = serverConfigurationService.getString("portal.notifications.push.subject", defaultSubject);
Key Requirements for Apple:
- No spaces after colons:
mailto:admin@school.edu
✅ (notmailto: <admin@school.edu>
❌) - Valid HTTPS URLs or mailto addresses
- Domain doesn’t need to match your Sakai instance
2. Enhanced Browser Detection
We implemented comprehensive browser detection to provide platform-specific experiences:
export const isIOSSafari = () => {
const ua = getUserAgent();
return /iPad|iPhone|iPod/.test(ua) && /Safari/.test(ua) && !/Chrome/.test(ua);
};
export const isPWA = () => {
const standaloneMode = window.matchMedia("(display-mode: standalone)").matches;
const iosPWA = window.navigator.standalone === true;
return standaloneMode || iosPWA;
};
3. User Experience Improvements
iOS Safari Browser (Non-PWA):
- Shows informational banner about PWA installation
- Displays notifications immediately below (no button click required)
- Provides clear installation instructions
iOS Safari PWA:
- Full push notification support
- Automatic permission flow after user interaction
- Badge support for notification counts
4. Automatic Subscription Cleanup
We implemented intelligent subscription management to handle failed push endpoints:
// Handle subscription cleanup for permanent failures
if (statusCode == 410 || statusCode == 404 || statusCode == 400) {
log.info("Removing invalid push subscription for user {} due to status {}",
un.getToUser(), statusCode);
clearUserPushSubscription(un.getToUser());
}
Status codes handled:
- 410 Gone - Subscription expired (common with FCM)
- 404 Not Found - Endpoint no longer valid
- 400 Bad Request - Malformed subscription
- 403 Forbidden - VAPID authentication issues (logged but not auto-deleted)
Debugging iOS Safari Push Notifications
Remote Debugging Setup
The key to debugging iOS Safari push notifications is using Safari’s remote debugging feature:
- Connect iOS device to Mac via USB
- Enable Web Inspector on iOS: Settings → Safari → Advanced → Web Inspector
- Open Safari on Mac → Develop menu → [Your Device] → [Your PWA]
- Access full console and network debugging tools
Essential Debugging Points
Frontend Debugging:
console.debug("PWA detection:", { standaloneMode, iosPWA, isPwaMode });
console.debug("Push subscription created:", sub);
console.debug("Subscription endpoint:", sub.endpoint);
Backend Debugging:
log.info("Push service configured with VAPID subject: {}", pushSubject);
log.warn("Push notification to {} failed with status {} and reason {}",
pushEndpoint, statusCode, reason);
Key things to monitor:
- PWA detection accuracy
- Push subscription creation success
- Endpoint registration with backend
- HTTP status codes from push services
- VAPID subject configuration
Common Pitfalls and Solutions
1. VAPID Subject Formatting
Problem: Spaces and brackets in mailto format
Solution: Use exact format mailto:admin@school.edu
2. PWA Installation Detection
Problem: iOS standalone detection not working
Solution: Check both CSS media query and navigator.standalone
3. Permission Timing
Problem: Requesting permissions too early Solution: Wait for user interaction and PWA installation
4. Subscription Endpoint Cleanup
Problem: Accumulating invalid endpoints causing errors Solution: Automatic cleanup based on HTTP status codes
Security Considerations
VAPID Authentication
- Keys are not tied to domains - can use any valid URL/email as subject
- No APNs certificates needed for iOS Web Push
- Subject serves as identifier for push service rate limiting
Privacy
- User consent required for all push notifications
- Subscription data encrypted using Web Push Protocol
- No personal data in push payloads - use notification IDs instead
Performance Optimizations
Efficient Error Handling
// Only process users with complete subscription data
if (StringUtils.isAnyBlank(pushEndpoint, pushUserKey, pushAuth)) {
log.debug("Skipping push notification due to missing subscription details");
return;
}
Subscription Lifecycle Management
- Automatic cleanup of invalid subscriptions
- Fingerprint-based deduplication to prevent multiple subscriptions per device
- User-based subscription lookup for efficient targeting
Documentation Improvements
We enhanced Sakai’s default configuration documentation:
# Generate the key and pub using openssl
# openssl ecparam -name prime256v1 -genkey -noout -out sakai/sakai_push.key
# openssl ec -in sakai/sakai_push.key -pubout -out sakai/sakai_push.key.pub
#
# DEFAULT: the servername
# IMPORTANT: Apple seems to want zero spaces or brackets
# portal.notifications.push.subject=mailto:somebody@sakai.edu
Results and Impact
Zero-Configuration Experience
With our improvements, new Sakai installations work out-of-the-box:
- Automatic VAPID subject using server name
- No manual configuration required for basic functionality
- Smart platform detection for optimal user experience
Cross-Platform Compatibility
- iOS Safari PWA: Full push notification support
- iOS Safari Browser: Graceful degradation with installation guidance
- Android/Desktop: Existing functionality maintained and enhanced
- Automatic cleanup: Self-maintaining subscription database
Enhanced Debugging
- Comprehensive logging for troubleshooting
- Status code handling for all major push services
- Clear error messages for configuration issues
Conclusion
Implementing cross-platform push notifications revealed the importance of understanding each platform’s unique requirements. While iOS Safari’s PWA requirement initially seemed like a limitation, it actually provides a more integrated and powerful notification experience for users who choose to install the PWA.
Key takeaways for other developers:
- Test extensively on actual devices - simulators don’t always reflect real behavior
- Use remote debugging tools - essential for iOS Safari development
- Implement comprehensive error handling - push services fail in various ways
- Provide clear user guidance - PWA installation isn’t intuitive for all users
- Monitor and clean up subscriptions - invalid endpoints accumulate over time
The result is a robust, self-maintaining push notification system that works seamlessly across all major platforms while providing clear guidance to users about the best experience available on their device.
For Sakai administrators, these improvements mean less configuration overhead and fewer support requests about push notifications. For users, it means a more reliable and intuitive notification experience regardless of their platform choice.
This implementation is available in Sakai’s trunk branch under issue SAK-51709, contributing to Sakai’s ongoing commitment to providing a modern, accessible learning experience across all devices and platforms.