@pyrocancode/react-native-vk-auth 0.4.1 → 1.0.0
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.
- package/android/build.gradle +7 -11
- package/android/src/main/java/com/vkauth/VkAuthModule.kt +18 -16
- package/android/src/main/java/com/vkauth/VkAuthPackage.kt +10 -5
- package/android/src/main/java/com/vkauth/vkid/AuthDelegate.kt +92 -84
- package/android/src/main/java/com/vkauth/vkid/InitDelegate.kt +8 -2
- package/android/src/main/java/com/vkauth/vkid/VkAuthPayload.kt +61 -0
- package/android/src/main/java/com/vkauth/vkid/VkAuthServiceHolder.kt +8 -0
- package/android/src/main/java/com/vkauth/vkid/onetapbutton/OneTapButtonManager.kt +32 -129
- package/ios/Event.swift +3 -19
- package/ios/RCTDomain.swift +17 -13
- package/ios/VkAuth.swift +113 -97
- package/package.json +2 -2
- package/react-native-vk-auth.podspec +17 -10
- package/src/index.tsx +99 -77
- package/android/src/main/java/com/vkauth/vkid/JSSilentTokenExchanger.kt +0 -33
- package/android/src/main/java/com/vkauth/vkid/SuperAppKitInitUtils.kt +0 -75
- package/android/src/main/java/com/vkauth/vkid/dto/AcessToken.kt +0 -19
- package/android/src/main/java/com/vkauth/vkid/dto/DtoExt.kt +0 -24
- package/android/src/main/java/com/vkauth/vkid/dto/SilentAuthInfo.kt +0 -22
- package/android/src/main/java/com/vkauth/vkid/dto/Token.kt +0 -15
- package/android/src/main/java/com/vkauth/vkid/dto/UserSession.kt +0 -28
- package/android/src/main/java/com/vkauth/vkid/jstutils/JsCbSender.kt +0 -16
- package/android/src/main/java/com/vkauth/vkid/jstutils/JsOutputParam.kt +0 -7
package/ios/Event.swift
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
import OSLog
|
|
3
|
-
|
|
4
|
-
@_implementationOnly import VKSDK
|
|
3
|
+
import VKID
|
|
5
4
|
|
|
6
5
|
extension VkAuth {
|
|
7
6
|
func send(event: Event) {
|
|
@@ -25,17 +24,11 @@ struct Event {
|
|
|
25
24
|
self.event = event
|
|
26
25
|
}
|
|
27
26
|
|
|
28
|
-
// MARK: - Accessors
|
|
29
|
-
|
|
30
27
|
static let onLogout = Self(OnLogout())
|
|
31
28
|
|
|
32
|
-
static func onAuth(userSession:
|
|
29
|
+
static func onAuth(userSession: UserSession) -> Self {
|
|
33
30
|
.init(OnAuth(userSession: userSession))
|
|
34
31
|
}
|
|
35
|
-
|
|
36
|
-
static func onSilentDataReceive(silentToken: VKID.SilentToken) -> Self {
|
|
37
|
-
.init(OnSilentDataReceive(silentToken: silentToken))
|
|
38
|
-
}
|
|
39
32
|
}
|
|
40
33
|
|
|
41
34
|
extension Event: CustomStringConvertible {
|
|
@@ -54,17 +47,8 @@ extension Event {
|
|
|
54
47
|
let name = "onAuth"
|
|
55
48
|
let body: Any
|
|
56
49
|
|
|
57
|
-
init(userSession:
|
|
50
|
+
init(userSession: UserSession) {
|
|
58
51
|
self.body = userSession.dictionary
|
|
59
52
|
}
|
|
60
53
|
}
|
|
61
|
-
|
|
62
|
-
private struct OnSilentDataReceive: RCTEvent {
|
|
63
|
-
let name = "onSilentDataReceive"
|
|
64
|
-
let body: Any
|
|
65
|
-
|
|
66
|
-
init(silentToken: VKID.SilentToken) {
|
|
67
|
-
self.body = ["token": ["value": silentToken.token.value], "uuid": silentToken.uuid]
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
54
|
}
|
package/ios/RCTDomain.swift
CHANGED
|
@@ -1,26 +1,30 @@
|
|
|
1
1
|
import Foundation
|
|
2
|
-
|
|
3
|
-
@_implementationOnly import VKSDK
|
|
2
|
+
import VKID
|
|
4
3
|
|
|
5
4
|
protocol RCTDomain {
|
|
6
5
|
var dictionary: [String: Any?] { get }
|
|
7
6
|
}
|
|
8
7
|
|
|
9
|
-
extension
|
|
10
|
-
|
|
11
|
-
var dictionary: [String : Any?] {
|
|
8
|
+
extension User: RCTDomain {
|
|
9
|
+
var dictionary: [String: Any?] {
|
|
12
10
|
[
|
|
13
|
-
"userID": ["value": self.id.
|
|
14
|
-
"firstName": self.
|
|
15
|
-
"lastName": self.
|
|
16
|
-
"phone": self.
|
|
17
|
-
"photo200": self.
|
|
11
|
+
"userID": ["value": String(self.id.value)],
|
|
12
|
+
"firstName": self.firstName,
|
|
13
|
+
"lastName": self.lastName,
|
|
14
|
+
"phone": self.phone,
|
|
15
|
+
"photo200": self.avatarURL?.absoluteString,
|
|
16
|
+
"email": self.email,
|
|
17
|
+
"userHash": nil,
|
|
18
18
|
]
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
extension
|
|
23
|
-
var dictionary: [String
|
|
24
|
-
[
|
|
22
|
+
extension UserSession {
|
|
23
|
+
var dictionary: [String: Any?] {
|
|
24
|
+
[
|
|
25
|
+
"type": "authorized",
|
|
26
|
+
"userId": String(self.userId.value),
|
|
27
|
+
"accessToken": self.accessToken.value,
|
|
28
|
+
]
|
|
25
29
|
}
|
|
26
30
|
}
|
package/ios/VkAuth.swift
CHANGED
|
@@ -1,22 +1,40 @@
|
|
|
1
1
|
import UIKit
|
|
2
2
|
import OSLog
|
|
3
|
+
import React
|
|
4
|
+
import VKID
|
|
5
|
+
import VKIDCore
|
|
6
|
+
|
|
7
|
+
// MARK: - Общие хелперы (VK ID SDK 2.x, OAuth 2.1)
|
|
8
|
+
|
|
9
|
+
fileprivate func vkAuthTopViewController() -> UIViewController? {
|
|
10
|
+
let keyWindow: UIWindow?
|
|
11
|
+
if #available(iOS 13.0, *) {
|
|
12
|
+
keyWindow = UIApplication.shared.connectedScenes
|
|
13
|
+
.compactMap { $0 as? UIWindowScene }
|
|
14
|
+
.flatMap(\.windows)
|
|
15
|
+
.first { $0.isKeyWindow }
|
|
16
|
+
} else {
|
|
17
|
+
keyWindow = UIApplication.shared.keyWindow
|
|
18
|
+
}
|
|
19
|
+
guard var top = keyWindow?.rootViewController else { return nil }
|
|
20
|
+
while let presented = top.presentedViewController {
|
|
21
|
+
top = presented
|
|
22
|
+
}
|
|
23
|
+
return top
|
|
24
|
+
}
|
|
3
25
|
|
|
4
|
-
|
|
26
|
+
/// Публичный клиент + PKCE внутри SDK. Для обмена кода на бэкенде позже можно сменить на `confidentialClientFlow`.
|
|
27
|
+
fileprivate func vkAuthMakeConfiguration() -> AuthConfiguration {
|
|
28
|
+
AuthConfiguration(
|
|
29
|
+
flow: .publicClientFlow(),
|
|
30
|
+
scope: Scope([])
|
|
31
|
+
)
|
|
32
|
+
}
|
|
5
33
|
|
|
34
|
+
/// React Native мост для VK ID SDK. См. https://id.vk.com/about/business/go/docs/ru/vkid/latest/vk-id/connection/migration/ios/migration-ios
|
|
6
35
|
@objc(VkAuth)
|
|
7
36
|
final class VkAuth: RCTEventEmitter {
|
|
8
|
-
|
|
9
|
-
fileprivate static var _sharedSuperappKit: VkAuth?
|
|
10
|
-
|
|
11
|
-
fileprivate static var sharedSDK: VKSDK.VK.Type2<App, VKID> {
|
|
12
|
-
guard let _shared = Self._sharedSDK else {
|
|
13
|
-
fatalError("VKSDK is not initialized. Call initialize(_:vkid:) method before using VkAuth.")
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
return _shared
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
private var activeAuthCompletion: ((Result<VKSDK.VKID.AccessToken, Error>) -> Void)?
|
|
37
|
+
fileprivate static weak var _sharedEmitter: VkAuth?
|
|
20
38
|
|
|
21
39
|
@objc(initialize:vkid:)
|
|
22
40
|
func initialize(_ app: NSDictionary, vkid: NSDictionary) {
|
|
@@ -30,50 +48,50 @@ final class VkAuth: RCTEventEmitter {
|
|
|
30
48
|
}
|
|
31
49
|
|
|
32
50
|
do {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
51
|
+
try VKID.shared.set(
|
|
52
|
+
config: Configuration(
|
|
53
|
+
appCredentials: AppCredentials(
|
|
54
|
+
clientId: clientId,
|
|
55
|
+
clientSecret: clientSecret
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
)
|
|
59
|
+
VkAuth._sharedEmitter = self
|
|
60
|
+
VKID.shared.add(observer: self)
|
|
38
61
|
} catch {
|
|
39
|
-
os_log("
|
|
62
|
+
os_log("VKID initialization failed: %{public}@", type: .error, error.localizedDescription)
|
|
40
63
|
}
|
|
41
64
|
}
|
|
42
65
|
|
|
43
66
|
@objc(openURL:)
|
|
44
|
-
func openURL(_
|
|
45
|
-
guard let url = URL(string:
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
try? Self.sharedSDK.open(url: url)
|
|
67
|
+
func openURL(_ urlString: String) {
|
|
68
|
+
guard let url = URL(string: urlString) else { return }
|
|
69
|
+
_ = VKID.shared.open(url: url)
|
|
50
70
|
}
|
|
51
71
|
|
|
52
|
-
// MARK: - Auth
|
|
53
|
-
|
|
54
72
|
@objc func startAuth() {
|
|
55
|
-
let
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
73
|
+
guard let presenter = vkAuthTopViewController() else {
|
|
74
|
+
os_log("No presenter for VKID authorize", type: .error)
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
VKID.shared.authorize(
|
|
78
|
+
with: vkAuthMakeConfiguration(),
|
|
79
|
+
using: .uiViewController(presenter)
|
|
80
|
+
) { _ in }
|
|
60
81
|
}
|
|
61
82
|
|
|
62
83
|
@objc func closeAuth() {
|
|
63
|
-
|
|
64
|
-
os_log("Authorization
|
|
84
|
+
vkAuthTopViewController()?.dismiss(animated: true)
|
|
85
|
+
os_log("Authorization UI dismissed", type: .info)
|
|
65
86
|
}
|
|
66
87
|
|
|
67
88
|
@objc func logout() {
|
|
68
|
-
guard let
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
self?.send(event: .onLogout)
|
|
89
|
+
guard let session = VKID.shared.authorizedSessions.first else { return }
|
|
90
|
+
session.logout { [weak self] result in
|
|
91
|
+
if case .success = result {
|
|
92
|
+
self?.send(event: .onLogout)
|
|
93
|
+
}
|
|
74
94
|
}
|
|
75
|
-
|
|
76
|
-
os_log("Logout user session", type: .info, "\(userSession)")
|
|
77
95
|
}
|
|
78
96
|
|
|
79
97
|
@objc(getUserSessions:rejecter:)
|
|
@@ -81,7 +99,7 @@ final class VkAuth: RCTEventEmitter {
|
|
|
81
99
|
resolver resolve: RCTPromiseResolveBlock,
|
|
82
100
|
rejecter reject: RCTPromiseRejectBlock
|
|
83
101
|
) {
|
|
84
|
-
resolve(
|
|
102
|
+
resolve(VKID.shared.authorizedSessions.map(\.dictionary))
|
|
85
103
|
}
|
|
86
104
|
|
|
87
105
|
@objc(getUserProfile:rejecter:)
|
|
@@ -89,92 +107,90 @@ final class VkAuth: RCTEventEmitter {
|
|
|
89
107
|
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
90
108
|
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
91
109
|
) {
|
|
92
|
-
guard let
|
|
93
|
-
reject(
|
|
110
|
+
guard let session = VKID.shared.authorizedSessions.first else {
|
|
111
|
+
reject("no_session", "No authorized VK ID session", nil)
|
|
94
112
|
return
|
|
95
113
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
let
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
114
|
+
session.fetchUser { result in
|
|
115
|
+
switch result {
|
|
116
|
+
case .success:
|
|
117
|
+
if let user = session.user {
|
|
118
|
+
resolve(user.dictionary)
|
|
119
|
+
} else {
|
|
120
|
+
resolve(["userID": ["value": String(session.userId.value)]])
|
|
121
|
+
}
|
|
122
|
+
case .failure(let error):
|
|
123
|
+
reject("profile_failed", error.localizedDescription, error)
|
|
103
124
|
}
|
|
104
125
|
}
|
|
105
126
|
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
extension VkAuth: TokenExchanging {
|
|
109
|
-
func exchange(silentToken: VKSDK.VKID.SilentToken, completion: @escaping (Result<VKSDK.VKID.AccessToken, Error>) -> Void) {
|
|
110
|
-
self.activeAuthCompletion = completion
|
|
111
|
-
self.send(event: .onSilentDataReceive(silentToken: silentToken))
|
|
112
|
-
}
|
|
113
127
|
|
|
114
128
|
@objc(accessTokenChangedSuccess:userId:)
|
|
115
129
|
func accessTokenChangedSuccess(_ token: String, userId: NSNumber) {
|
|
116
|
-
|
|
117
|
-
self.activeAuthCompletion?(.success(accessToken))
|
|
118
|
-
self.activeAuthCompletion = nil
|
|
119
|
-
|
|
120
|
-
os_log("Token exchange succeeded", type: .info)
|
|
130
|
+
os_log("accessTokenChangedSuccess ignored on VK ID iOS (no silent exchange)", type: .info)
|
|
121
131
|
}
|
|
122
132
|
|
|
123
133
|
@objc(accessTokenChangedFailed:)
|
|
124
134
|
func accessTokenChangedFailed(_ error: NSDictionary) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
self.activeAuthCompletion = nil
|
|
135
|
+
os_log("accessTokenChangedFailed ignored on VK ID iOS", type: .info)
|
|
136
|
+
}
|
|
128
137
|
|
|
129
|
-
|
|
138
|
+
@objc(supportedEvents)
|
|
139
|
+
override func supportedEvents() -> [String]! {
|
|
140
|
+
["onLogout", "onAuth"]
|
|
130
141
|
}
|
|
131
142
|
}
|
|
132
143
|
|
|
133
|
-
extension VkAuth:
|
|
134
|
-
func vkid(_ vkid:
|
|
144
|
+
extension VkAuth: VKIDObserver {
|
|
145
|
+
func vkid(_ vkid: VKID, didCompleteAuthWith result: AuthResult, in oAuth: OAuthProvider) {
|
|
135
146
|
do {
|
|
136
|
-
|
|
147
|
+
let session = try result.get()
|
|
148
|
+
send(event: .onAuth(userSession: session))
|
|
149
|
+
} catch AuthError.cancelled {
|
|
150
|
+
os_log("VKID auth cancelled", type: .info)
|
|
137
151
|
} catch {
|
|
138
|
-
os_log("
|
|
152
|
+
os_log("VKID auth failed: %{public}@", type: .error, error.localizedDescription)
|
|
139
153
|
}
|
|
140
154
|
}
|
|
155
|
+
|
|
156
|
+
func vkid(_ vkid: VKID, didLogoutFrom session: UserSession, with result: LogoutResult) {
|
|
157
|
+
if case .success = result {
|
|
158
|
+
send(event: .onLogout)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
func vkid(_ vkid: VKID, didStartAuthUsing oAuth: OAuthProvider) {}
|
|
163
|
+
|
|
164
|
+
func vkid(_ vkid: VKID, didUpdateUserIn session: UserSession, with result: UserFetchingResult) {}
|
|
165
|
+
|
|
166
|
+
func vkid(_ vkid: VKID, didRefreshAccessTokenIn session: UserSession, with result: TokenRefreshingResult) {}
|
|
141
167
|
}
|
|
142
168
|
|
|
143
169
|
@objc(RTCVkOneTapButton)
|
|
144
170
|
final class OneTapButtonManager: RCTViewManager {
|
|
145
171
|
override func view() -> UIView! {
|
|
146
|
-
guard
|
|
147
|
-
|
|
172
|
+
guard VkAuth._sharedEmitter != nil else {
|
|
173
|
+
os_log("VkAuth not initialized before OneTap", type: .fault)
|
|
148
174
|
return UIView()
|
|
149
175
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
authPresenter = .uiViewController(root)
|
|
176
|
+
guard let root = vkAuthTopViewController() else {
|
|
177
|
+
return UIView()
|
|
153
178
|
}
|
|
154
179
|
|
|
155
|
-
let
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
)
|
|
180
|
+
let button = OneTapButton(
|
|
181
|
+
layout: .regular(
|
|
182
|
+
height: .medium(.h44),
|
|
183
|
+
cornerRadius: 8
|
|
184
|
+
),
|
|
185
|
+
presenter: .uiViewController(root),
|
|
186
|
+
authConfiguration: vkAuthMakeConfiguration(),
|
|
187
|
+
onCompleteAuth: nil
|
|
164
188
|
)
|
|
165
189
|
|
|
166
|
-
guard let
|
|
167
|
-
|
|
190
|
+
guard let view = try? VKID.shared.ui(for: button).uiView() else {
|
|
191
|
+
os_log("OneTapButton uiView failed", type: .error)
|
|
168
192
|
return UIView()
|
|
169
193
|
}
|
|
170
|
-
|
|
171
|
-
return buttonView
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
extension VkAuth {
|
|
176
|
-
@objc(supportedEvents)
|
|
177
|
-
override func supportedEvents() -> [String] {
|
|
178
|
-
["onLogout", "onAuth", "onSilentDataReceive"]
|
|
194
|
+
return view
|
|
179
195
|
}
|
|
180
196
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyrocancode/react-native-vk-auth",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Тонкая обёртка над VK ID SDK для React Native: OAuth 2.1, нативные модули iOS и Android.",
|
|
5
5
|
"main": "src/index.tsx",
|
|
6
6
|
"module": "src/index.tsx",
|
|
7
7
|
"types": "src/index.tsx",
|
|
@@ -10,26 +10,33 @@ Pod::Spec.new do |s|
|
|
|
10
10
|
s.homepage = package["homepage"]
|
|
11
11
|
s.license = package["license"]
|
|
12
12
|
s.authors = package["author"]
|
|
13
|
-
s.platforms = { :ios => "
|
|
13
|
+
s.platforms = { :ios => "15.1" }
|
|
14
14
|
s.source = { :git => "https://github.com/pyrocancode/react-native-vk-auth.git", :tag => "#{s.version}" }
|
|
15
15
|
|
|
16
16
|
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
s.dependency "
|
|
18
|
+
# VK ID SDK (OAuth 2.1). См. https://id.vk.com/about/business/go/docs/ru/vkid/latest/vk-id/connection/migration/ios/migration-ios
|
|
19
|
+
s.dependency "VKID", "2.9.2"
|
|
20
20
|
|
|
21
|
-
# Don't install the dependencies when we run `pod install` in the old architecture.
|
|
22
21
|
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
|
|
23
22
|
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
24
|
-
s.pod_target_xcconfig
|
|
23
|
+
s.pod_target_xcconfig = {
|
|
25
24
|
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
26
25
|
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
|
27
26
|
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
28
27
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
|
|
29
|
+
unless respond_to?(:install_modules_dependencies, true)
|
|
30
|
+
rn_pods = File.expand_path(File.join(__dir__, '..', '..', 'react-native', 'scripts', 'react_native_pods.rb'))
|
|
31
|
+
require rn_pods if File.exist?(rn_pods)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
if respond_to?(:install_modules_dependencies, true)
|
|
35
|
+
install_modules_dependencies(s)
|
|
36
|
+
else
|
|
37
|
+
raise "[@pyrocancode/react-native-vk-auth] New Architecture requires React Native scripts (install_modules_dependencies). Check that react-native is in node_modules."
|
|
38
|
+
end
|
|
39
|
+
else
|
|
40
|
+
s.dependency "React-Core"
|
|
34
41
|
end
|
|
35
42
|
end
|