Manos Chorianopoulos

fix problematic apiKey, webId checks

...@@ -1117,12 +1117,108 @@ After these changes, the framework should: ...@@ -1117,12 +1117,108 @@ After these changes, the framework should:
1117 4. **Network Requests**: Check that all API calls work with simplified authentication 1117 4. **Network Requests**: Check that all API calls work with simplified authentication
1118 5. **Log Verification**: Ensure no more excessive credential warnings 1118 5. **Log Verification**: Ensure no more excessive credential warnings
1119 1119
1120 +### **🔧 Additional Safety Fixes - June 27, 2025 (Session 2)**
1121 +
1122 +After the initial legacy credential removal, a comprehensive search revealed **2 additional problematic checks** that could still cause issues:
1123 +
1124 +#### **Issue #5: NetworkService Signature Generation (CRITICAL)**
1125 +**File**: `SwiftWarplyFramework/SwiftWarplyFramework/Network/NetworkService.swift`
1126 +**Problem**: Conditional signature generation that skipped the `loyalty-signature` header when API key was empty
1127 +**Impact**: ❌ **CRITICAL** - Missing signature header could cause API authentication failures
1128 +
1129 +**Before (Problematic)**:
1130 +```swift
1131 +// Generate loyalty signature (apiKey + timestamp SHA256)
1132 +let apiKey = getApiKey()
1133 +if !apiKey.isEmpty {
1134 + let signatureString = "\(apiKey)\(timestamp)"
1135 + let signature = signatureString.sha256()
1136 + request.setValue(signature, forHTTPHeaderField: "loyalty-signature")
1137 +}
1138 +```
1139 +
1140 +**After (Safe)**:
1141 +```swift
1142 +// Generate loyalty signature (apiKey + timestamp SHA256)
1143 +// Always generate signature, even with empty API key (server expects this header)
1144 +let apiKey = getApiKey()
1145 +let signatureString = "\(apiKey)\(timestamp)"
1146 +let signature = signatureString.sha256()
1147 +request.setValue(signature, forHTTPHeaderField: "loyalty-signature")
1148 +```
1149 +
1150 +**Result**: ✅ Signature header always sent, preventing authentication failures
1151 +
1152 +---
1153 +
1154 +#### **Issue #6: WarplySDK Registration Check (CLEANUP)**
1155 +**File**: `SwiftWarplyFramework/SwiftWarplyFramework/Core/WarplySDK.swift`
1156 +**Problem**: Dead code that checked for non-empty legacy credentials (would never execute)
1157 +**Impact**: 🟡 **MEDIUM** - Unnecessary code that could confuse developers
1158 +
1159 +**Before (Dead Code)**:
1160 +```swift
1161 +// Check if we already have API key and web ID
1162 +let existingApiKey = UserDefaults.standard.string(forKey: "NBAPIKeyUD")
1163 +let existingWebId = UserDefaults.standard.string(forKey: "NBWebIDUD")
1164 +
1165 +if let apiKey = existingApiKey, !apiKey.isEmpty,
1166 + let webId = existingWebId, !webId.isEmpty {
1167 + print("✅ [WarplySDK] Device already registered - API Key: \(apiKey.prefix(8))..., Web ID: \(webId)")
1168 + return
1169 +}
1170 +```
1171 +
1172 +**After (Clean)**:
1173 +```swift
1174 +// Legacy credentials are deprecated - always proceed with registration if needed
1175 +// (The server will handle duplicate registrations gracefully)
1176 +```
1177 +
1178 +**Result**: ✅ Cleaner code, no more dead conditional logic
1179 +
1180 +---
1181 +
1182 +### **📊 Complete Fix Summary**
1183 +
1184 +| Session | File | Change Type | Impact | Description |
1185 +|---------|------|-------------|---------|-------------|
1186 +| **1** | `TokenRefreshManager.swift` | **Critical Fix** | 🔴 **HIGH** | Removed blocking guard for client credentials |
1187 +| **1** | `WarplySDK.swift` | **Critical Fix** | 🔴 **HIGH** | Removed registration validation for legacy credentials |
1188 +| **1** | `NetworkService.swift` | **Optimization** | 🟡 **MEDIUM** | Simplified credential methods, removed storage |
1189 +| **1** | `TokenModel.swift` | **Enhancement** | 🟢 **LOW** | Default empty strings for legacy credentials |
1190 +| **2** | `NetworkService.swift` | **Critical Fix** | 🔴 **HIGH** | Always generate signature header |
1191 +| **2** | `WarplySDK.swift` | **Cleanup** | 🟢 **LOW** | Removed dead registration check code |
1192 +
1193 +### **🎯 Final Expected Results**
1194 +
1195 +After all fixes, the framework should:
1196 +
1197 +1.**No more WarplyError code 5** during device registration
1198 +2.**No more credential warning logs** during network requests
1199 +3.**Token refresh works** without client_id/client_secret requirements
1200 +4.**Registration succeeds** with "deprecated" API responses
1201 +5.**Signature header always sent** - no authentication failures
1202 +6.**Clean codebase** - no dead conditional logic
1203 +7.**All existing functionality preserved** - zero breaking changes
1204 +
1205 +### **🔍 Comprehensive Testing Recommendations**
1206 +
1207 +1. **Registration Flow**: Test device registration with "deprecated" responses
1208 +2. **Token Refresh**: Verify token refresh works without legacy credentials
1209 +3. **Campaign Loading**: Confirm campaigns load successfully (should fix getCampaigns ERROR: -1)
1210 +4. **Network Requests**: Check that all API calls work with simplified authentication
1211 +5. **Signature Verification**: Ensure loyalty-signature header is always present
1212 +6. **Log Verification**: Ensure no more excessive credential warnings
1213 +
1120 ### **📝 Migration Notes** 1214 ### **📝 Migration Notes**
1121 1215
1122 - **Backward Compatibility**: ✅ Maintained - no breaking changes 1216 - **Backward Compatibility**: ✅ Maintained - no breaking changes
1123 - **API Compatibility**: ✅ Preserved - all public methods unchanged 1217 - **API Compatibility**: ✅ Preserved - all public methods unchanged
1124 - **Authentication Method**: Updated from legacy credentials to merchant ID + access/refresh tokens 1218 - **Authentication Method**: Updated from legacy credentials to merchant ID + access/refresh tokens
1125 - **Error Handling**: Improved - no more false failures for missing legacy credentials 1219 - **Error Handling**: Improved - no more false failures for missing legacy credentials
1220 +- **Security**: Enhanced - signature header always sent for proper authentication
1221 +- **Code Quality**: Improved - removed dead code and unnecessary conditional logic
1126 1222
1127 --- 1223 ---
1128 1224
......
...@@ -437,15 +437,8 @@ public final class WarplySDK { ...@@ -437,15 +437,8 @@ public final class WarplySDK {
437 437
438 /// Perform device registration during initialization 438 /// Perform device registration during initialization
439 private func performDeviceRegistration() async throws { 439 private func performDeviceRegistration() async throws {
440 - // Check if we already have API key and web ID 440 + // Legacy credentials are deprecated - always proceed with registration if needed
441 - let existingApiKey = UserDefaults.standard.string(forKey: "NBAPIKeyUD") 441 + // (The server will handle duplicate registrations gracefully)
442 - let existingWebId = UserDefaults.standard.string(forKey: "NBWebIDUD")
443 -
444 - if let apiKey = existingApiKey, !apiKey.isEmpty,
445 - let webId = existingWebId, !webId.isEmpty {
446 - print("✅ [WarplySDK] Device already registered - API Key: \(apiKey.prefix(8))..., Web ID: \(webId)")
447 - return
448 - }
449 442
450 print("🔄 [WarplySDK] Performing automatic device registration...") 443 print("🔄 [WarplySDK] Performing automatic device registration...")
451 444
......
...@@ -308,12 +308,11 @@ public final class NetworkService: NetworkServiceProtocol { ...@@ -308,12 +308,11 @@ public final class NetworkService: NetworkServiceProtocol {
308 request.setValue("\(timestamp)", forHTTPHeaderField: "loyalty-date") 308 request.setValue("\(timestamp)", forHTTPHeaderField: "loyalty-date")
309 309
310 // Generate loyalty signature (apiKey + timestamp SHA256) 310 // Generate loyalty signature (apiKey + timestamp SHA256)
311 + // Always generate signature, even with empty API key (server expects this header)
311 let apiKey = getApiKey() 312 let apiKey = getApiKey()
312 - if !apiKey.isEmpty {
313 let signatureString = "\(apiKey)\(timestamp)" 313 let signatureString = "\(apiKey)\(timestamp)"
314 let signature = signatureString.sha256() 314 let signature = signatureString.sha256()
315 request.setValue(signature, forHTTPHeaderField: "loyalty-signature") 315 request.setValue(signature, forHTTPHeaderField: "loyalty-signature")
316 - }
317 316
318 // Standard HTTP headers (always sent) 317 // Standard HTTP headers (always sent)
319 request.setValue("gzip", forHTTPHeaderField: "Accept-Encoding") 318 request.setValue("gzip", forHTTPHeaderField: "Accept-Encoding")
......