@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/src/index.tsx CHANGED
@@ -20,12 +20,12 @@ interface VkAuthModule extends NativeModule {
20
20
  startAuth: () => void;
21
21
  closeAuth: () => void;
22
22
  logout: () => void;
23
- getUserSessions: () => void;
24
- initialize: (app: VK.App, vkid: VKID) => void;
23
+ getUserSessions: () => Promise<Array<{ type: string }>>;
24
+ initialize: (app: VK.App, vkid: VKIDInitPayload) => void;
25
25
  openURL: (url: string) => void;
26
26
 
27
- accessTokenChangedSuccess: (token: string, userId: bigint) => void;
28
- accessTokenChangedFailed: (error: Error) => void;
27
+ accessTokenChangedSuccess: (token: string, userId: number) => void;
28
+ accessTokenChangedFailed: (error: Record<string, unknown>) => void;
29
29
  }
30
30
 
31
31
  const VkAuth: VkAuthModule = NativeModules.VkAuth
@@ -39,9 +39,22 @@ const VkAuth: VkAuthModule = NativeModules.VkAuth
39
39
  }
40
40
  );
41
41
 
42
+ /** Плоский объект для нативного моста (см. jsinput/VKID.kt). */
43
+ export type VKIDInitPayload = {
44
+ appName: string;
45
+ appVersion: string;
46
+ appIcon: ImageResolvedAssetSource;
47
+ appLinks: VKID.Links;
48
+ };
49
+
42
50
  export class VK {
43
51
  static initialize(app: VK.App, vkid: VKID) {
44
- VkAuth.initialize(app, vkid);
52
+ VkAuth.initialize(app, {
53
+ appName: vkid.appName,
54
+ appVersion: vkid.appVersion,
55
+ appIcon: vkid.appIcon,
56
+ appLinks: vkid.appLinks,
57
+ });
45
58
  }
46
59
 
47
60
  static openURL(url: string) {
@@ -67,43 +80,81 @@ export namespace VK {
67
80
  }
68
81
  }
69
82
 
83
+ function parseOnAuthPayload(
84
+ raw: Record<string, unknown>
85
+ ): { kind: 'error'; message: string } | { kind: 'ok'; payload: VKID.AuthSuccessPayload } {
86
+ if (raw.type === 'error') {
87
+ return {
88
+ kind: 'error',
89
+ message: String(raw.error ?? 'VK ID authorization failed'),
90
+ };
91
+ }
92
+
93
+ if (raw.type === 'authorized') {
94
+ const vkid = raw.vkid as Record<string, unknown> | undefined;
95
+ if (vkid && typeof vkid.accessToken === 'string') {
96
+ const uid =
97
+ vkid.userID != null && String(vkid.userID) !== ''
98
+ ? String(vkid.userID)
99
+ : profileUserIdFromProfile(raw.profile);
100
+ if (!uid) {
101
+ return { kind: 'error', message: 'VK user id missing in auth payload' };
102
+ }
103
+ return {
104
+ kind: 'ok',
105
+ payload: {
106
+ accessToken: vkid.accessToken,
107
+ userId: uid,
108
+ profile: raw.profile as VKID.UserProfile | undefined,
109
+ vkidNative: vkid,
110
+ },
111
+ };
112
+ }
113
+
114
+ if (typeof raw.accessToken === 'string' && typeof raw.userId === 'string') {
115
+ if (!raw.userId) {
116
+ return { kind: 'error', message: 'VK user id missing in auth payload' };
117
+ }
118
+ return {
119
+ kind: 'ok',
120
+ payload: {
121
+ accessToken: raw.accessToken,
122
+ userId: raw.userId,
123
+ profile: raw.profile as VKID.UserProfile | undefined,
124
+ },
125
+ };
126
+ }
127
+ }
128
+
129
+ return { kind: 'error', message: 'Unexpected VK auth payload' };
130
+ }
131
+
132
+ function profileUserIdFromProfile(profile: unknown): string {
133
+ if (!profile || typeof profile !== 'object') {
134
+ return '';
135
+ }
136
+ const u = (profile as { userID?: { value?: string } }).userID;
137
+ return u?.value != null ? String(u.value) : '';
138
+ }
139
+
70
140
  export class VKID {
71
141
  readonly appName: string;
72
142
  readonly appVersion: string;
73
143
  readonly appIcon: ImageResolvedAssetSource;
74
144
  readonly appLinks: VKID.Links;
75
- private readonly silentTokenExchanger: VKID.SilentTokenExchanger;
76
145
  private readonly eventEmitter: NativeEventEmitter;
77
146
 
78
147
  constructor(
79
148
  appName: string,
80
149
  appVersion: string,
81
150
  appIcon: ImageResolvedAssetSource,
82
- appLinks: VKID.Links,
83
- silentTokenExchanger: VKID.SilentTokenExchanger
151
+ appLinks: VKID.Links
84
152
  ) {
85
153
  this.appName = appName;
86
154
  this.appVersion = appVersion;
87
155
  this.appIcon = appIcon;
88
156
  this.appLinks = appLinks;
89
- this.silentTokenExchanger = silentTokenExchanger;
90
157
  this.eventEmitter = new NativeEventEmitter(VkAuth);
91
-
92
- this.initSilentDataReceive();
93
- }
94
-
95
- private initSilentDataReceive() {
96
- this.eventEmitter.removeAllListeners('onSilentDataReceive');
97
- this.eventEmitter.addListener(
98
- 'onSilentDataReceive',
99
- async (silentToken: VKID.SilentToken) => {
100
- let exchangeResult: VKID.TokenExchangeResult =
101
- await this.silentTokenExchanger.exchange(silentToken).catch(() => {
102
- return { ok: false, error: Error('Exchange failed') };
103
- });
104
- VKID.accessTokenChanged(exchangeResult);
105
- }
106
- );
107
158
  }
108
159
 
109
160
  startAuth() {
@@ -123,12 +174,8 @@ export class VKID {
123
174
  }
124
175
 
125
176
  userSessions(): Promise<Array<VKID.Session.UserSession>> {
126
- // @ts-ignore
127
- let promise: Promise<Array<UserSessionInternal.UserSession>> =
128
- VkAuth.getUserSessions();
129
- return promise.then((sessions) => {
130
- return sessions.map((session) => {
131
- console.log(session);
177
+ return VkAuth.getUserSessions().then(sessions => {
178
+ return sessions.map(session => {
132
179
  return session.type === UserSessionInternal.Type.AUTHORIZED
133
180
  ? new VKID.Session.Authorized()
134
181
  : new VKID.Session.Authenticated();
@@ -136,38 +183,26 @@ export class VKID {
136
183
  });
137
184
  }
138
185
 
139
- setOnAuthChanged(onAuthChanged: VKID.AuthChangedCallback) {
186
+ setOnAuthChanged(callbacks: VKID.AuthChangedCallback) {
140
187
  this.eventEmitter.removeAllListeners('onLogout');
141
188
  this.eventEmitter.removeAllListeners('onAuth');
142
189
 
143
190
  this.eventEmitter.addListener('onLogout', () => {
144
- onAuthChanged.onLogout();
191
+ callbacks.onLogout();
145
192
  });
193
+
146
194
  this.eventEmitter.addListener(
147
195
  'onAuth',
148
- (session: UserSessionInternal.UserSession) => {
149
- console.log(session);
150
- let externalSession =
151
- session.type === UserSessionInternal.Type.AUTHORIZED
152
- ? new VKID.Session.Authorized()
153
- : new VKID.Session.Authenticated();
154
- onAuthChanged.onAuth(externalSession);
196
+ (raw: Record<string, unknown>) => {
197
+ const parsed = parseOnAuthPayload(raw);
198
+ if (parsed.kind === 'error') {
199
+ callbacks.onAuthFailed?.(parsed.message);
200
+ return;
201
+ }
202
+ callbacks.onAuthorized(parsed.payload);
155
203
  }
156
204
  );
157
205
  }
158
-
159
- private static accessTokenChanged(
160
- result: VKID.TokenExchangeResult<VKID.AccessToken, Error>
161
- ) {
162
- if (result.ok) {
163
- VkAuth.accessTokenChangedSuccess(
164
- result.accessToken.token.value,
165
- result.accessToken.userID.value
166
- );
167
- } else {
168
- VkAuth.accessTokenChangedFailed(result.error);
169
- }
170
- }
171
206
  }
172
207
 
173
208
  export namespace VKID {
@@ -187,24 +222,6 @@ export namespace VKID {
187
222
  }
188
223
  }
189
224
 
190
- export interface SilentToken {
191
- token: Token;
192
- uuid: string;
193
- firstName: string;
194
- lastName: string;
195
- }
196
-
197
- export interface SilentTokenExchanger {
198
- exchange(
199
- silentData: VKID.SilentToken
200
- ): Promise<VKID.TokenExchangeResult<VKID.AccessToken, Error>>;
201
- }
202
-
203
- export interface AccessToken {
204
- token: Token;
205
- userID: UserID;
206
- }
207
-
208
225
  export interface Links {
209
226
  serviceUserAgreement: string;
210
227
  servicePrivacyPolicy: string;
@@ -221,10 +238,19 @@ export namespace VKID {
221
238
  userHash: string | null;
222
239
  }
223
240
 
224
- export interface AuthChangedCallback {
225
- onAuth(userSession: VKID.Session.UserSession): void;
241
+ /** Успешная авторизация VK ID (OAuth 2.1): access token и id пользователя VK. */
242
+ export interface AuthSuccessPayload {
243
+ accessToken: string;
244
+ userId: string;
245
+ profile?: UserProfile;
246
+ /** Android: полный ответ VK ID SDK (отладка). */
247
+ vkidNative?: Record<string, unknown>;
248
+ }
226
249
 
250
+ export interface AuthChangedCallback {
251
+ onAuthorized(payload: AuthSuccessPayload): void;
227
252
  onLogout(): void;
253
+ onAuthFailed?(message: string): void;
228
254
  }
229
255
 
230
256
  export namespace Session {
@@ -250,10 +276,6 @@ export namespace VKID {
250
276
  }
251
277
  }
252
278
  }
253
-
254
- export type TokenExchangeResult<T = VKID.AccessToken, E = Error> =
255
- | { ok: true; accessToken: T }
256
- | { ok: false; error: E };
257
279
  }
258
280
 
259
281
  namespace UserSessionInternal {
@@ -1,33 +0,0 @@
1
- package com.vkauth.vkid
2
-
3
- import com.facebook.react.bridge.ReactApplicationContext
4
- import com.vk.auth.main.SilentAuthSource
5
- import com.vk.auth.main.VkFastLoginModifiedUser
6
- import com.vk.auth.main.VkSilentTokenExchanger
7
- import com.vkauth.vkid.dto.SilentAuthInfo
8
- import com.vkauth.vkid.dto.Token
9
- import com.vkauth.vkid.jstutils.JsCbSender
10
-
11
- internal class JSSilentTokenExchanger(
12
- private val context: ReactApplicationContext
13
- ) : VkSilentTokenExchanger {
14
- private val jsCallbackSender = JsCbSender()
15
-
16
- override fun exchangeSilentToken(
17
- user: com.vk.silentauth.SilentAuthInfo,
18
- modifiedUser: VkFastLoginModifiedUser?,
19
- source: SilentAuthSource
20
- ): VkSilentTokenExchanger.Result {
21
- jsCallbackSender.sendCallback(context, SILENT_DATA_EVENT, SilentAuthInfo(
22
- silentToken = Token(user.token),
23
- uuid = user.uuid,
24
- firstName = user.firstName,
25
- lastName = user.lastName,
26
- ).toMap())
27
- return VkSilentTokenExchanger.Result.Success(accessToken = "will be exchanged in js part", uid = 1)
28
- }
29
-
30
- private companion object {
31
- private const val SILENT_DATA_EVENT = "onSilentDataReceive"
32
- }
33
- }
@@ -1,75 +0,0 @@
1
- package com.vkauth.vkid
2
-
3
- import android.app.Application
4
- import android.content.Context
5
- import android.content.res.Resources
6
- import android.graphics.BitmapFactory
7
- import android.graphics.drawable.BitmapDrawable
8
- import android.graphics.drawable.Drawable
9
- import android.net.Uri
10
- import com.facebook.react.bridge.ReactApplicationContext
11
- import com.vk.auth.main.VkClientAuthLibConfig
12
- import com.vk.auth.main.VkClientLibverifyInfo
13
- import com.vk.auth.main.VkClientUiInfo
14
- import com.vk.superapp.SuperappKit
15
- import com.vk.superapp.SuperappKitConfig
16
- import com.vk.superapp.core.SuperappConfig
17
- import com.vkauth.vkid.jsinput.App
18
- import com.vkauth.vkid.jsinput.VKID
19
- import java.net.URL
20
-
21
- internal object SuperAppKitInitUtils {
22
- private const val DRAWABLE_DEF_TYPE = "drawable"
23
- private val HTTP_SCHEMES = listOf("http", "https")
24
-
25
- fun initSuperappKit(reactAppContext: ReactApplicationContext, app: App, vkid: VKID) {
26
- if (SuperappKit.isInitialized()) {
27
- return
28
- }
29
-
30
- val appInfo = SuperappConfig.AppInfo(
31
- appName = vkid.appName,
32
- appVersion = vkid.appVersion,
33
- appId = app.credentials.clientId,
34
- )
35
-
36
- val logo = resolveLogoUri(reactAppContext, Uri.parse(vkid.icon.getString("uri")))
37
-
38
- val builder = SuperappKitConfig.Builder(reactAppContext.applicationContext as Application)
39
- .setAuthModelData(
40
- VkClientAuthLibConfig.AuthModelData(
41
- clientSecret = app.credentials.clientSecret,
42
- libverifyInfo = VkClientLibverifyInfo.disabled(),
43
- ignoreSuccessAuth = true
44
- )
45
- )
46
- .setAuthUiManagerData(VkClientUiInfo(icon48 = logo, icon56 = logo, appName = vkid.appName))
47
- .setLegalInfoLinks(
48
- serviceUserAgreement = vkid.links.serviceUserAgreement,
49
- servicePrivacyPolicy = vkid.links.servicePrivacyPolicy,
50
- serviceSupport = vkid.links.serviceSupport
51
- )
52
- .setApplicationInfo(appInfo)
53
- .setSilentTokenExchanger(JSSilentTokenExchanger(reactAppContext))
54
- .sslPinningEnabled(false)
55
- .build()
56
-
57
- SuperappKit.init(builder)
58
- }
59
-
60
- private fun resolveLogoUri(context: Context, uri: Uri): Drawable {
61
- return if (uri.scheme in HTTP_SCHEMES) {
62
- URL(uri.toString()).openConnection()
63
- .apply { connect() }
64
- .getInputStream()
65
- .use {
66
- BitmapDrawable(Resources.getSystem(), BitmapFactory.decodeStream(it))
67
- }
68
- } else {
69
- val fileName = uri.toString()
70
- val resourceId = context.resources.getIdentifier(fileName, DRAWABLE_DEF_TYPE, context.packageName)
71
- val bitmap = BitmapFactory.decodeResource(context.resources, resourceId)
72
- BitmapDrawable(Resources.getSystem(), bitmap)
73
- }
74
- }
75
- }
@@ -1,19 +0,0 @@
1
- package com.vkauth.vkid.dto
2
-
3
- import com.facebook.react.bridge.Arguments
4
- import com.facebook.react.bridge.WritableMap
5
- import com.vk.dto.common.id.UserId
6
- import com.vkauth.vkid.jstutils.JsOutputParam
7
-
8
- internal data class AccessToken(
9
- val token: Token,
10
- val userId: UserId
11
- ) : JsOutputParam {
12
-
13
- override fun toMap(): WritableMap {
14
- return Arguments.createMap().apply {
15
- putMap("token", token.toMap())
16
- putMap("userId", userId.toMap())
17
- }
18
- }
19
- }
@@ -1,24 +0,0 @@
1
- package com.vkauth.vkid.dto
2
-
3
- import com.facebook.react.bridge.Arguments
4
- import com.facebook.react.bridge.WritableMap
5
- import com.vk.auth.main.VkClientAuthLib
6
- import com.vk.dto.common.id.UserId
7
- import com.vk.superapp.api.dto.account.ProfileShortInfo
8
-
9
- fun UserId.toMap(): WritableMap {
10
- return Arguments.createMap().apply {
11
- putDouble("value", value.toDouble())
12
- }
13
- }
14
-
15
- fun ProfileShortInfo.toMap(): WritableMap {
16
- return Arguments.createMap().apply {
17
- putMap("userID", VkClientAuthLib.getUserId().toMap())
18
- putString("firstName", firstName)
19
- putString("lastName", lastName)
20
- putString("phone", phone)
21
- putString("photo200", photo200)
22
- putString("userHash", userHash)
23
- }
24
- }
@@ -1,22 +0,0 @@
1
- package com.vkauth.vkid.dto
2
-
3
- import com.facebook.react.bridge.Arguments
4
- import com.facebook.react.bridge.WritableMap
5
- import com.vkauth.vkid.jstutils.JsOutputParam
6
-
7
-
8
- internal data class SilentAuthInfo(
9
- val silentToken: Token,
10
- val uuid: String,
11
- val firstName: String,
12
- val lastName: String,
13
- ) : JsOutputParam {
14
- override fun toMap(): WritableMap {
15
- return Arguments.createMap().apply {
16
- putMap("token", silentToken.toMap())
17
- putString("uuid", uuid)
18
- putString("firstName", firstName)
19
- putString("lastName", lastName)
20
- }
21
- }
22
- }
@@ -1,15 +0,0 @@
1
- package com.vkauth.vkid.dto
2
-
3
- import com.facebook.react.bridge.Arguments
4
- import com.facebook.react.bridge.WritableMap
5
- import com.vkauth.vkid.jstutils.JsOutputParam
6
-
7
- internal data class Token(
8
- val value: String
9
- ) : JsOutputParam {
10
- override fun toMap(): WritableMap {
11
- return Arguments.createMap().apply {
12
- putString("value", value)
13
- }
14
- }
15
- }
@@ -1,28 +0,0 @@
1
- package com.vkauth.vkid.dto
2
-
3
- import com.facebook.react.bridge.Arguments
4
- import com.facebook.react.bridge.WritableMap
5
- import com.vkauth.vkid.jstutils.JsOutputParam
6
-
7
- internal sealed class UserSession(val type: String) : JsOutputParam {
8
- object Authorized: UserSession(AUTHORIZED) {
9
- override fun toMap(): WritableMap {
10
- return Arguments.createMap().apply {
11
- putString("type", type)
12
- }
13
- }
14
- }
15
-
16
- object Authenticated : UserSession(AUTHENTICATED) {
17
- override fun toMap(): WritableMap {
18
- return Arguments.createMap().apply {
19
- putString("type", type)
20
- }
21
- }
22
- }
23
-
24
- private companion object {
25
- private const val AUTHORIZED = "authorized"
26
- private const val AUTHENTICATED = "authenticated"
27
- }
28
- }
@@ -1,16 +0,0 @@
1
- package com.vkauth.vkid.jstutils
2
-
3
- import com.facebook.react.bridge.ReactContext
4
- import com.facebook.react.bridge.WritableMap
5
- import com.facebook.react.modules.core.DeviceEventManagerModule
6
-
7
- class JsCbSender {
8
- fun sendCallback(
9
- context: ReactContext,
10
- callbackName: String,
11
- callbackParams: WritableMap?
12
- ) {
13
- context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
14
- .emit(callbackName, callbackParams)
15
- }
16
- }
@@ -1,7 +0,0 @@
1
- package com.vkauth.vkid.jstutils
2
-
3
- import com.facebook.react.bridge.WritableMap
4
-
5
- internal interface JsOutputParam {
6
- fun toMap(): WritableMap
7
- }