@cloudbase/auth 2.5.47-beta.0 → 2.5.49-beta.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudbase/auth",
3
- "version": "2.5.47-beta.0",
3
+ "version": "2.5.49-beta.0",
4
4
  "description": "cloudbase javascript sdk auth componets",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -28,9 +28,9 @@
28
28
  "author": "",
29
29
  "license": "Apache-2.0",
30
30
  "dependencies": {
31
- "@cloudbase/oauth": "^2.5.47-beta.0",
32
- "@cloudbase/types": "^2.5.47-beta.0",
33
- "@cloudbase/utilities": "^2.5.47-beta.0"
31
+ "@cloudbase/oauth": "^2.5.49-beta.0",
32
+ "@cloudbase/types": "^2.5.49-beta.0",
33
+ "@cloudbase/utilities": "^2.5.49-beta.0"
34
34
  },
35
- "gitHead": "5eff80cfe47e3cf6e3067f1d9bba8753565e5b79"
35
+ "gitHead": "a4b9835493467e4ab8d35ba0ab3c02dbdc576edf"
36
36
  }
package/src/adapter.ts ADDED
@@ -0,0 +1,161 @@
1
+ import adapterForWxMp from 'cloudbase-adapter-wx_mp'
2
+ import { AuthOptions } from '@cloudbase/oauth'
3
+
4
+ declare const wx: any
5
+
6
+ class OauthClientStorageBase {
7
+ public readonly localStorage
8
+ constructor(config?: { localStorage: any /* StorageInterface */ }) {
9
+ this.localStorage = config?.localStorage || (globalThis as any).localStorage
10
+ }
11
+ /**
12
+ * Get Item
13
+ * @param {string} key
14
+ * @return {Promise<string | null>}
15
+ */
16
+ async getItem(key: string): Promise<string | null> {
17
+ return this.localStorage.getItem(key)
18
+ }
19
+
20
+ /**
21
+ * Remove Item.
22
+ * @param {string} key
23
+ * @return {Promise<void>}
24
+ */
25
+ async removeItem(key: string) {
26
+ this.localStorage.removeItem(key)
27
+ }
28
+
29
+ /**
30
+ * Set Item.
31
+ * @param {string} key
32
+ * @param {string} value
33
+ * @return {Promise<void>}
34
+ */
35
+ async setItem(key: string, value: string): Promise<void> {
36
+ this.localStorage.setItem(key, value)
37
+ }
38
+
39
+ getItemSync(key: string): string | null {
40
+ return this.localStorage.getItem(key)
41
+ }
42
+
43
+ setItemSync(key: string, value: string) {
44
+ this.localStorage.setItem(key, value)
45
+ }
46
+
47
+ removeItemSync(key: string) {
48
+ this.localStorage.removeItem(key)
49
+ }
50
+ }
51
+
52
+ /**
53
+ * copy to git@git.woa.com:QBase/lcap/datasource.git/packages/cloud-sdk/common
54
+ * 同步修改
55
+ */
56
+ const URL_REG = /^[^:]+:\/\/[^/]+(\/[^?#]+)/
57
+
58
+ function generateOauthClientRequest(reqClass) {
59
+ return async function (
60
+ url: string,
61
+ options?: {
62
+ body?: any | null
63
+ headers?: any | null
64
+ method?: string
65
+ [key: string]: any
66
+ },
67
+ ) {
68
+ const requestId = options?.headers?.['x-request-id']
69
+
70
+ return new Promise((resolve, reject) => {
71
+ // Objects must be copied to prevent modification of data such as body.
72
+ const copyOptions = Object.assign({}, options)
73
+ if (copyOptions.body && typeof copyOptions.body !== 'string') {
74
+ copyOptions.body = JSON.stringify(copyOptions.body)
75
+ }
76
+
77
+ const task = wx.request({
78
+ url,
79
+ data: copyOptions.body,
80
+ timeout: reqClass._timeout,
81
+ method: copyOptions.method || 'GET',
82
+ header: copyOptions.headers,
83
+ success(res) {
84
+ if (res.code) {
85
+ res = {
86
+ error: res.code,
87
+ error_description: res.message || res.code,
88
+ request_id: res.requestId,
89
+ }
90
+ }
91
+
92
+ if (!res.request_id) {
93
+ res.request_id = res.request_id || requestId
94
+ }
95
+
96
+ if (res.error) {
97
+ res.error_uri = getUrlPath(url)
98
+ reject(res)
99
+ }
100
+ resolve(res.data || {})
101
+ },
102
+ fail(err) {
103
+ reject({
104
+ error: 'unreachable',
105
+ error_description: (err as Error).message,
106
+ })
107
+ },
108
+ complete(err) {
109
+ if (!err || !err.errMsg) {
110
+ return
111
+ }
112
+ if (!reqClass._timeout || reqClass._restrictedMethods.indexOf('request') === -1) {
113
+ return
114
+ }
115
+ const { errMsg } = err
116
+ if (errMsg === 'request:fail timeout') {
117
+ console.warn(reqClass._timeoutMsg)
118
+ try {
119
+ task.abort()
120
+ } catch (e) {}
121
+ }
122
+ },
123
+ })
124
+ })
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Get url path.
130
+ * @param {string} url
131
+ * @return {string}
132
+ */
133
+ function getUrlPath(url: string) {
134
+ // return path if matched, or original url
135
+ return URL_REG.test(url) ? RegExp.$1 : url
136
+ }
137
+
138
+ export const useAuthAdapter = (config: AuthOptions) => {
139
+ if (!adapterForWxMp.isMatch() || (config.storage && config.baseRequest)) return config
140
+
141
+ const authOptions: any = {}
142
+ try {
143
+ const { localStorage, reqClass: ReqClass } = adapterForWxMp.genAdapter()
144
+ if (localStorage) {
145
+ authOptions.storage = new OauthClientStorageBase({ localStorage })
146
+ }
147
+ if (ReqClass) {
148
+ const reqClass = new ReqClass({
149
+ timeout: 10000,
150
+ restrictedMethods: ['get', 'post', 'upload', 'download', 'request'],
151
+ })
152
+ authOptions.request = generateOauthClientRequest(reqClass)
153
+ }
154
+
155
+ return { ...config, ...authOptions }
156
+ } catch (e) {
157
+ console.error('adapter generate fail:', e)
158
+ }
159
+
160
+ return config
161
+ }
package/src/index.ts CHANGED
@@ -6,9 +6,12 @@ import { ICloudbaseAuthConfig, IUser, IUserInfo, ILoginState } from '@cloudbase/
6
6
  import { ICloudbaseComponent } from '@cloudbase/types/component'
7
7
 
8
8
  import { authModels, CloudbaseOAuth, AuthOptions, Credentials } from '@cloudbase/oauth'
9
- import { ProviderSubType } from '@cloudbase/oauth/dist/cjs/auth/models'
9
+ import { GrantProviderTokenResponse, ProviderSubType } from '@cloudbase/oauth/dist/cjs/auth/models'
10
+ import { useAuthAdapter } from './adapter'
11
+ import adapterForWxMp from 'cloudbase-adapter-wx_mp'
10
12
 
11
13
  declare const cloudbase: ICloudbase
14
+ declare const wx: any
12
15
 
13
16
  const { printWarn, throwError } = utils
14
17
  const { ERRORS, COMMUNITY_SITE_URL } = constants
@@ -442,6 +445,307 @@ class Auth {
442
445
  return this.createLoginState()
443
446
  }
444
447
 
448
+ /**
449
+ * 小程序openId静默登录
450
+ * @returns {Promise<LoginState>}
451
+ * @memberof Auth
452
+ */
453
+ @catchErrorsDecorator({
454
+ title: '小程序openId静默登录失败',
455
+ messages: [
456
+ '请确认以下各项:',
457
+ ' 1 - 当前环境是否开启了小程序openId静默登录',
458
+ ' 2 - 调用 auth().signInWithOpenId() 的语法或参数是否正确',
459
+ `如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
460
+ ],
461
+ })
462
+ public async signInWithOpenId({ useWxCloud = true } = {}): Promise<LoginState> {
463
+ if (!adapterForWxMp.isMatch()) {
464
+ throw Error('wx api undefined')
465
+ }
466
+
467
+ if (useWxCloud) {
468
+ const wxInfo = wx.getAccountInfoSync().miniProgram
469
+ let result: GrantProviderTokenResponse | undefined = undefined
470
+ let credentials: Credentials | undefined = undefined
471
+ try {
472
+ result = await this.oauthInstance.authApi.grantProviderToken(
473
+ {
474
+ provider_id: wxInfo?.appId,
475
+ provider_params: {
476
+ provider_code_type: 'open_id',
477
+ },
478
+ },
479
+ true,
480
+ )
481
+
482
+ if ((result as any)?.error_code) {
483
+ throw result
484
+ }
485
+
486
+ credentials = await this.oauthInstance.authApi.signInWithProvider(
487
+ { provider_token: result.provider_token },
488
+ true,
489
+ )
490
+
491
+ if ((credentials as any)?.error_code) {
492
+ throw credentials
493
+ }
494
+ } catch (error) {
495
+ throw error
496
+ }
497
+
498
+ await this.oauthInstance.oauth2client.setCredentials(credentials as Credentials)
499
+ } else {
500
+ await new Promise((resolve, reject) => {
501
+ const wxInfo = wx.getAccountInfoSync().miniProgram
502
+ wx.login({
503
+ success: async (res: { code: string }) => {
504
+ const providerId = wxInfo?.appId
505
+ try {
506
+ const result = await this.oauthInstance.authApi.grantProviderToken({
507
+ provider_code: res.code,
508
+ provider_id: providerId,
509
+ provider_params: {
510
+ provider_code_type: 'open_id',
511
+ appid: wxInfo?.appId,
512
+ },
513
+ })
514
+
515
+ const { provider_token: providerToken } = result
516
+
517
+ if (!providerToken) {
518
+ reject(result)
519
+ return
520
+ }
521
+
522
+ const signInRes = await this.oauthInstance.authApi.signInWithProvider({
523
+ provider_token: providerToken,
524
+ })
525
+
526
+ if ((signInRes as any)?.error_code) {
527
+ reject(signInRes)
528
+ return
529
+ }
530
+
531
+ resolve(true)
532
+ } catch (error) {
533
+ reject(error)
534
+ }
535
+ },
536
+ fail: (res: any) => {
537
+ const error = new Error(res?.errMsg)
538
+ ;(error as any).code = res?.errno
539
+ reject(error)
540
+ },
541
+ })
542
+ })
543
+ }
544
+
545
+ return this.createLoginState()
546
+ }
547
+
548
+ /**
549
+ * 小程序unionId静默登录
550
+ * @returns {Promise<LoginState>}
551
+ * @memberof Auth
552
+ */
553
+ @catchErrorsDecorator({
554
+ title: '小程序unionId静默登录失败',
555
+ messages: [
556
+ '请确认以下各项:',
557
+ ' 1 - 当前环境是否开启了小程序unionId静默登录',
558
+ ' 2 - 调用 auth().signInWithUnionId() 的语法或参数是否正确',
559
+ `如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
560
+ ],
561
+ })
562
+ public async signInWithUnionId(): Promise<LoginState> {
563
+ if (!adapterForWxMp.isMatch()) {
564
+ throw Error('wx api undefined')
565
+ }
566
+ try {
567
+ await new Promise((resolve, reject) => {
568
+ const wxInfo = wx.getAccountInfoSync().miniProgram
569
+ wx.login({
570
+ success: async (res: { code: string }) => {
571
+ const providerId = wxInfo?.appId
572
+ try {
573
+ const result = await this.oauthInstance.authApi.grantProviderToken({
574
+ provider_code: res.code,
575
+ provider_id: providerId,
576
+ provider_params: {
577
+ provider_code_type: 'union_id',
578
+ appid: wxInfo?.appId,
579
+ },
580
+ })
581
+
582
+ const { provider_token: providerToken } = result
583
+
584
+ if (!providerToken) {
585
+ reject(result)
586
+ return
587
+ }
588
+
589
+ const signInRes = await this.oauthInstance.authApi.signInWithProvider({
590
+ provider_id: providerId,
591
+ provider_token: providerToken,
592
+ })
593
+
594
+ if ((signInRes as any)?.error_code) {
595
+ reject(signInRes)
596
+ return
597
+ }
598
+ resolve(true)
599
+ } catch (error) {
600
+ reject(error)
601
+ }
602
+ },
603
+ fail: (res: any) => {
604
+ const error = new Error(res?.errMsg)
605
+ ;(error as any).code = res?.errno
606
+ reject(error)
607
+ },
608
+ })
609
+ })
610
+ } catch (error) {
611
+ throw error
612
+ }
613
+
614
+ return this.createLoginState()
615
+ }
616
+
617
+ /**
618
+ * 小程序手机号授权登录
619
+ * @returns {Promise<LoginState>}
620
+ * @memberof Auth
621
+ */
622
+ @catchErrorsDecorator({
623
+ title: '小程序手机号授权登录失败',
624
+ messages: [
625
+ '请确认以下各项:',
626
+ ' 1 - 当前环境是否开启了小程序手机号授权登录',
627
+ ' 2 - 调用 auth().signInWithPhoneAuth() 的语法或参数是否正确',
628
+ `如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
629
+ ],
630
+ })
631
+ public async signInWithPhoneAuth({ phoneCode = '' }): Promise<LoginState> {
632
+ if (!adapterForWxMp.isMatch()) {
633
+ throw Error('wx api undefined')
634
+ }
635
+ const wxInfo = wx.getAccountInfoSync().miniProgram
636
+ const providerInfo = {
637
+ provider_params: { provider_code_type: 'phone' },
638
+ provider_id: wxInfo.appId,
639
+ }
640
+
641
+ const { code } = await wx.login()
642
+ ;(providerInfo as any).provider_code = code
643
+
644
+ try {
645
+ let providerToken = await this.oauthInstance.authApi.grantProviderToken(providerInfo)
646
+ if (providerToken.error_code) {
647
+ throw providerToken
648
+ }
649
+
650
+ providerToken = await this.oauthInstance.authApi.patchProviderToken({
651
+ provider_token: providerToken.provider_token,
652
+ provider_id: wxInfo.appId,
653
+ provider_params: {
654
+ code: phoneCode,
655
+ provider_code_type: 'phone',
656
+ },
657
+ })
658
+ if (providerToken.error_code) {
659
+ throw providerToken
660
+ }
661
+
662
+ const signInRes = await this.oauthInstance.authApi.signInWithProvider({
663
+ provider_token: providerToken.provider_token,
664
+ })
665
+
666
+ if ((signInRes as any)?.error_code) {
667
+ throw signInRes
668
+ }
669
+ } catch (error) {
670
+ throw error
671
+ }
672
+
673
+ return this.createLoginState()
674
+ }
675
+
676
+ /**
677
+ * 小程序短信验证码登陆
678
+ * @returns {Promise<LoginState>}
679
+ * @memberof Auth
680
+ */
681
+ @catchErrorsDecorator({
682
+ title: '小程序短信验证码登陆',
683
+ messages: [
684
+ '请确认以下各项:',
685
+ ' 1 - 当前环境是否开启了小程序短信验证码登陆',
686
+ ' 2 - 调用 auth().signInWithSms() 的语法或参数是否正确',
687
+ `如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
688
+ ],
689
+ })
690
+ public async signInWithSms({
691
+ verificationInfo = { id: '', isUser: false },
692
+ verificationCode = '',
693
+ phoneNum = '',
694
+ bindInfo = undefined,
695
+ }): Promise<LoginState> {
696
+ try {
697
+ // 1. 验证验证码
698
+ const verifyRes = await this.oauthInstance.authApi.verify({
699
+ verification_id: verificationInfo.id,
700
+ verification_code: verificationCode,
701
+ })
702
+
703
+ if ((verifyRes as any)?.error_code) {
704
+ throw verifyRes
705
+ }
706
+
707
+ const { verification_token } = verifyRes
708
+
709
+ // 2. 根据是否已经是用户,分别走登录或注册逻辑
710
+ if (verificationInfo.isUser) {
711
+ // 私有化环境或者自定义应用走v1版本的老逻辑
712
+ const signInRes = await this.oauthInstance.authApi.signIn({
713
+ username: `+86 ${phoneNum}`,
714
+ verification_token,
715
+ })
716
+
717
+ if ((signInRes as any)?.error_code) {
718
+ throw signInRes
719
+ }
720
+
721
+ if (bindInfo) {
722
+ const bindRes = await this.oauthInstance.authApi.bindWithProvider({
723
+ provider_token: (bindInfo as any)?.providerToken,
724
+ })
725
+
726
+ if ((bindRes as any)?.error_code) {
727
+ throw bindRes
728
+ }
729
+ }
730
+ } else {
731
+ // 自定义应用走signUp逻辑
732
+ const signUpRes = await this.oauthInstance.authApi.signUp({
733
+ phone_number: `+86 ${phoneNum}`,
734
+ verification_token,
735
+ provider_token: (bindInfo as any)?.providerId,
736
+ })
737
+
738
+ if ((signUpRes as any)?.error_code) {
739
+ throw signUpRes
740
+ }
741
+ }
742
+
743
+ return this.createLoginState()
744
+ } catch (error) {
745
+ throw error
746
+ }
747
+ }
748
+
445
749
  /**
446
750
  * 设置获取自定义登录 ticket 函数
447
751
  * @param {authModels.GetCustomSignTicketFn} getTickFn
@@ -826,8 +1130,9 @@ const component: ICloudbaseComponent = {
826
1130
  this.updateConfig({ persistence: newPersistence })
827
1131
  }
828
1132
 
829
- const { env, persistence, debug, clientId, storage } = this.config
830
- const oauthInstance = new CloudbaseOAuth({
1133
+ const { env, persistence, debug, clientId, storage, wxCloud } = this.config
1134
+ const oauthInstance = new CloudbaseOAuth(useAuthAdapter({
1135
+ env,
831
1136
  clientId,
832
1137
  apiOrigin: this.request.getBaseEndPoint(),
833
1138
  // @todo 以下最好走adaptor处理,目前oauth模块没按adaptor接口设计
@@ -836,7 +1141,8 @@ const component: ICloudbaseComponent = {
836
1141
  request: config?.request,
837
1142
  anonymousSignInFunc: config?.anonymousSignInFunc,
838
1143
  captchaOptions: config?.captchaOptions,
839
- })
1144
+ wxCloud: config?.wxCloud || wxCloud,
1145
+ }),)
840
1146
 
841
1147
  this.oauthInstance = oauthInstance
842
1148