@things-factory/auth-base 8.0.0-beta.0 → 8.0.0-beta.2
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
@@ -1,165 +0,0 @@
|
|
1
|
-
import jwt from 'jsonwebtoken'
|
2
|
-
import compose from 'koa-compose'
|
3
|
-
import passport from 'koa-passport'
|
4
|
-
import Router from 'koa-router'
|
5
|
-
|
6
|
-
import { Domain, getRepository } from '@things-factory/shell'
|
7
|
-
|
8
|
-
import { jwtAuthenticateMiddleware } from '../../middlewares'
|
9
|
-
import { Application } from '../../service/application/application'
|
10
|
-
import { User, UserStatus } from '../../service/user/user'
|
11
|
-
import { setAccessTokenCookie } from '../../utils/access-token-cookie'
|
12
|
-
import { SECRET } from '../../utils/get-secret'
|
13
|
-
import { server as oauth2orizeServer } from './oauth2-server'
|
14
|
-
import { Strategy as ClientPasswordStrategy } from './passport-oauth2-client-password'
|
15
|
-
|
16
|
-
declare global {
|
17
|
-
namespace NodeJS {
|
18
|
-
interface Process {
|
19
|
-
oauthDisconnect: (user: User) => Promise<void>
|
20
|
-
}
|
21
|
-
}
|
22
|
-
}
|
23
|
-
|
24
|
-
export const oauth2Router = new Router()
|
25
|
-
|
26
|
-
passport.use(
|
27
|
-
'oauth2-client-password',
|
28
|
-
new ClientPasswordStrategy({}, (clientId, clientSecret, done) => {
|
29
|
-
getRepository(Application)
|
30
|
-
.findOneBy({
|
31
|
-
appKey: clientId
|
32
|
-
})
|
33
|
-
.then(client => {
|
34
|
-
if (!client || client.appSecret != clientSecret) {
|
35
|
-
done(null, false)
|
36
|
-
return
|
37
|
-
}
|
38
|
-
|
39
|
-
done(null, client)
|
40
|
-
})
|
41
|
-
.catch(err => done(err))
|
42
|
-
})
|
43
|
-
)
|
44
|
-
|
45
|
-
// user decision endpoint
|
46
|
-
//
|
47
|
-
// `decision` middleware processes a user's decision to allow or deny access
|
48
|
-
// requested by a client application. Based on the grant type requested by the
|
49
|
-
// client, the above grant middleware configured above will be invoked to send
|
50
|
-
// a response.
|
51
|
-
|
52
|
-
oauth2Router.post(
|
53
|
-
'/decision',
|
54
|
-
jwtAuthenticateMiddleware,
|
55
|
-
compose(
|
56
|
-
oauth2orizeServer.decision(async function (context) {
|
57
|
-
const { request } = context
|
58
|
-
|
59
|
-
return request.body
|
60
|
-
})
|
61
|
-
)
|
62
|
-
)
|
63
|
-
|
64
|
-
// token endpoint
|
65
|
-
//
|
66
|
-
// `token` middleware handles client requests to exchange authorization grants
|
67
|
-
// for access tokens. Based on the grant type being exchanged, the above
|
68
|
-
// exchange middleware will be invoked to handle the request. Clients must
|
69
|
-
// authenticate when making requests to this endpoint.
|
70
|
-
|
71
|
-
oauth2Router.post(
|
72
|
-
'/access-token',
|
73
|
-
passport.authenticate('oauth2-client-password', { session: false }),
|
74
|
-
oauth2orizeServer.token(),
|
75
|
-
oauth2orizeServer.errorHandler()
|
76
|
-
)
|
77
|
-
|
78
|
-
oauth2Router.post('/refresh-token', async (context, next) => {
|
79
|
-
const refreshToken: string | undefined = context.request?.body?.refreshToken
|
80
|
-
if (!refreshToken) throw new Error('Missing refresh token')
|
81
|
-
|
82
|
-
const appUser: User | undefined = await getRepository(User).findOneBy({
|
83
|
-
password: refreshToken
|
84
|
-
})
|
85
|
-
|
86
|
-
if (!appUser) throw new Error('App user is not found')
|
87
|
-
|
88
|
-
try {
|
89
|
-
jwt.verify(refreshToken, SECRET)
|
90
|
-
const decoded = jwt.decode(refreshToken) as any
|
91
|
-
const subdomain: string = decoded.domain.subdomain
|
92
|
-
const domain: Domain | undefined = await getRepository(Domain).findOne({
|
93
|
-
where: { subdomain }
|
94
|
-
})
|
95
|
-
if (!domain) throw new Error('Domain is not found')
|
96
|
-
const appKey: string = decoded.application.appKey
|
97
|
-
const scopes: any[] = decoded.scope
|
98
|
-
|
99
|
-
const newAccessToken: string = Application.generateAccessToken(domain, appUser, appKey, scopes)
|
100
|
-
const newRefreshToken: string = Application.generateRefreshToken(domain, appUser, appKey, scopes)
|
101
|
-
|
102
|
-
appUser.password = newRefreshToken
|
103
|
-
await getRepository(User).save(appUser)
|
104
|
-
|
105
|
-
setAccessTokenCookie(context, newAccessToken)
|
106
|
-
|
107
|
-
context.body = {
|
108
|
-
accessToken: newAccessToken,
|
109
|
-
refreshToken: newRefreshToken
|
110
|
-
}
|
111
|
-
} catch (e) {
|
112
|
-
context.status = 401
|
113
|
-
context.body = e.message
|
114
|
-
}
|
115
|
-
})
|
116
|
-
|
117
|
-
oauth2Router.get('/profile', jwtAuthenticateMiddleware, async (context, next) => {
|
118
|
-
const { user, domain } = context.state
|
119
|
-
|
120
|
-
const { name, description, email, userType: type, locale } = user
|
121
|
-
const { name: domainName, subdomain, brandName, brandImage, contentImage, timezone } = domain || {}
|
122
|
-
|
123
|
-
var application = {}
|
124
|
-
if (type == 'application') {
|
125
|
-
/* user entity에 reference 필드가 추가되기 전까지, appKey취득 방법임. */
|
126
|
-
application['appKey'] = email.substr(0, email.lastIndexOf('@'))
|
127
|
-
}
|
128
|
-
|
129
|
-
context.body = {
|
130
|
-
profile: {
|
131
|
-
name,
|
132
|
-
description,
|
133
|
-
email,
|
134
|
-
type /* (admin|user|application|appliance) */,
|
135
|
-
domain: {
|
136
|
-
name: domainName,
|
137
|
-
subdomain,
|
138
|
-
brandName,
|
139
|
-
brandImage,
|
140
|
-
contentImage,
|
141
|
-
timezone
|
142
|
-
},
|
143
|
-
application
|
144
|
-
}
|
145
|
-
}
|
146
|
-
})
|
147
|
-
|
148
|
-
oauth2Router.post('/disconnect', jwtAuthenticateMiddleware, async (context, next) => {
|
149
|
-
try {
|
150
|
-
let { user } = context.state
|
151
|
-
|
152
|
-
if (typeof process.oauthDisconnect === 'function') {
|
153
|
-
await process.oauthDisconnect(user)
|
154
|
-
} else {
|
155
|
-
user.domains = []
|
156
|
-
user.roles = []
|
157
|
-
user.status = UserStatus.DELETED
|
158
|
-
await getRepository(User).save(user)
|
159
|
-
}
|
160
|
-
context.status = 200
|
161
|
-
context.body = 'ok'
|
162
|
-
} catch (e) {
|
163
|
-
throw e
|
164
|
-
}
|
165
|
-
})
|
@@ -1,262 +0,0 @@
|
|
1
|
-
import oauth2orize from 'oauth2orize-koa'
|
2
|
-
import { ILike, In } from 'typeorm'
|
3
|
-
|
4
|
-
import { logger } from '@things-factory/env'
|
5
|
-
import { Domain, getRepository } from '@things-factory/shell'
|
6
|
-
|
7
|
-
import { Application } from '../../service/application/application'
|
8
|
-
import { Role } from '../../service/role/role'
|
9
|
-
import { User, UserStatus } from '../../service/user/user'
|
10
|
-
|
11
|
-
const crypto = require('crypto')
|
12
|
-
|
13
|
-
export const NOTFOUND = 'NOTFOUND'
|
14
|
-
export const NonClient = {
|
15
|
-
id: NOTFOUND
|
16
|
-
}
|
17
|
-
|
18
|
-
// create OAuth 2.0 server
|
19
|
-
export const server = oauth2orize.createServer()
|
20
|
-
|
21
|
-
// Register serialialization and deserialization functions.
|
22
|
-
//
|
23
|
-
// When a client redirects a user to user authorization endpoint, an
|
24
|
-
// authorization transaction is initiated. To complete the transaction, the
|
25
|
-
// user must authenticate and approve the authorization request. Because this
|
26
|
-
// may involve multiple HTTP request/response exchanges, the transaction is
|
27
|
-
// stored in the session.
|
28
|
-
//
|
29
|
-
// An application must supply serialization functions, which determine how the
|
30
|
-
// client object is serialized into the session. Typically this will be a
|
31
|
-
// simple matter of serializing the client's ID, and deserializing by finding
|
32
|
-
// the client by ID from the database.
|
33
|
-
|
34
|
-
server.serializeClient(async function (client) {
|
35
|
-
return client.id
|
36
|
-
})
|
37
|
-
|
38
|
-
server.deserializeClient(async function (id) {
|
39
|
-
if (id == NOTFOUND) {
|
40
|
-
return {}
|
41
|
-
}
|
42
|
-
|
43
|
-
const application = await getRepository(Application).findOneBy({ id })
|
44
|
-
return application
|
45
|
-
})
|
46
|
-
|
47
|
-
// Register supported grant types.
|
48
|
-
//
|
49
|
-
// OAuth 2.0 specifies a framework that allows users to grant client
|
50
|
-
// applications limited access to their protected resources. It does this
|
51
|
-
// through a process of the user granting access, and the client exchanging
|
52
|
-
// the grant for an access token.
|
53
|
-
|
54
|
-
// Grant authorization codes. The callback takes the `client` requesting
|
55
|
-
// authorization, the `redirectURI` (which is used as a verifier in the
|
56
|
-
// subsequent exchange), the authenticated `user` granting access, and
|
57
|
-
// their response, which contains approved scope, duration, etc. as parsed by
|
58
|
-
// the application. The application issues a code, which is bound to these
|
59
|
-
// values, and will be exchanged for an access token.
|
60
|
-
|
61
|
-
server.grant(
|
62
|
-
oauth2orize.grant.code(async (client, redirectUrl, user, ares, areq) => {
|
63
|
-
const { email, appKey, subdomain, scopes, state } = ares
|
64
|
-
|
65
|
-
return Application.generateAuthCode(email, appKey, subdomain, scopes, state)
|
66
|
-
})
|
67
|
-
)
|
68
|
-
|
69
|
-
// Exchange authorization codes for access tokens. The callback accepts the
|
70
|
-
// `client`, which is exchanging `code` and any `redirectURI` from the
|
71
|
-
// authorization request for verification. If these values are validated, the
|
72
|
-
// application issues an access token on behalf of the user who authorized the
|
73
|
-
// code.
|
74
|
-
|
75
|
-
server.exchange(
|
76
|
-
oauth2orize.exchange.code(async (client, code, redirectUrl) => {
|
77
|
-
try {
|
78
|
-
/* authorization code */
|
79
|
-
var decoded: any = Application.verifyAuthCode(code)
|
80
|
-
} catch (e) {
|
81
|
-
return false
|
82
|
-
}
|
83
|
-
let { email, appKey, subdomain, scopes } = decoded
|
84
|
-
|
85
|
-
const application: Application = await getRepository(Application).findOneBy({
|
86
|
-
appKey
|
87
|
-
})
|
88
|
-
|
89
|
-
if (!application) {
|
90
|
-
return false
|
91
|
-
}
|
92
|
-
|
93
|
-
/* DONT-FORGET uncomment after test */
|
94
|
-
// if (redirectUrl !== application.redirectUrl && redirectUrl.indexOf(application.redirectUrl) != 0) {
|
95
|
-
// logger.error(
|
96
|
-
// 'oauth2 exchange error - redirectUrl should begins with the application setting',
|
97
|
-
// redirectUrl,
|
98
|
-
// application.redirectUrl
|
99
|
-
// )
|
100
|
-
// // return false
|
101
|
-
// throw new TypeError(
|
102
|
-
// `oauth2 exchange error - redirectUrl should begins with the application setting : '${redirectUrl}':'${application.redirectUrl}'`
|
103
|
-
// )
|
104
|
-
// }
|
105
|
-
|
106
|
-
const domain: Domain = await getRepository(Domain).findOneBy({
|
107
|
-
subdomain
|
108
|
-
})
|
109
|
-
|
110
|
-
const creator: User = await getRepository(User).findOneBy({ email: ILike(email) })
|
111
|
-
|
112
|
-
const appuserEmail = `${crypto.randomUUID()}@${subdomain}`
|
113
|
-
|
114
|
-
var appuser: User = await getRepository(User).findOne({
|
115
|
-
where: {
|
116
|
-
email: appuserEmail,
|
117
|
-
reference: application.id,
|
118
|
-
userType: 'application'
|
119
|
-
},
|
120
|
-
|
121
|
-
relations: ['domains', 'creator', 'updater']
|
122
|
-
})
|
123
|
-
|
124
|
-
appuser = await getRepository(User).save({
|
125
|
-
...(appuser || {}),
|
126
|
-
email: appuserEmail,
|
127
|
-
name: application.name,
|
128
|
-
userType: 'application',
|
129
|
-
reference: application.id,
|
130
|
-
domains: [domain],
|
131
|
-
roles: scopes,
|
132
|
-
status: UserStatus.ACTIVATED,
|
133
|
-
updater: creator,
|
134
|
-
creator
|
135
|
-
})
|
136
|
-
|
137
|
-
// appuser = await getRepository(User).findOne({
|
138
|
-
// where: { email: ILike(appuserEmail) },
|
139
|
-
// relations: ['domains']
|
140
|
-
// })
|
141
|
-
|
142
|
-
// appuser.domains = Promise.resolve([domain])
|
143
|
-
// await getRepository(User).save(appuser)
|
144
|
-
// Lazy relation 필드들(domain, domains)들에 대한 업데이트. 이상의 방법으로 업데이트 해야하는 것 같다.
|
145
|
-
// Lazy relation 업데이트 방법의 일관성이 부족하므로, Lazy relation 필드를 사용하지 않기를 권장함.
|
146
|
-
|
147
|
-
var accessToken = Application.generateAccessToken(domain, appuser, appKey, scopes)
|
148
|
-
var refreshToken = Application.generateRefreshToken(domain, appuser, appKey, scopes)
|
149
|
-
|
150
|
-
await getRepository(User).save({
|
151
|
-
...(appuser as any),
|
152
|
-
password: refreshToken
|
153
|
-
})
|
154
|
-
|
155
|
-
return [
|
156
|
-
accessToken,
|
157
|
-
refreshToken,
|
158
|
-
{
|
159
|
-
expires_in: 30 * 24 * 60 * 60 /* 30d */,
|
160
|
-
token_type: 'bearer',
|
161
|
-
centerId: subdomain
|
162
|
-
}
|
163
|
-
]
|
164
|
-
})
|
165
|
-
)
|
166
|
-
|
167
|
-
server.exchange(
|
168
|
-
oauth2orize.exchange.refreshToken(async (client, refreshToken, scope) => {
|
169
|
-
try {
|
170
|
-
/* refresh token */
|
171
|
-
var decoded: any = Application.verifyAuthCode(refreshToken)
|
172
|
-
} catch (e) {
|
173
|
-
logger.error(e)
|
174
|
-
return false
|
175
|
-
}
|
176
|
-
const {
|
177
|
-
id,
|
178
|
-
userType,
|
179
|
-
email,
|
180
|
-
application: { appKey },
|
181
|
-
domain: { subdomain },
|
182
|
-
scope: originalScope,
|
183
|
-
exp: expires_in
|
184
|
-
} = decoded
|
185
|
-
|
186
|
-
const application: Application = await getRepository(Application).findOneBy({
|
187
|
-
appKey
|
188
|
-
})
|
189
|
-
|
190
|
-
if (!application) {
|
191
|
-
logger.error('application is not exist')
|
192
|
-
return false
|
193
|
-
}
|
194
|
-
|
195
|
-
if (Date.now() > expires_in * 1000) {
|
196
|
-
logger.error('refresh token is expired')
|
197
|
-
return false
|
198
|
-
}
|
199
|
-
|
200
|
-
const domain: Domain = await getRepository(Domain).findOneBy({
|
201
|
-
subdomain
|
202
|
-
})
|
203
|
-
|
204
|
-
const creator: User = await getRepository(User).findOneBy({
|
205
|
-
id,
|
206
|
-
userType
|
207
|
-
})
|
208
|
-
|
209
|
-
const appuserEmail = `${appKey}@${subdomain}`
|
210
|
-
|
211
|
-
var appuser: User = await getRepository(User).findOne({
|
212
|
-
where: {
|
213
|
-
email: appuserEmail,
|
214
|
-
reference: application.id,
|
215
|
-
userType: 'application'
|
216
|
-
},
|
217
|
-
relations: ['domain', 'creator', 'updater']
|
218
|
-
})
|
219
|
-
|
220
|
-
if (!appuser) {
|
221
|
-
logger.error('application is not bound')
|
222
|
-
return false
|
223
|
-
}
|
224
|
-
|
225
|
-
/*
|
226
|
-
* `scope` is the scope of access requested by the client, which must not include any scope not originally granted.
|
227
|
-
*/
|
228
|
-
|
229
|
-
scope = scope || originalScope
|
230
|
-
|
231
|
-
const scopes: string[] = scope.split(',')
|
232
|
-
const originalScopes = (originalScope || '').split(',')
|
233
|
-
const additionalScope = scopes.find(scope => originalScopes.indexOf(scope) === -1)
|
234
|
-
if (additionalScope) {
|
235
|
-
logger.error(`additional scope(${additionalScope}) required`)
|
236
|
-
return false
|
237
|
-
}
|
238
|
-
|
239
|
-
const roles = await getRepository(Role).findBy({
|
240
|
-
name: In(scopes),
|
241
|
-
domain: { id: domain.id }
|
242
|
-
})
|
243
|
-
|
244
|
-
var accessToken = Application.generateAccessToken(domain, appuser, appKey, scope)
|
245
|
-
var refreshToken: any = Application.generateRefreshToken(domain, appuser, appKey, scope)
|
246
|
-
|
247
|
-
await getRepository(User).save({
|
248
|
-
...(appuser as any),
|
249
|
-
roles,
|
250
|
-
password: refreshToken
|
251
|
-
})
|
252
|
-
|
253
|
-
return [
|
254
|
-
accessToken,
|
255
|
-
refreshToken,
|
256
|
-
{
|
257
|
-
expires_in: 30 * 24 * 60 * 60 /* 30d */,
|
258
|
-
token_type: 'bearer'
|
259
|
-
}
|
260
|
-
]
|
261
|
-
})
|
262
|
-
)
|
@@ -1,87 +0,0 @@
|
|
1
|
-
import passport from 'koa-passport'
|
2
|
-
import util from 'util'
|
3
|
-
|
4
|
-
/**
|
5
|
-
* `Oauth2ClientPasswordStrategy` constructor.
|
6
|
-
*
|
7
|
-
* @api protected
|
8
|
-
* Basic Authorization Header와 Body 형식을 모두 지원한다.
|
9
|
-
*/
|
10
|
-
export function Strategy(options, verify) {
|
11
|
-
if (typeof options == 'function') {
|
12
|
-
verify = options
|
13
|
-
options = {}
|
14
|
-
}
|
15
|
-
if (!verify) throw new Error('OAuth 2.0 client password strategy requires a verify function')
|
16
|
-
|
17
|
-
passport.Strategy.call(this)
|
18
|
-
this.name = 'oauth2-client-password'
|
19
|
-
this._verify = verify
|
20
|
-
this._passReqToCallback = options.passReqToCallback
|
21
|
-
}
|
22
|
-
|
23
|
-
/**
|
24
|
-
* Inherit from `passport.Strategy`.
|
25
|
-
*/
|
26
|
-
util.inherits(Strategy, passport.Strategy)
|
27
|
-
|
28
|
-
function fetchBasicCredential(authorization = '') {
|
29
|
-
var parts = authorization.split(' ')
|
30
|
-
if (parts.length < 2) {
|
31
|
-
return
|
32
|
-
}
|
33
|
-
|
34
|
-
var scheme = parts[0]
|
35
|
-
var credentials = new Buffer(parts[1], 'base64').toString().split(':')
|
36
|
-
|
37
|
-
if (!/Basic/i.test(scheme)) {
|
38
|
-
return
|
39
|
-
}
|
40
|
-
if (credentials.length < 2) {
|
41
|
-
return
|
42
|
-
}
|
43
|
-
|
44
|
-
var clientId = credentials[0]
|
45
|
-
var clientSecret = credentials[1]
|
46
|
-
if (!clientId || !clientSecret) {
|
47
|
-
return
|
48
|
-
}
|
49
|
-
|
50
|
-
return [clientId, clientSecret]
|
51
|
-
}
|
52
|
-
|
53
|
-
/**
|
54
|
-
* Authenticate request based on client credentials in the request body.
|
55
|
-
*
|
56
|
-
* @param {Object} req
|
57
|
-
* @api protected
|
58
|
-
*/
|
59
|
-
Strategy.prototype.authenticate = function (req) {
|
60
|
-
var [clientId, clientSecret] = fetchBasicCredential(req.headers['authorization']) || []
|
61
|
-
if (!clientId) {
|
62
|
-
if (!req.body || !req.body['client_id'] || !req.body['client_secret']) {
|
63
|
-
return this.fail()
|
64
|
-
}
|
65
|
-
|
66
|
-
clientId = req.body['client_id']
|
67
|
-
clientSecret = req.body['client_secret']
|
68
|
-
}
|
69
|
-
|
70
|
-
var self = this
|
71
|
-
|
72
|
-
function verified(err, client, info) {
|
73
|
-
if (err) {
|
74
|
-
return self.error(err)
|
75
|
-
}
|
76
|
-
if (!client) {
|
77
|
-
return self.fail()
|
78
|
-
}
|
79
|
-
self.success(client, info)
|
80
|
-
}
|
81
|
-
|
82
|
-
if (self._passReqToCallback) {
|
83
|
-
this._verify(req, clientId, clientSecret, verified)
|
84
|
-
} else {
|
85
|
-
this._verify(clientId, clientSecret, verified)
|
86
|
-
}
|
87
|
-
}
|
@@ -1,87 +0,0 @@
|
|
1
|
-
import passport from 'koa-passport'
|
2
|
-
import util from 'util'
|
3
|
-
|
4
|
-
/**
|
5
|
-
* `PassportRefreshTokenStrategy` constructor.
|
6
|
-
*
|
7
|
-
* @api protected
|
8
|
-
* Basic Authorization Header와 Body 형식을 모두 지원한다.
|
9
|
-
*/
|
10
|
-
export function Strategy(options, verify) {
|
11
|
-
if (typeof options == 'function') {
|
12
|
-
verify = options
|
13
|
-
options = {}
|
14
|
-
}
|
15
|
-
if (!verify) throw new Error('OAuth 2.0 refresh-token strategy requires a verify function')
|
16
|
-
|
17
|
-
passport.Strategy.call(this)
|
18
|
-
this.name = 'refresh-token'
|
19
|
-
this._verify = verify
|
20
|
-
this._passReqToCallback = options.passReqToCallback
|
21
|
-
}
|
22
|
-
|
23
|
-
/**
|
24
|
-
* Inherit from `passport.Strategy`.
|
25
|
-
*/
|
26
|
-
util.inherits(Strategy, passport.Strategy)
|
27
|
-
|
28
|
-
function fetchBasicCredential(authorization = '') {
|
29
|
-
var parts = authorization.split(' ')
|
30
|
-
if (parts.length < 2) {
|
31
|
-
return
|
32
|
-
}
|
33
|
-
|
34
|
-
var scheme = parts[0]
|
35
|
-
var credentials = new Buffer(parts[1], 'base64').toString().split(':')
|
36
|
-
|
37
|
-
if (!/Basic/i.test(scheme)) {
|
38
|
-
return
|
39
|
-
}
|
40
|
-
if (credentials.length < 2) {
|
41
|
-
return
|
42
|
-
}
|
43
|
-
|
44
|
-
var clientId = credentials[0]
|
45
|
-
var clientSecret = credentials[1]
|
46
|
-
if (!clientId || !clientSecret) {
|
47
|
-
return
|
48
|
-
}
|
49
|
-
|
50
|
-
return [clientId, clientSecret]
|
51
|
-
}
|
52
|
-
|
53
|
-
/**
|
54
|
-
* Authenticate request based on client credentials in the request body.
|
55
|
-
*
|
56
|
-
* @param {Object} req
|
57
|
-
* @api protected
|
58
|
-
*/
|
59
|
-
Strategy.prototype.authenticate = function (req) {
|
60
|
-
var [clientId, clientSecret] = fetchBasicCredential(req.headers['authorization']) || []
|
61
|
-
if (!clientId) {
|
62
|
-
if (!req.body || !req.body['client_id'] || !req.body['client_secret']) {
|
63
|
-
return this.fail()
|
64
|
-
}
|
65
|
-
|
66
|
-
clientId = req.body['client_id']
|
67
|
-
clientSecret = req.body['client_secret']
|
68
|
-
}
|
69
|
-
|
70
|
-
var self = this
|
71
|
-
|
72
|
-
function verified(err, client, info) {
|
73
|
-
if (err) {
|
74
|
-
return self.error(err)
|
75
|
-
}
|
76
|
-
if (!client) {
|
77
|
-
return self.fail()
|
78
|
-
}
|
79
|
-
self.success(client, info)
|
80
|
-
}
|
81
|
-
|
82
|
-
if (self._passReqToCallback) {
|
83
|
-
this._verify(req, clientId, clientSecret, verified)
|
84
|
-
} else {
|
85
|
-
this._verify(clientId, clientSecret, verified)
|
86
|
-
}
|
87
|
-
}
|
@@ -1,48 +0,0 @@
|
|
1
|
-
import Router from 'koa-router'
|
2
|
-
import passport from 'koa-passport'
|
3
|
-
|
4
|
-
import { Domain, domainMiddleware } from '@things-factory/shell'
|
5
|
-
import { config } from '@things-factory/env'
|
6
|
-
|
7
|
-
import { User } from '../service/user/user'
|
8
|
-
import { getUserDomains } from '../utils/get-user-domains'
|
9
|
-
|
10
|
-
const PUBLIC_HOME_ROUTE = config.get('publicHomeRoute', '/public/home')
|
11
|
-
|
12
|
-
export const siteRootRouter = new Router()
|
13
|
-
|
14
|
-
async function findAuth(context, next) {
|
15
|
-
return await passport.authenticate('jwt', { session: false }, async (err, decoded, info) => {
|
16
|
-
if (decoded) {
|
17
|
-
try {
|
18
|
-
const user = await User.checkAuth(decoded)
|
19
|
-
context.state.user = user
|
20
|
-
} catch (e) {}
|
21
|
-
}
|
22
|
-
|
23
|
-
await next()
|
24
|
-
})(context, next)
|
25
|
-
}
|
26
|
-
|
27
|
-
siteRootRouter.get('/', findAuth, domainMiddleware, async (context, next) => {
|
28
|
-
const { user, domain } = context.state
|
29
|
-
|
30
|
-
const subdomain = domain?.subdomain
|
31
|
-
|
32
|
-
if (user && subdomain) {
|
33
|
-
const userDomains: Partial<Domain>[] = await getUserDomains(user)
|
34
|
-
if (userDomains.find(userDomain => userDomain.subdomain == subdomain)) {
|
35
|
-
return await next()
|
36
|
-
}
|
37
|
-
|
38
|
-
return context.redirect(`/auth/checkin/${subdomain}`)
|
39
|
-
}
|
40
|
-
|
41
|
-
if (user && !subdomain) {
|
42
|
-
context.redirect('/auth/checkin')
|
43
|
-
|
44
|
-
return
|
45
|
-
}
|
46
|
-
|
47
|
-
context.redirect(PUBLIC_HOME_ROUTE)
|
48
|
-
})
|