@superfan-app/spotify-auth 0.1.29 → 0.1.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -233,33 +233,33 @@ final class SpotifyAuthAuth: NSObject, SPTSessionManagerDelegate {
233
233
  }
234
234
 
235
235
  private func securelyStoreToken(_ session: SPTSession) {
236
- // Only pass token to JS, store sensitive data securely
236
+ // Pass token to JS and securely store refresh token
237
237
  module?.onAccessTokenObtained(session.accessToken)
238
238
 
239
- // Store refresh token in keychain if available
240
- if let refreshToken = session.refreshToken {
239
+ // Since refreshToken is now a non-optional String, we simply check for an empty value.
240
+ let refreshToken = session.refreshToken
241
+ if !refreshToken.isEmpty {
241
242
  do {
242
243
  let keychainKey = try getKeychainKey()
243
- try KeychainAccess.store(
244
- key: keychainKey,
245
- data: refreshToken.data(using: .utf8)!,
246
- accessibility: .afterFirstUnlock
247
- )
244
+ // Create a Keychain instance (using bundle identifier as the service)
245
+ let keychain = Keychain(service: Bundle.main.bundleIdentifier ?? "com.superfan.app")
246
+ .accessibility(.afterFirstUnlock)
247
+ try keychain.set(refreshToken, key: keychainKey)
248
248
  } catch {
249
- print("Failed to store refresh token securely")
249
+ print("Failed to store refresh token securely: \(error)")
250
250
  }
251
251
  }
252
252
  }
253
253
 
254
254
  private func cleanupPreviousSession() {
255
- // Clear any sensitive data from previous session
256
255
  refreshTimer?.invalidate()
257
256
 
258
257
  do {
259
258
  let keychainKey = try getKeychainKey()
260
- try KeychainAccess.delete(key: keychainKey)
259
+ let keychain = Keychain(service: Bundle.main.bundleIdentifier ?? "com.superfan.app")
260
+ try keychain.remove(keychainKey)
261
261
  } catch {
262
- print("Failed to clear previous refresh token")
262
+ print("Failed to clear previous refresh token: \(error)")
263
263
  }
264
264
 
265
265
  // Clear in-memory session data
@@ -287,8 +287,9 @@ final class SpotifyAuthAuth: NSObject, SPTSessionManagerDelegate {
287
287
  let scopes = try self.requestedScopes
288
288
  isAuthenticating = true
289
289
 
290
- let options: SPTConfiguration.AuthorizationOptions = showDialog ? .clientOnly : .default
291
- sessionManager.initiateSession(with: scopes, options: options)
290
+ // Updated: Use SPTSessionManagerOptions (an OptionSet) and pass nil for campaign.
291
+ let options: SPTSessionManagerOptions = showDialog ? .clientOnly : []
292
+ sessionManager.initiateSession(with: scopes, options: options, campaign: nil)
292
293
  } catch {
293
294
  isAuthenticating = false
294
295
  handleError(error, context: "authentication")
@@ -304,7 +305,8 @@ final class SpotifyAuthAuth: NSObject, SPTSessionManagerDelegate {
304
305
  }
305
306
  let scopes = try self.requestedScopes
306
307
  isAuthenticating = true
307
- sessionManager.initiateSession(with: scopes, options: .default)
308
+ // Updated: Use SPTSessionManagerOptions and pass nil for campaign.
309
+ sessionManager.initiateSession(with: scopes, options: [], campaign: nil)
308
310
  } catch {
309
311
  isAuthenticating = false
310
312
  handleError(error, context: "authentication_retry")
@@ -382,19 +384,10 @@ final class SpotifyAuthAuth: NSObject, SPTSessionManagerDelegate {
382
384
  private func handleError(_ error: Error, context: String) {
383
385
  let spotifyError: SpotifyAuthError
384
386
 
385
- if let error = error as? SpotifyAuthError {
386
- spotifyError = error
387
- } else if let sptError = error as? SPTError {
388
- switch sptError {
389
- case .configurationError:
390
- spotifyError = .invalidConfiguration("Invalid Spotify configuration")
391
- case .authenticationError:
392
- spotifyError = .authenticationFailed("Please try authenticating again")
393
- case .loggedOut:
394
- spotifyError = .sessionError("User logged out")
395
- default:
396
- spotifyError = .authenticationFailed(sptError.localizedDescription)
397
- }
387
+ // Instead of switching on SPTError cases (which are no longer available),
388
+ // we simply wrap the error’s description.
389
+ if error is SPTError {
390
+ spotifyError = .authenticationFailed(error.localizedDescription)
398
391
  } else {
399
392
  spotifyError = .authenticationFailed(error.localizedDescription)
400
393
  }
@@ -459,4 +452,4 @@ final class SpotifyAuthAuth: NSObject, SPTSessionManagerDelegate {
459
452
  deinit {
460
453
  cleanupPreviousSession()
461
454
  }
462
- }
455
+ }
@@ -17,7 +17,8 @@ public class SpotifyAuthDelegate: ExpoAppDelegateSubscriber, SPTSessionManagerDe
17
17
  }
18
18
 
19
19
  public func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
20
- spotifyAuth.sessionManager.application(app, open: url, options: options)
20
+ // Use optional chaining to avoid calling on a nil session manager.
21
+ spotifyAuth.sessionManager?.application(app, open: url, options: options)
21
22
  return true
22
23
  }
23
- }
24
+ }
@@ -33,9 +33,6 @@ struct AuthorizeConfig: Record {
33
33
  public class SpotifyAuthModule: Module {
34
34
  let spotifyAuth = SpotifyAuthAuth.shared
35
35
 
36
- // Each module class must implement the definition function. The definition consists of components
37
- // that describes the module's functionality and behavior.
38
- // See https://docs.expo.dev/modules/module-api for more details about available components.
39
36
  public func definition() -> ModuleDefinition {
40
37
  Name("SpotifyAuth")
41
38
 
@@ -51,12 +48,12 @@ public class SpotifyAuthModule: Module {
51
48
  // Defines event names that the module can send to JavaScript.
52
49
  Events(SPOTIFY_AUTHORIZATION_EVENT_NAME)
53
50
 
54
- // This will be called when JS starts observing the event.
51
+ // Called when JS starts observing the event.
55
52
  OnStartObserving {
56
53
  secureLog("Started observing events")
57
54
  }
58
55
 
59
- // This will be called when JS stops observing the event.
56
+ // Called when JS stops observing the event.
60
57
  OnStopObserving {
61
58
  secureLog("Stopped observing events")
62
59
  }
@@ -64,7 +61,7 @@ public class SpotifyAuthModule: Module {
64
61
  AsyncFunction("authorize") { (config: AuthorizeConfig, promise: Promise) in
65
62
  secureLog("Authorization requested")
66
63
 
67
- // Sanitize and validate redirect URL
64
+ // Sanitize and validate redirect URL.
68
65
  guard let url = URL(string: config.redirectUrl),
69
66
  url.scheme != nil,
70
67
  url.host != nil else {
@@ -72,22 +69,21 @@ public class SpotifyAuthModule: Module {
72
69
  return
73
70
  }
74
71
 
75
- let configuration = SPTConfiguration(clientID: config.clientId, redirectURL: url)
72
+ // Create a configuration (this example does not use the variable afterwards).
73
+ let _ = SPTConfiguration(clientID: config.clientId, redirectURL: url)
76
74
 
77
75
  do {
78
76
  try spotifyAuth.initAuth(showDialog: config.showDialog)
79
77
  promise.resolve()
80
78
  } catch {
81
- // Sanitize error message
79
+ // Sanitize error message.
82
80
  let sanitizedError = sanitizeErrorMessage(error.localizedDescription)
83
81
  promise.reject(SpotifyAuthError.authenticationFailed(sanitizedError))
84
82
  }
85
83
  }
86
84
 
87
- // Enables the module to be used as a native view. Definition components that are accepted as part of the
88
- // view definition: Prop, Events.
85
+ // Enables the module to be used as a native view.
89
86
  View(SpotifyAuthView.self) {
90
- // Defines a setter for the `name` prop.
91
87
  Prop("name") { (_: SpotifyAuthView, prop: String) in
92
88
  secureLog("View prop updated: \(prop)")
93
89
  }
@@ -95,7 +91,7 @@ public class SpotifyAuthModule: Module {
95
91
  }
96
92
 
97
93
  private func sanitizeErrorMessage(_ message: String) -> String {
98
- // Remove any potential sensitive data from error messages
94
+ // Remove potential sensitive data from error messages.
99
95
  let sensitivePatterns = [
100
96
  "(?i)client[_-]?id",
101
97
  "(?i)token",
@@ -124,7 +120,7 @@ public class SpotifyAuthModule: Module {
124
120
  let eventData: [String: Any] = [
125
121
  "success": true,
126
122
  "token": token,
127
- "error": nil
123
+ "error": NSNull() // Use NSNull() instead of nil.
128
124
  ]
129
125
  sendEvent(SPOTIFY_AUTHORIZATION_EVENT_NAME, eventData)
130
126
  }
@@ -134,8 +130,8 @@ public class SpotifyAuthModule: Module {
134
130
  secureLog("User signed out")
135
131
  let eventData: [String: Any] = [
136
132
  "success": true,
137
- "token": nil,
138
- "error": nil
133
+ "token": NSNull(), // Use NSNull() instead of nil.
134
+ "error": NSNull() // Use NSNull() instead of nil.
139
135
  ]
140
136
  sendEvent(SPOTIFY_AUTHORIZATION_EVENT_NAME, eventData)
141
137
  }
@@ -146,9 +142,9 @@ public class SpotifyAuthModule: Module {
146
142
  secureLog("Authorization error: \(sanitizedError)")
147
143
  let eventData: [String: Any] = [
148
144
  "success": false,
149
- "token": nil,
145
+ "token": NSNull(), // Use NSNull() instead of nil.
150
146
  "error": sanitizedError
151
147
  ]
152
148
  sendEvent(SPOTIFY_AUTHORIZATION_EVENT_NAME, eventData)
153
149
  }
154
- }
150
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superfan-app/spotify-auth",
3
- "version": "0.1.29",
3
+ "version": "0.1.30",
4
4
  "description": "Spotify OAuth module for Expo",
5
5
  "main": "src/index.ts",
6
6
  "types": "build/index.d.ts",