@things-factory/auth-base 8.0.0-beta.1 → 8.0.0-beta.4
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 +6 -6
- package/client/actions/auth.ts +0 -24
- package/client/auth.ts +0 -272
- package/client/bootstrap.ts +0 -47
- package/client/directive/privileged.ts +0 -28
- package/client/index.ts +0 -4
- package/client/profiled.ts +0 -83
- package/client/reducers/auth.ts +0 -31
- package/client/verify-webauthn.ts +0 -86
- package/server/constants/error-code.ts +0 -22
- package/server/constants/error-message.ts +0 -0
- package/server/constants/max-age.ts +0 -1
- package/server/controllers/auth.ts +0 -5
- package/server/controllers/change-pwd.ts +0 -100
- package/server/controllers/checkin.ts +0 -21
- package/server/controllers/delete-user.ts +0 -71
- package/server/controllers/invitation.ts +0 -163
- package/server/controllers/profile.ts +0 -55
- package/server/controllers/reset-password.ts +0 -126
- package/server/controllers/signin.ts +0 -98
- package/server/controllers/signup.ts +0 -72
- package/server/controllers/unlock-user.ts +0 -62
- package/server/controllers/utils/make-invitation-token.ts +0 -5
- package/server/controllers/utils/make-verification-token.ts +0 -4
- package/server/controllers/utils/password-rule.ts +0 -120
- package/server/controllers/utils/save-invitation-token.ts +0 -10
- package/server/controllers/utils/save-verification-token.ts +0 -12
- package/server/controllers/verification.ts +0 -84
- package/server/errors/auth-error.ts +0 -24
- package/server/errors/index.ts +0 -2
- package/server/errors/user-domain-not-match-error.ts +0 -29
- package/server/index.ts +0 -37
- package/server/middlewares/authenticate-401-middleware.ts +0 -114
- package/server/middlewares/domain-authenticate-middleware.ts +0 -78
- package/server/middlewares/graphql-authenticate-middleware.ts +0 -13
- package/server/middlewares/index.ts +0 -67
- package/server/middlewares/jwt-authenticate-middleware.ts +0 -84
- package/server/middlewares/signin-middleware.ts +0 -55
- package/server/middlewares/webauthn-middleware.ts +0 -126
- package/server/migrations/1548206416130-SeedUser.ts +0 -60
- package/server/migrations/1566805283882-SeedPrivilege.ts +0 -28
- package/server/migrations/index.ts +0 -9
- package/server/router/auth-checkin-router.ts +0 -113
- package/server/router/auth-private-process-router.ts +0 -114
- package/server/router/auth-public-process-router.ts +0 -314
- package/server/router/auth-signin-router.ts +0 -55
- package/server/router/auth-signup-router.ts +0 -95
- package/server/router/index.ts +0 -9
- package/server/router/oauth2/index.ts +0 -2
- package/server/router/oauth2/oauth2-authorize-router.ts +0 -81
- package/server/router/oauth2/oauth2-router.ts +0 -165
- package/server/router/oauth2/oauth2-server.ts +0 -262
- package/server/router/oauth2/passport-oauth2-client-password.ts +0 -87
- package/server/router/oauth2/passport-refresh-token.ts +0 -87
- package/server/router/path-base-domain-router.ts +0 -8
- package/server/router/site-root-router.ts +0 -48
- package/server/router/webauthn-router.ts +0 -149
- package/server/routes.ts +0 -80
- package/server/service/app-binding/app-binding-mutation.ts +0 -22
- package/server/service/app-binding/app-binding-query.ts +0 -92
- package/server/service/app-binding/app-binding-types.ts +0 -11
- package/server/service/app-binding/app-binding.ts +0 -17
- package/server/service/app-binding/index.ts +0 -4
- package/server/service/appliance/appliance-mutation.ts +0 -113
- package/server/service/appliance/appliance-query.ts +0 -76
- package/server/service/appliance/appliance-types.ts +0 -56
- package/server/service/appliance/appliance.ts +0 -133
- package/server/service/appliance/index.ts +0 -6
- package/server/service/application/application-mutation.ts +0 -104
- package/server/service/application/application-query.ts +0 -98
- package/server/service/application/application-types.ts +0 -76
- package/server/service/application/application.ts +0 -216
- package/server/service/application/index.ts +0 -6
- package/server/service/auth-provider/auth-provider-mutation.ts +0 -159
- package/server/service/auth-provider/auth-provider-parameter-spec.ts +0 -24
- package/server/service/auth-provider/auth-provider-query.ts +0 -88
- package/server/service/auth-provider/auth-provider-type.ts +0 -67
- package/server/service/auth-provider/auth-provider.ts +0 -155
- package/server/service/auth-provider/index.ts +0 -7
- package/server/service/domain-generator/domain-generator-mutation.ts +0 -117
- package/server/service/domain-generator/domain-generator-types.ts +0 -46
- package/server/service/domain-generator/index.ts +0 -3
- package/server/service/granted-role/granted-role-mutation.ts +0 -156
- package/server/service/granted-role/granted-role-query.ts +0 -60
- package/server/service/granted-role/granted-role.ts +0 -27
- package/server/service/granted-role/index.ts +0 -6
- package/server/service/index.ts +0 -90
- package/server/service/invitation/index.ts +0 -6
- package/server/service/invitation/invitation-mutation.ts +0 -78
- package/server/service/invitation/invitation-query.ts +0 -33
- package/server/service/invitation/invitation-types.ts +0 -11
- package/server/service/invitation/invitation.ts +0 -63
- package/server/service/login-history/index.ts +0 -5
- package/server/service/login-history/login-history-query.ts +0 -51
- package/server/service/login-history/login-history-type.ts +0 -12
- package/server/service/login-history/login-history.ts +0 -45
- package/server/service/partner/index.ts +0 -6
- package/server/service/partner/partner-mutation.ts +0 -61
- package/server/service/partner/partner-query.ts +0 -102
- package/server/service/partner/partner-types.ts +0 -11
- package/server/service/partner/partner.ts +0 -57
- package/server/service/password-history/index.ts +0 -3
- package/server/service/password-history/password-history.ts +0 -16
- package/server/service/privilege/index.ts +0 -6
- package/server/service/privilege/privilege-directive.ts +0 -77
- package/server/service/privilege/privilege-mutation.ts +0 -92
- package/server/service/privilege/privilege-query.ts +0 -94
- package/server/service/privilege/privilege-types.ts +0 -60
- package/server/service/privilege/privilege.ts +0 -102
- package/server/service/role/index.ts +0 -6
- package/server/service/role/role-mutation.ts +0 -109
- package/server/service/role/role-query.ts +0 -155
- package/server/service/role/role-types.ts +0 -81
- package/server/service/role/role.ts +0 -72
- package/server/service/user/domain-query.ts +0 -24
- package/server/service/user/index.ts +0 -7
- package/server/service/user/user-mutation.ts +0 -482
- package/server/service/user/user-query.ts +0 -145
- package/server/service/user/user-types.ts +0 -100
- package/server/service/user/user.ts +0 -381
- package/server/service/users-auth-providers/index.ts +0 -5
- package/server/service/users-auth-providers/users-auth-providers.ts +0 -71
- package/server/service/verification-token/index.ts +0 -3
- package/server/service/verification-token/verification-token.ts +0 -60
- package/server/service/web-auth-credential/index.ts +0 -3
- package/server/service/web-auth-credential/web-auth-credential.ts +0 -67
- package/server/templates/account-unlock-email.ts +0 -65
- package/server/templates/invitation-email.ts +0 -66
- package/server/templates/reset-password-email.ts +0 -65
- package/server/templates/verification-email.ts +0 -66
- package/server/types.ts +0 -21
- package/server/utils/accepts.ts +0 -11
- package/server/utils/access-token-cookie.ts +0 -61
- package/server/utils/check-permission.ts +0 -52
- package/server/utils/check-user-belongs-domain.ts +0 -19
- package/server/utils/check-user-has-role.ts +0 -29
- package/server/utils/encrypt-state.ts +0 -22
- package/server/utils/get-aes-256-key.ts +0 -13
- package/server/utils/get-domain-from-hostname.ts +0 -7
- package/server/utils/get-domain-users.ts +0 -38
- package/server/utils/get-secret.ts +0 -13
- package/server/utils/get-user-domains.ts +0 -112
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@things-factory/auth-base",
|
3
|
-
"version": "8.0.0-beta.
|
3
|
+
"version": "8.0.0-beta.4",
|
4
4
|
"main": "dist-server/index.js",
|
5
5
|
"browser": "dist-client/index.js",
|
6
6
|
"things-factory": true,
|
@@ -32,10 +32,10 @@
|
|
32
32
|
"dependencies": {
|
33
33
|
"@simplewebauthn/browser": "^10.0.0",
|
34
34
|
"@simplewebauthn/server": "^10.0.0",
|
35
|
-
"@things-factory/email-base": "^8.0.0-beta.
|
36
|
-
"@things-factory/env": "^8.0.0-beta.
|
37
|
-
"@things-factory/shell": "^8.0.0-beta.
|
38
|
-
"@things-factory/utils": "^8.0.0-beta.
|
35
|
+
"@things-factory/email-base": "^8.0.0-beta.4",
|
36
|
+
"@things-factory/env": "^8.0.0-beta.4",
|
37
|
+
"@things-factory/shell": "^8.0.0-beta.4",
|
38
|
+
"@things-factory/utils": "^8.0.0-beta.4",
|
39
39
|
"@types/webappsec-credential-management": "^0.6.8",
|
40
40
|
"jsonwebtoken": "^9.0.0",
|
41
41
|
"koa-passport": "^6.0.0",
|
@@ -46,5 +46,5 @@
|
|
46
46
|
"passport-jwt": "^4.0.0",
|
47
47
|
"passport-local": "^1.0.0"
|
48
48
|
},
|
49
|
-
"gitHead": "
|
49
|
+
"gitHead": "d83d12ed4ba07177dff1dac26e37be347d156b43"
|
50
50
|
}
|
package/client/actions/auth.ts
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
import { Action, ThunkAction } from '@reduxjs/toolkit'
|
2
|
-
|
3
|
-
export const SET_PROFILE = 'SET-PROFILE'
|
4
|
-
export const SET_AUTH = 'SET-AUTH'
|
5
|
-
|
6
|
-
type RootState = any
|
7
|
-
|
8
|
-
export const updateUser =
|
9
|
-
(user: any): ThunkAction<void, RootState, unknown, Action<any>> =>
|
10
|
-
(dispatch, getState) => {
|
11
|
-
dispatch({
|
12
|
-
type: SET_PROFILE,
|
13
|
-
user
|
14
|
-
})
|
15
|
-
}
|
16
|
-
|
17
|
-
export const updateAuthenticated =
|
18
|
-
(auth: { authenticated: boolean }): ThunkAction<void, RootState, unknown, Action<any>> =>
|
19
|
-
(dispatch, getState) => {
|
20
|
-
dispatch({
|
21
|
-
type: SET_AUTH,
|
22
|
-
auth
|
23
|
-
})
|
24
|
-
}
|
package/client/auth.ts
DELETED
@@ -1,272 +0,0 @@
|
|
1
|
-
/* [ AUTH PATH ]
|
2
|
-
signinPath = '/auth/signin'
|
3
|
-
signoutPath = '/auth/signout'
|
4
|
-
profilePath = '/auth/profile'
|
5
|
-
updateProfilePath = '/auth/update-profile'
|
6
|
-
changepassPath = '/auth/change-pass'
|
7
|
-
deleteUserPath = '/auth/delete-user'
|
8
|
-
*/
|
9
|
-
|
10
|
-
const HEADER_JSON = {
|
11
|
-
'Content-Type': 'application/json',
|
12
|
-
Accept: 'application/json'
|
13
|
-
}
|
14
|
-
type AuthEventName = 'profile' | 'signin' | 'signout' | 'presignout' | 'passwordchange' | 'error'
|
15
|
-
type AuthEventHandler = (e?: {
|
16
|
-
accessToken?: string
|
17
|
-
credential?: string
|
18
|
-
domains: any[]
|
19
|
-
domain: any
|
20
|
-
languages?: { code: string; display: string }[]
|
21
|
-
}) => void
|
22
|
-
type AuthErrorHandler = (err: any) => void
|
23
|
-
|
24
|
-
class ClientAuth {
|
25
|
-
private listeners: {
|
26
|
-
profile: AuthEventHandler[]
|
27
|
-
signout: AuthEventHandler[]
|
28
|
-
signin: AuthEventHandler[]
|
29
|
-
presignout: AuthEventHandler[]
|
30
|
-
passwordchange: AuthEventHandler[]
|
31
|
-
error: AuthErrorHandler[]
|
32
|
-
} = {
|
33
|
-
profile: [],
|
34
|
-
signout: [],
|
35
|
-
signin: [],
|
36
|
-
presignout: [],
|
37
|
-
passwordchange: [],
|
38
|
-
error: []
|
39
|
-
}
|
40
|
-
|
41
|
-
private authRequiredEventListener = this.onAuthRequired.bind(this)
|
42
|
-
private activateRequiredEventListener = this.onActivateRequired.bind(this)
|
43
|
-
|
44
|
-
private _credential: any
|
45
|
-
private accessToken?: string
|
46
|
-
private domains: any[] = []
|
47
|
-
private domain: any
|
48
|
-
private languages: { code: string; display: string }[] = []
|
49
|
-
|
50
|
-
constructor() {
|
51
|
-
document.addEventListener('auth-required', this.authRequiredEventListener)
|
52
|
-
document.addEventListener('activate-required', this.activateRequiredEventListener)
|
53
|
-
}
|
54
|
-
|
55
|
-
on(event: AuthEventName, handler: AuthEventHandler | AuthErrorHandler) {
|
56
|
-
var listeners = this.listeners[event]
|
57
|
-
if (listeners) {
|
58
|
-
listeners.push(handler)
|
59
|
-
} else {
|
60
|
-
console.log('unknown event', event)
|
61
|
-
}
|
62
|
-
|
63
|
-
if (event == 'profile' && this._credential) {
|
64
|
-
/*
|
65
|
-
특별히 event 가 profile 인 경우에는 이미 fetch된 credential이 있다면, 콜백을 해준다.
|
66
|
-
시스템 bootstrap에서 profile 이벤트가 사용되는 경우가 많은데, profile도 매우 초기에 fetch 되므로 레이스컨디션이 발생할 수 있기 때문에, 확실하게 event 콜백을 보장하기 위해서이다.
|
67
|
-
*/
|
68
|
-
handler({ credential: this._credential, domains: this.domains, domain: this.domain, languages: this.languages })
|
69
|
-
}
|
70
|
-
}
|
71
|
-
|
72
|
-
off(event: AuthEventName, handler: AuthEventHandler | AuthErrorHandler) {
|
73
|
-
var listeners = this.listeners[event]
|
74
|
-
if (listeners) {
|
75
|
-
let idx = listeners.indexOf(handler)
|
76
|
-
idx >= 0 && listeners.splice(idx, 1)
|
77
|
-
} else {
|
78
|
-
console.log('unknown event', event)
|
79
|
-
}
|
80
|
-
}
|
81
|
-
|
82
|
-
dispose() {
|
83
|
-
document.removeEventListener('auth-required', this.authRequiredEventListener)
|
84
|
-
document.removeEventListener('activate-required', this.activateRequiredEventListener)
|
85
|
-
|
86
|
-
this.listeners = {
|
87
|
-
profile: [],
|
88
|
-
signin: [],
|
89
|
-
signout: [],
|
90
|
-
presignout: [],
|
91
|
-
passwordchange: [],
|
92
|
-
error: []
|
93
|
-
}
|
94
|
-
}
|
95
|
-
|
96
|
-
private onProfileFetched({ credential, accessToken, domains, domain, languages }) {
|
97
|
-
this._credential = credential
|
98
|
-
this.domains = domains
|
99
|
-
this.domain = domain
|
100
|
-
this.languages = languages
|
101
|
-
|
102
|
-
if (accessToken && !this.accessToken) {
|
103
|
-
/*
|
104
|
-
기존에 세션을 가지거나, 액세스토큰으로 인증된 경우,
|
105
|
-
이 경우는 signin 이벤트리스너들을 호출해서 authenticated 상태로 되도록 유도한다.
|
106
|
-
*/
|
107
|
-
this.accessToken = accessToken
|
108
|
-
this.listeners.signin.forEach(handler => handler({ accessToken, domains, domain, languages }))
|
109
|
-
}
|
110
|
-
accessToken && (this.accessToken = accessToken)
|
111
|
-
this.listeners.profile.forEach(handler => handler({ credential, domains, domain, languages }))
|
112
|
-
}
|
113
|
-
|
114
|
-
private async onPreSignout() {
|
115
|
-
for (let onpresignout of this.listeners.presignout) {
|
116
|
-
await onpresignout()
|
117
|
-
}
|
118
|
-
}
|
119
|
-
|
120
|
-
private onAuthError(error) {
|
121
|
-
/* signin, signup 과정에서 에러가 발생한 경우 */
|
122
|
-
this.listeners?.error.forEach(handler => handler(error))
|
123
|
-
}
|
124
|
-
|
125
|
-
private onPasswordChanged(result) {
|
126
|
-
//event is passwordchange, handler is result
|
127
|
-
this.listeners?.passwordchange.forEach(handler => handler(result))
|
128
|
-
}
|
129
|
-
|
130
|
-
private onAuthRequired(e) {
|
131
|
-
console.warn('authentication required')
|
132
|
-
let url = new URL(window.location.href)
|
133
|
-
url.pathname = '/auth/signin'
|
134
|
-
url.searchParams.append('redirect_to', window.location.href)
|
135
|
-
|
136
|
-
window.location.href = url.href
|
137
|
-
}
|
138
|
-
|
139
|
-
private onActivateRequired(e) {
|
140
|
-
console.warn('activate required')
|
141
|
-
var params = new URLSearchParams()
|
142
|
-
params.append('email', e.email)
|
143
|
-
|
144
|
-
window.location.replace(`/auth/activate?${params}`)
|
145
|
-
}
|
146
|
-
|
147
|
-
get credential() {
|
148
|
-
return this._credential
|
149
|
-
}
|
150
|
-
|
151
|
-
route(path, redirected) {
|
152
|
-
/* history에 남긴다. redirected된 상태임을 남긴다. */
|
153
|
-
const location = window.location
|
154
|
-
const origin = location.origin || location.protocol + '//' + location.host
|
155
|
-
const href = `${origin}${path}`
|
156
|
-
|
157
|
-
if (location.pathname === path) return
|
158
|
-
|
159
|
-
// popstate 이벤트가 history.back() 에서만 발생하므로
|
160
|
-
// 히스토리에 두번을 넣고 back()을 호출하는 편법을 사용함.
|
161
|
-
// forward history가 한번 남는 문제가 있으나 signin 프로세스 중에만 발생하므로 큰 문제는 아님.
|
162
|
-
// 이 로직은 login process가 어플리케이션 구조에 종속되는 것을 최소화하기 위함임.
|
163
|
-
// 예를 들면, redux 구조에 들어가지 않아도 로그인 프로세스가 동작하도록 한 것임.
|
164
|
-
window.history.pushState({ redirected }, '', href)
|
165
|
-
window.history.pushState({}, '', href)
|
166
|
-
|
167
|
-
window.history.back()
|
168
|
-
}
|
169
|
-
|
170
|
-
async updateProfile(formProps) {
|
171
|
-
const response = await fetch('/auth/update-profile', {
|
172
|
-
method: 'POST',
|
173
|
-
credentials: 'include',
|
174
|
-
headers: HEADER_JSON,
|
175
|
-
body: JSON.stringify(formProps)
|
176
|
-
})
|
177
|
-
|
178
|
-
const message = await response.text()
|
179
|
-
if (response.ok) {
|
180
|
-
return message
|
181
|
-
}
|
182
|
-
|
183
|
-
throw new Error(message)
|
184
|
-
}
|
185
|
-
|
186
|
-
async changePassword(formProps) {
|
187
|
-
try {
|
188
|
-
const response = await fetch('/auth/change-pass', {
|
189
|
-
method: 'POST',
|
190
|
-
credentials: 'include',
|
191
|
-
headers: HEADER_JSON,
|
192
|
-
body: JSON.stringify(formProps)
|
193
|
-
})
|
194
|
-
|
195
|
-
const message = await response.text()
|
196
|
-
if (response.ok) {
|
197
|
-
this.onPasswordChanged({ message })
|
198
|
-
} else {
|
199
|
-
this.onAuthError({ message })
|
200
|
-
}
|
201
|
-
} catch (e) {
|
202
|
-
this.onAuthError(e)
|
203
|
-
}
|
204
|
-
}
|
205
|
-
|
206
|
-
async deleteUser(params) {
|
207
|
-
const response = await fetch('/auth/delete-user', {
|
208
|
-
method: 'POST',
|
209
|
-
credentials: 'include',
|
210
|
-
headers: HEADER_JSON,
|
211
|
-
body: JSON.stringify(params)
|
212
|
-
})
|
213
|
-
|
214
|
-
const message = await response.text()
|
215
|
-
if (response.ok) {
|
216
|
-
return message
|
217
|
-
} else {
|
218
|
-
throw new Error(message)
|
219
|
-
}
|
220
|
-
}
|
221
|
-
|
222
|
-
async profile() {
|
223
|
-
if (sessionStorage.getItem('ThingsFactory-UseExternServer')) {
|
224
|
-
return
|
225
|
-
}
|
226
|
-
|
227
|
-
try {
|
228
|
-
var searchParams = new URLSearchParams(location.search)
|
229
|
-
var token = searchParams.get('token')
|
230
|
-
var headers = JSON.parse(JSON.stringify(HEADER_JSON))
|
231
|
-
|
232
|
-
if (token) {
|
233
|
-
headers.authorization = `Bearer ${token}`
|
234
|
-
}
|
235
|
-
|
236
|
-
const response = await fetch('/auth/profile', {
|
237
|
-
method: 'GET',
|
238
|
-
credentials: 'include',
|
239
|
-
headers
|
240
|
-
})
|
241
|
-
|
242
|
-
if (response.ok) {
|
243
|
-
if (response.redirected) {
|
244
|
-
location.href = response.url
|
245
|
-
return
|
246
|
-
}
|
247
|
-
|
248
|
-
const data = await response.json()
|
249
|
-
|
250
|
-
this.onProfileFetched({
|
251
|
-
credential: data.user,
|
252
|
-
accessToken: data.token,
|
253
|
-
domains: data.domains,
|
254
|
-
domain: data.domain,
|
255
|
-
languages: data.languages
|
256
|
-
})
|
257
|
-
|
258
|
-
return
|
259
|
-
}
|
260
|
-
} catch (e) {
|
261
|
-
this.onAuthError(e)
|
262
|
-
}
|
263
|
-
}
|
264
|
-
|
265
|
-
async signout() {
|
266
|
-
await this.onPreSignout()
|
267
|
-
|
268
|
-
window.location.href = '/auth/signout'
|
269
|
-
}
|
270
|
-
}
|
271
|
-
|
272
|
-
export const auth = new ClientAuth()
|
package/client/bootstrap.ts
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
import { store, updateDomains } from '@operato/shell'
|
2
|
-
|
3
|
-
import { updateAuthenticated, updateUser } from './actions/auth'
|
4
|
-
import { auth } from './auth'
|
5
|
-
import reducerAuth from './reducers/auth'
|
6
|
-
|
7
|
-
import './directive/privileged' /* directive 초기화를 보장하기 위해서 호출함. */
|
8
|
-
|
9
|
-
export default function bootstrap() {
|
10
|
-
store.addReducers({
|
11
|
-
auth: reducerAuth
|
12
|
-
})
|
13
|
-
|
14
|
-
auth.on('profile', ({ credential, domains, domain, languages }) => {
|
15
|
-
store.dispatch(
|
16
|
-
updateAuthenticated({
|
17
|
-
authenticated: true
|
18
|
-
}) as any
|
19
|
-
)
|
20
|
-
store.dispatch(updateUser(credential) as any)
|
21
|
-
store.dispatch(updateDomains(domains, domain) as any)
|
22
|
-
})
|
23
|
-
|
24
|
-
auth.on('passwordchange', result => {
|
25
|
-
let message = result.message
|
26
|
-
|
27
|
-
document.dispatchEvent(
|
28
|
-
new CustomEvent('notify', {
|
29
|
-
detail: {
|
30
|
-
level: result.error ? 'error' : 'info',
|
31
|
-
message
|
32
|
-
}
|
33
|
-
})
|
34
|
-
)
|
35
|
-
})
|
36
|
-
|
37
|
-
auth.on('error', ex => {
|
38
|
-
document.dispatchEvent(
|
39
|
-
new CustomEvent('notify', {
|
40
|
-
detail: {
|
41
|
-
level: 'error',
|
42
|
-
message: ex.message
|
43
|
-
}
|
44
|
-
})
|
45
|
-
)
|
46
|
-
})
|
47
|
-
}
|
@@ -1,28 +0,0 @@
|
|
1
|
-
import { nothing } from 'lit'
|
2
|
-
import { directive, AsyncDirective } from 'lit/async-directive.js'
|
3
|
-
import { hasPrivilege } from '../profiled'
|
4
|
-
|
5
|
-
class PrivilegedDirective extends AsyncDirective {
|
6
|
-
render(
|
7
|
-
privilege: {
|
8
|
-
privilege?: string
|
9
|
-
category?: string
|
10
|
-
domainOwnerGranted?: boolean
|
11
|
-
superUserGranted?: boolean
|
12
|
-
},
|
13
|
-
trueResult: any,
|
14
|
-
falseResult: any = nothing
|
15
|
-
) {
|
16
|
-
this.setValue(nothing)
|
17
|
-
|
18
|
-
hasPrivilege(privilege).then(result => {
|
19
|
-
if (result) {
|
20
|
-
this.setValue(trueResult)
|
21
|
-
} else {
|
22
|
-
this.setValue(falseResult)
|
23
|
-
}
|
24
|
-
})
|
25
|
-
}
|
26
|
-
}
|
27
|
-
|
28
|
-
export const privileged = directive(PrivilegedDirective)
|
package/client/index.ts
DELETED
package/client/profiled.ts
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
import { auth } from './auth'
|
2
|
-
|
3
|
-
var profileResolved = false
|
4
|
-
var user
|
5
|
-
var languages
|
6
|
-
var domain
|
7
|
-
var domains
|
8
|
-
|
9
|
-
const profileReady = new Promise<void>(resolve => {
|
10
|
-
auth.on('profile', (data: { credential; domains; domain; languages }) => {
|
11
|
-
profileResolved = true
|
12
|
-
|
13
|
-
user = data.credential
|
14
|
-
languages = data.languages
|
15
|
-
domain = data.domain
|
16
|
-
domains = data.domains
|
17
|
-
|
18
|
-
resolve()
|
19
|
-
})
|
20
|
-
})
|
21
|
-
|
22
|
-
export async function hasPrivilege({
|
23
|
-
privilege,
|
24
|
-
category,
|
25
|
-
domainOwnerGranted,
|
26
|
-
superUserGranted
|
27
|
-
}: {
|
28
|
-
privilege?: string
|
29
|
-
category?: string
|
30
|
-
domainOwnerGranted?: boolean
|
31
|
-
superUserGranted?: boolean
|
32
|
-
}) {
|
33
|
-
if (!profileResolved) {
|
34
|
-
await profileReady
|
35
|
-
}
|
36
|
-
|
37
|
-
const { privileges, owner, super: superUser, unsafeIP } = user
|
38
|
-
|
39
|
-
if (unsafeIP) {
|
40
|
-
if (privilege && category) {
|
41
|
-
// unsafeIP 상황에서는 ownership granted는 적용되지 않는다.
|
42
|
-
return (privileges || []).find(p => p.privilege == privilege && p.category == category)
|
43
|
-
}
|
44
|
-
|
45
|
-
// privileage, category가 설정되지 않은 경우에는 ownership granted가 설정되었다면 허가하지 않는다.
|
46
|
-
return !domainOwnerGranted && !superUserGranted
|
47
|
-
} else {
|
48
|
-
if (!privilege || !category) {
|
49
|
-
// privileage, category가 설정되지 않은 경우에는 ownership granted만을 적용한다.
|
50
|
-
return (domainOwnerGranted && owner) || (superUserGranted && superUser)
|
51
|
-
}
|
52
|
-
|
53
|
-
if ((domainOwnerGranted && owner) || (superUserGranted && superUser)) {
|
54
|
-
return true
|
55
|
-
}
|
56
|
-
|
57
|
-
return (privileges || []).find(p => p.privilege == privilege && p.category == category)
|
58
|
-
}
|
59
|
-
}
|
60
|
-
|
61
|
-
export async function getLanguages() {
|
62
|
-
if (!profileResolved) {
|
63
|
-
await profileReady
|
64
|
-
}
|
65
|
-
|
66
|
-
return languages
|
67
|
-
}
|
68
|
-
|
69
|
-
export async function getDomain() {
|
70
|
-
if (!profileResolved) {
|
71
|
-
await profileReady
|
72
|
-
}
|
73
|
-
|
74
|
-
return domain
|
75
|
-
}
|
76
|
-
|
77
|
-
export async function getDomains() {
|
78
|
-
if (!profileResolved) {
|
79
|
-
await profileReady
|
80
|
-
}
|
81
|
-
|
82
|
-
return domains
|
83
|
-
}
|
package/client/reducers/auth.ts
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
import { SET_AUTH, SET_PROFILE } from '../actions/auth'
|
2
|
-
|
3
|
-
const INITIAL_STATE = {
|
4
|
-
authenticated: false,
|
5
|
-
accessToken: '',
|
6
|
-
user: null
|
7
|
-
}
|
8
|
-
|
9
|
-
const auth = (state = INITIAL_STATE, action) => {
|
10
|
-
switch (action.type) {
|
11
|
-
case SET_AUTH:
|
12
|
-
let auth = action.auth
|
13
|
-
|
14
|
-
return {
|
15
|
-
...state,
|
16
|
-
authenticated: auth.authenticated,
|
17
|
-
accessToken: auth.accessToken
|
18
|
-
}
|
19
|
-
|
20
|
-
case SET_PROFILE:
|
21
|
-
return {
|
22
|
-
...state,
|
23
|
-
user: action.user
|
24
|
-
}
|
25
|
-
|
26
|
-
default:
|
27
|
-
return state
|
28
|
-
}
|
29
|
-
}
|
30
|
-
|
31
|
-
export default auth
|
@@ -1,86 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
// Usage example
|
3
|
-
async function performSensitiveAction() {
|
4
|
-
try {
|
5
|
-
const result = await verifyBiometric()
|
6
|
-
if (result.verified) {
|
7
|
-
console.log('Verification successful. Proceeding with sensitive action.')
|
8
|
-
// Perform the sensitive action here
|
9
|
-
} else if (result.needsRegistration) {
|
10
|
-
console.log('Biometric registration needed:', result.message)
|
11
|
-
// Redirect user to biometric registration page or show registration prompt
|
12
|
-
} else {
|
13
|
-
console.log('Verification failed:', result.message)
|
14
|
-
// Handle the failure (e.g., show an error message to the user)
|
15
|
-
}
|
16
|
-
} catch (error) {
|
17
|
-
console.error('Error during biometric verification:', error)
|
18
|
-
// Handle any unexpected errors
|
19
|
-
}
|
20
|
-
}
|
21
|
-
*/
|
22
|
-
|
23
|
-
import { startAuthentication } from '@simplewebauthn/browser'
|
24
|
-
|
25
|
-
interface BiometricVerificationResult {
|
26
|
-
verified: boolean
|
27
|
-
message: string
|
28
|
-
needsRegistration?: boolean
|
29
|
-
}
|
30
|
-
|
31
|
-
/**
|
32
|
-
* Performs biometric verification for the current user.
|
33
|
-
* @param challengeUrl The URL to fetch the authentication challenge.
|
34
|
-
* @param verifyUrl The URL to send the authentication assertion for verification.
|
35
|
-
* @returns A promise that resolves to a BiometricVerificationResult.
|
36
|
-
*/
|
37
|
-
export async function verifyBiometric(
|
38
|
-
challengeUrl: string = '/auth/verify-webauthn/challenge',
|
39
|
-
verifyUrl: string = '/auth/verify-webauthn'
|
40
|
-
): Promise<BiometricVerificationResult> {
|
41
|
-
try {
|
42
|
-
// 1. Get the challenge from the server
|
43
|
-
const challengeResponse = await fetch(challengeUrl)
|
44
|
-
if (!challengeResponse.ok) {
|
45
|
-
const errorData = await challengeResponse.json()
|
46
|
-
if (challengeResponse.status === 400 && errorData.error === 'No biometric credentials registered for this user') {
|
47
|
-
return {
|
48
|
-
verified: false,
|
49
|
-
message: 'Biometric authentication is not set up for this account. Please register first.',
|
50
|
-
needsRegistration: true
|
51
|
-
}
|
52
|
-
}
|
53
|
-
throw new Error(`Failed to get challenge: ${errorData.error || challengeResponse.statusText}`)
|
54
|
-
}
|
55
|
-
const options = await challengeResponse.json()
|
56
|
-
|
57
|
-
// 2. Start the authentication process
|
58
|
-
const assertion = await startAuthentication(options)
|
59
|
-
|
60
|
-
// 3. Send the assertion to the server for verification
|
61
|
-
const verificationResponse = await fetch(verifyUrl, {
|
62
|
-
method: 'POST',
|
63
|
-
headers: {
|
64
|
-
'Content-Type': 'application/json'
|
65
|
-
},
|
66
|
-
body: JSON.stringify(assertion)
|
67
|
-
})
|
68
|
-
|
69
|
-
if (!verificationResponse.ok) {
|
70
|
-
throw new Error(`Verification failed: ${verificationResponse.statusText}`)
|
71
|
-
}
|
72
|
-
|
73
|
-
const verificationResult = await verificationResponse.json()
|
74
|
-
|
75
|
-
return {
|
76
|
-
verified: verificationResult.verified,
|
77
|
-
message: verificationResult.message || 'Biometric verification successful!'
|
78
|
-
}
|
79
|
-
} catch (error: any) {
|
80
|
-
console.error('Biometric verification error:', error)
|
81
|
-
return {
|
82
|
-
verified: false,
|
83
|
-
message: `Error: ${error.message}`
|
84
|
-
}
|
85
|
-
}
|
86
|
-
}
|
@@ -1,22 +0,0 @@
|
|
1
|
-
export const USER_NOT_FOUND = 'user not found'
|
2
|
-
export const PASSWORD_NOT_MATCHED = 'password-not-matched'
|
3
|
-
export const USER_NOT_ACTIVATED = 'user not activated'
|
4
|
-
export const USER_LOCKED = 'user-locked'
|
5
|
-
export const USER_DELETED = 'user-deleted'
|
6
|
-
export const NO_AVAILABLE_DOMAIN = 'no-available-domain'
|
7
|
-
export const UNAVAILABLE_DOMAIN = 'unavailable-domain'
|
8
|
-
export const NO_SELECTED_DOMAIN = 'no-selected-domain'
|
9
|
-
export const REDIRECT_TO_DEFAULT_DOMAIN = 'redirect-to-default-domain'
|
10
|
-
export const TOKEN_INVALID = 'token-invalid'
|
11
|
-
export const AUTH_INVALID = 'auth-invalid'
|
12
|
-
export const SUBDOMAIN_NOTFOUND = 'subdomain not found'
|
13
|
-
export const CONFIRM_PASSWORD_NOT_MATCHED = 'confirm password not matched'
|
14
|
-
export const PASSWORD_PATTERN_NOT_MATCHED = 'password should match the rule'
|
15
|
-
export const USER_DUPLICATED = 'user duplicated'
|
16
|
-
export const PASSWORD_USED_PAST = 'password used in the past'
|
17
|
-
export const VERIFICATION_ERROR = 'user or verification token not found'
|
18
|
-
export const AUTHN_VERIFICATION_FAILED = 'authn verification failed'
|
19
|
-
export const USER_CREDENTIAL_NOT_FOUND = 'user credential not found'
|
20
|
-
export const EMAIL_ALREADY_EXISTS = 'email already exists'
|
21
|
-
export const USERNAME_ALREADY_EXISTS = 'email already exists'
|
22
|
-
export const AUTH_ERROR = 'auth error'
|
File without changes
|
@@ -1 +0,0 @@
|
|
1
|
-
export const MAX_AGE = 7 * 24 * 3600 * 1000
|