@cloudbase/auth 1.7.3-alpha.0 → 2.0.0-alpha.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/dist/cjs/index.d.ts +50 -101
- package/dist/cjs/index.js +415 -778
- package/dist/esm/index.d.ts +50 -101
- package/dist/esm/index.js +416 -775
- package/package.json +52 -54
- package/src/index.ts +401 -766
- package/dist/cjs/common.d.ts +0 -8
- package/dist/cjs/common.js +0 -64
- package/dist/cjs/constants.d.ts +0 -12
- package/dist/cjs/constants.js +0 -17
- package/dist/cjs/providers/anonymousAuthProvider.d.ts +0 -15
- package/dist/cjs/providers/anonymousAuthProvider.js +0 -256
- package/dist/cjs/providers/base.d.ts +0 -21
- package/dist/cjs/providers/base.js +0 -152
- package/dist/cjs/providers/customAuthProvider.d.ts +0 -5
- package/dist/cjs/providers/customAuthProvider.js +0 -150
- package/dist/cjs/providers/emailAuthProvider.d.ts +0 -9
- package/dist/cjs/providers/emailAuthProvider.js +0 -250
- package/dist/cjs/providers/oauth2AuthProvider.d.ts +0 -61
- package/dist/cjs/providers/oauth2AuthProvider.js +0 -404
- package/dist/cjs/providers/phoneAuthProvider.d.ts +0 -17
- package/dist/cjs/providers/phoneAuthProvider.js +0 -219
- package/dist/cjs/providers/usernameAuthProvider.d.ts +0 -5
- package/dist/cjs/providers/usernameAuthProvider.js +0 -169
- package/dist/cjs/providers/weixinAuthProvider.d.ts +0 -28
- package/dist/cjs/providers/weixinAuthProvider.js +0 -294
- package/dist/esm/common.d.ts +0 -8
- package/dist/esm/common.js +0 -61
- package/dist/esm/constants.d.ts +0 -12
- package/dist/esm/constants.js +0 -14
- package/dist/esm/providers/anonymousAuthProvider.d.ts +0 -15
- package/dist/esm/providers/anonymousAuthProvider.js +0 -253
- package/dist/esm/providers/base.d.ts +0 -21
- package/dist/esm/providers/base.js +0 -149
- package/dist/esm/providers/customAuthProvider.d.ts +0 -5
- package/dist/esm/providers/customAuthProvider.js +0 -147
- package/dist/esm/providers/emailAuthProvider.d.ts +0 -9
- package/dist/esm/providers/emailAuthProvider.js +0 -247
- package/dist/esm/providers/oauth2AuthProvider.d.ts +0 -61
- package/dist/esm/providers/oauth2AuthProvider.js +0 -401
- package/dist/esm/providers/phoneAuthProvider.d.ts +0 -17
- package/dist/esm/providers/phoneAuthProvider.js +0 -216
- package/dist/esm/providers/usernameAuthProvider.d.ts +0 -5
- package/dist/esm/providers/usernameAuthProvider.js +0 -166
- package/dist/esm/providers/weixinAuthProvider.d.ts +0 -28
- package/dist/esm/providers/weixinAuthProvider.js +0 -291
- package/src/common.ts +0 -21
- package/src/constants.ts +0 -13
- package/src/providers/anonymousAuthProvider.ts +0 -126
- package/src/providers/base.ts +0 -78
- package/src/providers/customAuthProvider.ts +0 -69
- package/src/providers/emailAuthProvider.ts +0 -142
- package/src/providers/oauth2AuthProvider.ts +0 -585
- package/src/providers/phoneAuthProvider.ts +0 -132
- package/src/providers/usernameAuthProvider.ts +0 -77
- package/src/providers/weixinAuthProvider.ts +0 -193
|
@@ -1,585 +0,0 @@
|
|
|
1
|
-
import { AuthProvider } from './base'
|
|
2
|
-
import { ICloudbaseAuthConfig } from '@cloudbase/types/auth'
|
|
3
|
-
import { ICloudbaseCache } from '@cloudbase/types/cache'
|
|
4
|
-
import { ICloudbaseRequest } from '@cloudbase/types/request'
|
|
5
|
-
import { constants, utils, helpers } from '@cloudbase/utilities/'
|
|
6
|
-
import { eventBus, EVENTS, LoginState } from '..'
|
|
7
|
-
import { OAUTH2_LOGINTYPE_PREFIX } from '../constants';
|
|
8
|
-
|
|
9
|
-
const { getSdkName, ERRORS, COMMUNITY_SITE_URL } = constants
|
|
10
|
-
const { catchErrorsDecorator } = helpers
|
|
11
|
-
|
|
12
|
-
function qsParse(qs: string): object {
|
|
13
|
-
return qs.split('&').reduce((a, c) => {
|
|
14
|
-
const [key, value] = c.split('=')
|
|
15
|
-
a[key] = value
|
|
16
|
-
return a
|
|
17
|
-
}, {})
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const kPaths = {
|
|
21
|
-
prividerUri: '/auth/v1/provider/uri',
|
|
22
|
-
prividerToken: '/auth/v1/provider/token',
|
|
23
|
-
signinWithProvider: '/auth/v1/signin/with/provider',
|
|
24
|
-
me: '/auth/v1/user/me',
|
|
25
|
-
token: '/auth/v1/token',
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
interface IGenProviderRedirectURIRequest {
|
|
29
|
-
response_type: string // token | code
|
|
30
|
-
provider_id: string // google github ...
|
|
31
|
-
client_id: string //
|
|
32
|
-
scope: string //
|
|
33
|
-
redirect_uri: string
|
|
34
|
-
state?: string
|
|
35
|
-
// other_params?: string
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
interface IGenProviderRedirectURIResponse {
|
|
39
|
-
uri: string
|
|
40
|
-
signout_uri: string
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
interface IGrantProviderTokenRequest {
|
|
44
|
-
provider_id: string
|
|
45
|
-
client_id: string
|
|
46
|
-
|
|
47
|
-
// 以下参数任选其一即可
|
|
48
|
-
provider_code?: string // 'provider_code'
|
|
49
|
-
provider_access_token?: string // 'provider_access_token'
|
|
50
|
-
provider_id_token?: string // 'provider_id_token'
|
|
51
|
-
|
|
52
|
-
provider_redirect_uri?: string
|
|
53
|
-
provider_params?: string // 'provider_params'
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
interface IProviderProfile {
|
|
57
|
-
provider_id: string
|
|
58
|
-
// 主ID
|
|
59
|
-
sub?: string
|
|
60
|
-
name?: string
|
|
61
|
-
picture?: string
|
|
62
|
-
email?: string
|
|
63
|
-
phone_number?: string
|
|
64
|
-
gender?: string
|
|
65
|
-
locale?: string
|
|
66
|
-
// 三方信息原文
|
|
67
|
-
raw?: string
|
|
68
|
-
// 其他关联的ID
|
|
69
|
-
associated_ids?: string
|
|
70
|
-
meta?: {
|
|
71
|
-
[key: string]: string
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
interface IGrantProviderTokenResponse {
|
|
76
|
-
// 如果不启用自动注册, 则返回 provider_token, 用于进一步处理,例如:通过手机号等。
|
|
77
|
-
provider_token: string
|
|
78
|
-
// 过期时间
|
|
79
|
-
expires_in: number
|
|
80
|
-
// 如果不启用自动注册,则会返回provider userinfo end_point 的返回详情,用于前端展示
|
|
81
|
-
provider_profile: IProviderProfile
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
interface ISignInWithProviderRequest {
|
|
85
|
-
client_id: string
|
|
86
|
-
provider_token: string
|
|
87
|
-
// 强制关闭自动注册。
|
|
88
|
-
// 默认情况下,这里以服务器配置为准,如果客户端为了平滑升级可以配置为true。
|
|
89
|
-
force_disable_sign_up: boolean
|
|
90
|
-
// 是否强制从第三方同步昵称等信息
|
|
91
|
-
sync_profile: boolean
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
interface IToken {
|
|
95
|
-
token_type: string
|
|
96
|
-
access_token: string
|
|
97
|
-
refresh_token: string
|
|
98
|
-
id_token: string
|
|
99
|
-
expires_in: number
|
|
100
|
-
scope?: string
|
|
101
|
-
sub?: string
|
|
102
|
-
user_group?: string
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
interface IPrividerCallbackInfo {
|
|
106
|
-
href: string,
|
|
107
|
-
|
|
108
|
-
state: string,
|
|
109
|
-
|
|
110
|
-
token_type: string,
|
|
111
|
-
code?: string,
|
|
112
|
-
access_token?: string,
|
|
113
|
-
id_token?: string,
|
|
114
|
-
|
|
115
|
-
expires_in: number,
|
|
116
|
-
scope: string,
|
|
117
|
-
authuser: string,
|
|
118
|
-
prompt: string
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
interface IPopupWindowAuthRedirectMessage {
|
|
122
|
-
source: string,
|
|
123
|
-
callbackInfo: IPrividerCallbackInfo
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export interface IOAuth2AuthProviderOptions {
|
|
127
|
-
providerId?: string
|
|
128
|
-
clientId?: string
|
|
129
|
-
responseType?: string
|
|
130
|
-
scope?: string
|
|
131
|
-
redirectUri?: string
|
|
132
|
-
|
|
133
|
-
syncProfile?: boolean
|
|
134
|
-
forceDisableSignUp?: boolean
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export interface ISignInWithPopupOptions {
|
|
138
|
-
popup?: {
|
|
139
|
-
target?: string,
|
|
140
|
-
features?: string
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
interface IAuthServerRespError {
|
|
145
|
-
error: string,
|
|
146
|
-
error_code: number,
|
|
147
|
-
error_description: string
|
|
148
|
-
request_id: string
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export class OAuth2AuthProvider extends AuthProvider {
|
|
152
|
-
// private readonly _scope: string
|
|
153
|
-
// private readonly _state: string
|
|
154
|
-
// private readonly _appid: string
|
|
155
|
-
// private readonly _runtime: string
|
|
156
|
-
|
|
157
|
-
private providerId: string
|
|
158
|
-
private clientId: string
|
|
159
|
-
private responseType: string
|
|
160
|
-
private scope: string
|
|
161
|
-
private redirectUri: string
|
|
162
|
-
private syncProfile: boolean
|
|
163
|
-
private forceDisableSignUp: boolean
|
|
164
|
-
|
|
165
|
-
private popupWindowUrl: string
|
|
166
|
-
private popupWindowRef: Window = null
|
|
167
|
-
|
|
168
|
-
constructor(config: ICloudbaseAuthConfig&{cache:ICloudbaseCache,request:ICloudbaseRequest,runtime:string}, options: IOAuth2AuthProviderOptions = {}) {
|
|
169
|
-
super(config)
|
|
170
|
-
|
|
171
|
-
this.providerId = options.providerId
|
|
172
|
-
this.clientId = options.clientId || config.env
|
|
173
|
-
this.responseType = options.responseType || 'token'
|
|
174
|
-
this.scope = options.scope || ''
|
|
175
|
-
this.redirectUri = options.redirectUri || ''
|
|
176
|
-
this.syncProfile = options.syncProfile || false
|
|
177
|
-
this.forceDisableSignUp = options.forceDisableSignUp || false
|
|
178
|
-
|
|
179
|
-
const recvMessageFromPopup = this.recvMessageFromPopup.bind(this)
|
|
180
|
-
window.removeEventListener('message', recvMessageFromPopup)
|
|
181
|
-
window.addEventListener('message', recvMessageFromPopup, false)
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
public async signIn(){
|
|
185
|
-
return utils.printWarn(ERRORS.OPERATION_FAIL, 'API signIn has been deprecated, please use signInWithRedirect insteed')
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
@catchErrorsDecorator({
|
|
189
|
-
title: '跳转第三方登录平台失败',
|
|
190
|
-
messages: [
|
|
191
|
-
'请确认以下各项:',
|
|
192
|
-
' 1 - 调用 auth().oAuth2AuthProvider() 的参数是否正确',
|
|
193
|
-
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`
|
|
194
|
-
]
|
|
195
|
-
})
|
|
196
|
-
public async signInWithPopup(options: ISignInWithPopupOptions = {}) {
|
|
197
|
-
// if (this.checkLocalLoginState()) {
|
|
198
|
-
// throw new Error(`[${getSdkName()}][${ERRORS.UNKOWN_ERROR}]已登录,请先退出`)
|
|
199
|
-
// }
|
|
200
|
-
return this.jumpToProviderPage(options)
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
public async signInWithModal(elemId: string) {
|
|
204
|
-
|
|
205
|
-
const { uri: authorize_uri } = await this.fetchProviderRedirectURI()
|
|
206
|
-
const modal = document.getElementById(elemId)
|
|
207
|
-
modal.style.display = 'block'
|
|
208
|
-
const style = `
|
|
209
|
-
<style>
|
|
210
|
-
/* The Modal (background) */
|
|
211
|
-
.modal {
|
|
212
|
-
display: none; /* Hidden by default */
|
|
213
|
-
position: fixed; /* Stay in place */
|
|
214
|
-
z-index: 1; /* Sit on top */
|
|
215
|
-
padding-top: 100px; /* Location of the box */
|
|
216
|
-
left: 0;
|
|
217
|
-
top: 0;
|
|
218
|
-
width: 100%; /* Full width */
|
|
219
|
-
height: 100%; /* Full height */
|
|
220
|
-
overflow: auto; /* Enable scroll if needed */
|
|
221
|
-
background-color: rgb(0,0,0); /* Fallback color */
|
|
222
|
-
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/* Modal Content */
|
|
226
|
-
.modal-content {
|
|
227
|
-
background-color: #fefefe;
|
|
228
|
-
margin: auto;
|
|
229
|
-
padding: 20px;
|
|
230
|
-
border: 1px solid #888;
|
|
231
|
-
/* width: 80%; */
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/* The Close Button */
|
|
235
|
-
.close {
|
|
236
|
-
color: #aaaaaa;
|
|
237
|
-
float: right;
|
|
238
|
-
font-size: 28px;
|
|
239
|
-
font-weight: bold;
|
|
240
|
-
}
|
|
241
|
-
.close:hover,
|
|
242
|
-
.close:focus {
|
|
243
|
-
color: #000;
|
|
244
|
-
text-decoration: none;
|
|
245
|
-
cursor: pointer;
|
|
246
|
-
}
|
|
247
|
-
</style>
|
|
248
|
-
`
|
|
249
|
-
const html = `
|
|
250
|
-
<div class="modal-content">
|
|
251
|
-
<span class="close">×</span>
|
|
252
|
-
<iframe id="loginIframe" src="${authorize_uri}" title="iframe Example 1" width="400" height="300"></iframe>
|
|
253
|
-
</div>
|
|
254
|
-
`
|
|
255
|
-
const script = `
|
|
256
|
-
<script>
|
|
257
|
-
// Get the <span> element that closes the modal
|
|
258
|
-
var span = document.getElementsByClassName("close")[0];
|
|
259
|
-
|
|
260
|
-
// When the user clicks on <span> (x), close the modal
|
|
261
|
-
span.onclick = function() {
|
|
262
|
-
modal.style.display = "none";
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// When the user clicks anywhere outside of the modal, close it
|
|
266
|
-
window.onclick = function(event) {
|
|
267
|
-
if (event.target == modal) {
|
|
268
|
-
modal.style.display = "none";
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const loginIframe = document.getElementById("loginIframe")
|
|
273
|
-
</script>
|
|
274
|
-
`
|
|
275
|
-
modal.innerHTML = `
|
|
276
|
-
${html}
|
|
277
|
-
${style}
|
|
278
|
-
${script}
|
|
279
|
-
`
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
private async jumpToProviderPage(options: ISignInWithPopupOptions = {}): Promise<void> {
|
|
283
|
-
try {
|
|
284
|
-
const { uri: authorize_uri } = await this.fetchProviderRedirectURI()
|
|
285
|
-
const popup = options.popup || {}
|
|
286
|
-
const popupWindowTarget = popup.target || '_blank'
|
|
287
|
-
const popupWindowFeatures = popup.features || 'toolbar=no, menubar=no, width=600, height=700, top=100, left=100'
|
|
288
|
-
// console.log('jumpToProviderPage: ', authorize_uri, this.popupWindowRef)
|
|
289
|
-
let popupWindowRef = this.popupWindowRef
|
|
290
|
-
if (popupWindowRef === null || popupWindowRef.closed) {
|
|
291
|
-
popupWindowRef = window.open(authorize_uri, popupWindowTarget, popupWindowFeatures)
|
|
292
|
-
} else if (this.popupWindowUrl !== authorize_uri) {
|
|
293
|
-
if (popupWindowRef && !popupWindowRef.closed) {
|
|
294
|
-
popupWindowRef.close()
|
|
295
|
-
}
|
|
296
|
-
popupWindowRef = window.open(authorize_uri, popupWindowTarget, popupWindowFeatures)
|
|
297
|
-
} else {
|
|
298
|
-
// popupWindowRef.focus()
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
if (!popupWindowRef) {
|
|
302
|
-
return utils.printWarn(ERRORS.OPERATION_FAIL, `打开第三方登录授权失败,可能是禁用了浏览器弹窗,uri: ${authorize_uri}`)
|
|
303
|
-
}
|
|
304
|
-
this.popupWindowUrl = authorize_uri
|
|
305
|
-
this.popupWindowRef = popupWindowRef
|
|
306
|
-
this.popupWindowRef.focus()
|
|
307
|
-
} catch(e) {
|
|
308
|
-
// DOMException: Blocked a frame with origin "" from accessing a cross-origin frame.
|
|
309
|
-
if (this.popupWindowRef && !this.popupWindowRef.closed) {
|
|
310
|
-
this.popupWindowRef.close()
|
|
311
|
-
}
|
|
312
|
-
throw new Error(`[${getSdkName()}][${ERRORS.UNKOWN_ERROR}]${e}`)
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// 在新标签页 post message 进行测试,或取消注释进行测试
|
|
316
|
-
// window.opener.postMessage
|
|
317
|
-
// this.popupWindowRef.postMessage({
|
|
318
|
-
// source: 'cloudbase-login-redirect',
|
|
319
|
-
// callbackInfo: {
|
|
320
|
-
// state: 'eyJ0IjoxNjI3ODI4MzA2MjQzLCJwcm92aWRlcl9pZCI6Imdvb2dsZSIsImNsaWVudF9pZCI6InByb2R1Y3Rpb24tZnY5NzkiLCJyb3V0ZUtleSI6IiJ9',
|
|
321
|
-
// access_token: 'ya29.a0ARrdaM_JF-7l1aNkssC-jRYIDEoEyU2Rngkjoy0s9lHAAJp56yuxEyoUa8saDhR1S-04xtraEmDc0QSokyBOSVpKIE5zP0skeMWZuZinwmKhbsQTZfrCGJJGQM8n72HEhaxqK17k-gBd2MN0bWf9i-dlHnJECQ',
|
|
322
|
-
// token_type: 'Bearer',
|
|
323
|
-
// expires_in: '3598',
|
|
324
|
-
// scope: 'email%20profile%20openid%20https://www.googleapis.com/auth/userinfo.profile%20https://www.googleapis.com/auth/userinfo.email',
|
|
325
|
-
// authuser: '0',
|
|
326
|
-
// prompt: 'none'
|
|
327
|
-
// }
|
|
328
|
-
// }, 'http:///')
|
|
329
|
-
|
|
330
|
-
// function postMessageToOpener() {
|
|
331
|
-
// // 需要支持不同的参数形式
|
|
332
|
-
// if (window.opener) {
|
|
333
|
-
// // window.opener.postMessage({
|
|
334
|
-
// // source: 'cloudbase-login-redirect',
|
|
335
|
-
// // redirectUri: '',
|
|
336
|
-
// // callbackInfo: {
|
|
337
|
-
// // state: 'eyJ0IjoxNjI3NjMwNTY4NjkzLCJwcm92aWRlcl9pZCI6Imdvb2dsZSIsImNsaWVudF9pZCI6InByb2R1Y3Rpb24tZnY5NzkifQ==',
|
|
338
|
-
// // access_token: 'ya29.a0ARrdaM-hLc_CAGF26xMjTzdlAloRs8WihWFVy6GRDGv1DMYZbG0k1xI3dKgu3E42Gi6P1D1V6dtz-XBShjDou2MRWNaPNZ_SNC_idRTIqTCxU1f7xU-FKfmS8A0AZZDk8-h7a3VYsh12Eei1j2UNwuDGKUuOPw',
|
|
339
|
-
// // token_type: 'Bearer',
|
|
340
|
-
// // expires_in: '3599',
|
|
341
|
-
// // scope: 'email%20profile%20openid%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile',
|
|
342
|
-
// // authuser: '0',
|
|
343
|
-
// // prompt: 'none'
|
|
344
|
-
// // }
|
|
345
|
-
// // }, 'http:///')
|
|
346
|
-
// const params = window.location.search
|
|
347
|
-
// window.opener.postMessage(params, '')
|
|
348
|
-
// window.close()
|
|
349
|
-
// }
|
|
350
|
-
// }
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* recvMessageFromPopup 接收回调页面登录消息
|
|
355
|
-
* @param event
|
|
356
|
-
* @returns
|
|
357
|
-
*/
|
|
358
|
-
private recvMessageFromPopup(event: MessageEvent) {
|
|
359
|
-
// console.log('recv event:', event)
|
|
360
|
-
// origin: "http:///"
|
|
361
|
-
if (!event.isTrusted) {
|
|
362
|
-
// console.log('!event.isTrusted')
|
|
363
|
-
return
|
|
364
|
-
}
|
|
365
|
-
// console.log('this.popupWindowRef === event.source', this.popupWindowRef === event.source)
|
|
366
|
-
if (this.popupWindowRef === event.source && event.data.source === 'cloudbase-login-redirect') {
|
|
367
|
-
// console.log('recv cloudbase-login-redirect event', event.data)
|
|
368
|
-
const data: IPopupWindowAuthRedirectMessage = event.data
|
|
369
|
-
this.continueSignIn(data.callbackInfo)
|
|
370
|
-
if (!this.popupWindowRef.closed) {
|
|
371
|
-
this.popupWindowRef.close()
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
/**
|
|
377
|
-
* continueSignIn 继续登录
|
|
378
|
-
* @param callbackInfo
|
|
379
|
-
* @returns
|
|
380
|
-
*/
|
|
381
|
-
async continueSignIn(callbackInfo?: IPrividerCallbackInfo): Promise<LoginState> {
|
|
382
|
-
// 这里支持在回调页面调用该函数完成登录
|
|
383
|
-
callbackInfo = callbackInfo || this.getAuthPrividerCallbackInfoFromUrl()
|
|
384
|
-
const token = await this.signInWithProvider(callbackInfo)
|
|
385
|
-
const { accessTokenKey, accessTokenExpireKey, refreshTokenKey } = this._cache.keys
|
|
386
|
-
const { refresh_token: refreshToken, access_token: accessToken, expires_in: accessTokenExpire } = token
|
|
387
|
-
|
|
388
|
-
if (!accessToken || !accessTokenExpire) {
|
|
389
|
-
throw new Error(JSON.stringify({
|
|
390
|
-
code: 'SignFailure'
|
|
391
|
-
}))
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
await Promise.all([
|
|
395
|
-
this._cache.setStoreAsync(refreshTokenKey, refreshToken),
|
|
396
|
-
this._cache.setStoreAsync(accessTokenKey, accessToken),
|
|
397
|
-
this._cache.setStoreAsync(accessTokenExpireKey, accessTokenExpire * 1000 + Date.now())
|
|
398
|
-
])
|
|
399
|
-
eventBus.fire(EVENTS.LOGIN_STATE_CHANGED)
|
|
400
|
-
eventBus.fire(EVENTS.LOGIN_TYPE_CHANGED, {
|
|
401
|
-
env: this._config.env,
|
|
402
|
-
loginType: `${OAUTH2_LOGINTYPE_PREFIX}.${this.providerId}`,
|
|
403
|
-
persistence: this._config.persistence
|
|
404
|
-
})
|
|
405
|
-
|
|
406
|
-
const loginState = new LoginState({
|
|
407
|
-
envId: this._config.env,
|
|
408
|
-
cache: this._cache,
|
|
409
|
-
request: this._request
|
|
410
|
-
})
|
|
411
|
-
|
|
412
|
-
await loginState.checkLocalStateAsync()
|
|
413
|
-
|
|
414
|
-
// const userInfo = await this.refreshUserInfo()
|
|
415
|
-
|
|
416
|
-
return loginState
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
private getAuthPrividerCallbackInfoFromUrl(): IPrividerCallbackInfo {
|
|
420
|
-
// TODO: 支持 Query & Hash
|
|
421
|
-
// 直接从 URL 上取回调信息
|
|
422
|
-
// {
|
|
423
|
-
// state: '_tstate.1627564561750',
|
|
424
|
-
// access_token: 'ya29.a0ARrdaM98yMpUhCJRq2lVezPtdhQHAWsvDzj5OiiI8WREawQjC9HUo7tKjusJR4z0OCD5435BtbqH-kTsLTB3nllfHL0GjqJN1N20_r8Qs2ckVwH7axCuokmw58A_d0SKVuqN-U-NR61QrIK6Hvl8WAM-jm22ew',
|
|
425
|
-
// token_type: 'Bearer',
|
|
426
|
-
// expires_in: 3599,
|
|
427
|
-
// scope: 'email%20profile%20openid%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile',
|
|
428
|
-
// authuser: '0',
|
|
429
|
-
// prompt: 'none'
|
|
430
|
-
// }
|
|
431
|
-
return qsParse(decodeURIComponent((new URL(window.location.href).hash).replace('#', ''))) as IPrividerCallbackInfo
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
private async fetchProviderRedirectURI(): Promise<IGenProviderRedirectURIResponse> {
|
|
435
|
-
const {
|
|
436
|
-
response_type,
|
|
437
|
-
provider_id,
|
|
438
|
-
client_id,
|
|
439
|
-
scope,
|
|
440
|
-
redirect_uri,
|
|
441
|
-
state,
|
|
442
|
-
// other_params
|
|
443
|
-
}: IGenProviderRedirectURIRequest = {
|
|
444
|
-
response_type: this.responseType,
|
|
445
|
-
provider_id: this.providerId,
|
|
446
|
-
client_id: this.clientId,
|
|
447
|
-
scope: this.scope,
|
|
448
|
-
redirect_uri: this.redirectUri,
|
|
449
|
-
state: btoa(JSON.stringify({
|
|
450
|
-
t: Date.now(),
|
|
451
|
-
provider_id: this.providerId,
|
|
452
|
-
client_id: this.clientId,
|
|
453
|
-
// 登录成功之后路由的页面地址
|
|
454
|
-
routeKey: ''
|
|
455
|
-
})),
|
|
456
|
-
// other_params: utils.toQueryString({ a: 1 })
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
const qs = utils.toQueryString({
|
|
460
|
-
response_type,
|
|
461
|
-
provider_id,
|
|
462
|
-
client_id,
|
|
463
|
-
scope,
|
|
464
|
-
redirect_uri,
|
|
465
|
-
state,
|
|
466
|
-
// other_params
|
|
467
|
-
})
|
|
468
|
-
const resp = await this.fetch(`${kPaths.prividerUri}?${qs}`, {
|
|
469
|
-
method: 'GET'
|
|
470
|
-
})
|
|
471
|
-
// {
|
|
472
|
-
// uri: 'https://accounts.google.com/o/oauth2/v2/auth?client_id=686970215944-gun1neofjhtjt7gmta2qfth6f82sj011.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fproduction-fv979-1258964769.ap-shanghai.app.tcloudbase.com&response_type=token&scope=openid+email+profile&state=_tstate.1627545941923',
|
|
473
|
-
// signout_uri: ''
|
|
474
|
-
// }
|
|
475
|
-
return resp.json()
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
private async fetchProviderToken(callbackInfo: IPrividerCallbackInfo): Promise<IGrantProviderTokenResponse> {
|
|
479
|
-
// const state = atob(JSON.stringify(callbackInfo.state))
|
|
480
|
-
const body: IGrantProviderTokenRequest = {
|
|
481
|
-
provider_id: this.providerId,
|
|
482
|
-
client_id: this.clientId,
|
|
483
|
-
provider_redirect_uri: callbackInfo.href
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
if (callbackInfo.code) {
|
|
487
|
-
body.provider_code = callbackInfo.code
|
|
488
|
-
}
|
|
489
|
-
else if (callbackInfo.access_token) {
|
|
490
|
-
body.provider_access_token = callbackInfo.access_token
|
|
491
|
-
}
|
|
492
|
-
else if (callbackInfo.id_token) {
|
|
493
|
-
body.provider_id_token = callbackInfo.id_token
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
const resp = await this.fetch(kPaths.prividerToken, {
|
|
497
|
-
method: 'POST',
|
|
498
|
-
headers: {
|
|
499
|
-
'Accept': 'application/json',
|
|
500
|
-
'Content-Type': 'application/json'
|
|
501
|
-
},
|
|
502
|
-
body: JSON.stringify(body)
|
|
503
|
-
})
|
|
504
|
-
// {
|
|
505
|
-
// "provider_token": "eyJhbGciOiJB6AS8......HB4-v1P1j-zwqiQ",
|
|
506
|
-
// "expires_in": 1200,
|
|
507
|
-
// "provider_profile": {
|
|
508
|
-
// "provider_id": "google",
|
|
509
|
-
// "sub": "101963751496807079381",
|
|
510
|
-
// "name": "",
|
|
511
|
-
// "picture": "",
|
|
512
|
-
// "email": "",
|
|
513
|
-
// "locale": "zh-cn"
|
|
514
|
-
// }
|
|
515
|
-
// }
|
|
516
|
-
return resp.json()
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
private async signInWithProvider(callbackInfo: IPrividerCallbackInfo): Promise<IToken> {
|
|
520
|
-
const token = await this.fetchProviderToken(callbackInfo)
|
|
521
|
-
const body: ISignInWithProviderRequest = {
|
|
522
|
-
client_id: this.clientId,
|
|
523
|
-
provider_token: token.provider_token,
|
|
524
|
-
sync_profile: this.syncProfile,
|
|
525
|
-
force_disable_sign_up: this.forceDisableSignUp
|
|
526
|
-
}
|
|
527
|
-
const resp = await this.fetch(kPaths.signinWithProvider, {
|
|
528
|
-
method: 'POST',
|
|
529
|
-
headers: {
|
|
530
|
-
'Accept': 'application/json',
|
|
531
|
-
'Content-Type': 'application/json'
|
|
532
|
-
},
|
|
533
|
-
body: JSON.stringify(body)
|
|
534
|
-
})
|
|
535
|
-
return resp.json()
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
async refreshUserInfo() {
|
|
539
|
-
const { accessToken } = (await this._request.getAccessToken())
|
|
540
|
-
const authorization = `Bearer ${accessToken}`
|
|
541
|
-
const resp = await this.fetch(kPaths.me, {
|
|
542
|
-
method: 'GET',
|
|
543
|
-
headers: {
|
|
544
|
-
'Accept': 'application/json',
|
|
545
|
-
'Content-Type': 'application/json',
|
|
546
|
-
'Authorization': authorization
|
|
547
|
-
}
|
|
548
|
-
})
|
|
549
|
-
// {
|
|
550
|
-
// "sub": "7aab4ba9053e4402a3d42b61cc257c11",
|
|
551
|
-
// "name": "",
|
|
552
|
-
// "picture": "https://lh3.googleusercontent.com/a-/AOh14Gg4sDe14SC5WNs85Ko2nfBlXvldYVgbSYbvIrka=s96-c",
|
|
553
|
-
// "email": "",
|
|
554
|
-
// "providers": [
|
|
555
|
-
// {
|
|
556
|
-
// "id": "google",
|
|
557
|
-
// "provider_user_id": "101963751496807079381",
|
|
558
|
-
// "name": ""
|
|
559
|
-
// }
|
|
560
|
-
// ],
|
|
561
|
-
// "status": "ACTIVE",
|
|
562
|
-
// "created_at": "2021-07-28T06:31:36.983Z",
|
|
563
|
-
// "password_updated_at": "2021-07-28T06:31:36.983Z"
|
|
564
|
-
// }
|
|
565
|
-
return resp.json()
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
private async fetch(urlOrPath: string, init?: RequestInit) {
|
|
569
|
-
const resp = await this._request.fetch(urlOrPath, init)
|
|
570
|
-
|
|
571
|
-
const seqIdFromHeader = resp.headers.get('SeqId') || resp.headers.get('RequestId')
|
|
572
|
-
if (resp.status >= 400 && resp.status < 500) {
|
|
573
|
-
const body: IAuthServerRespError = await resp.json()
|
|
574
|
-
const seqId = body.request_id || seqIdFromHeader
|
|
575
|
-
throw new Error(`[${getSdkName()}][OAuth2AuthProvider][status:${resp.status}][${body.error}(${body.error_code})] ${body.error_description} (${seqId})`)
|
|
576
|
-
}
|
|
577
|
-
else if (resp.status >= 500) {
|
|
578
|
-
const body: IAuthServerRespError = await resp.json()
|
|
579
|
-
const seqId = body.request_id || seqIdFromHeader
|
|
580
|
-
throw new Error(`[${getSdkName()}][OAuth2AuthProvider][status:${resp.status}][${body.error}(${body.error_code})] ${body.error_description} (${seqId})`)
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
return resp
|
|
584
|
-
}
|
|
585
|
-
}
|