@steedos/service-identity-jwt 2.2.54-beta.10
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/LICENSE.txt +22 -0
- package/main/default/routes/account.d.ts +8 -0
- package/main/default/routes/account.js +73 -0
- package/main/default/routes/apps.router.d.ts +1 -0
- package/main/default/routes/apps.router.js +25 -0
- package/package.json +24 -0
- package/package.service.js +124 -0
- package/src/routes/account.ts +76 -0
- package/src/routes/apps.router.ts +25 -0
- package/tsconfig.json +37 -0
package/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Steedos Licensing
|
|
2
|
+
|
|
3
|
+
SOFTWARE LICENSING
|
|
4
|
+
|
|
5
|
+
To determine under which license you may use a file from the Steedos source code,
|
|
6
|
+
please resort to the header of that file.
|
|
7
|
+
|
|
8
|
+
If the file has no header, the following rules apply
|
|
9
|
+
1. enterprise features are licensed under Steedos Enterprise Terms, see License.enterprise.txt
|
|
10
|
+
2. source code that is neither (1) is licensed under MIT, see https://opensource.org/licenses/MIT
|
|
11
|
+
|
|
12
|
+
On request, licenses under different terms are available.
|
|
13
|
+
|
|
14
|
+
Source code of enterprise features are files that
|
|
15
|
+
* are in folders named "ee" or start with "ee_", or in subfolders of such folders.
|
|
16
|
+
* contain the strings "ee_" in its filename name.
|
|
17
|
+
The files can be found by running the command `find . -iname ee -or -iname "*_ee*" -or -iname "*ee_*"`
|
|
18
|
+
|
|
19
|
+
STEEDOS TRADEMARK GUIDELINES
|
|
20
|
+
|
|
21
|
+
Your use of the mark Steedos is subject to Steedos, Inc's prior written approval. For trademark approval or any questions
|
|
22
|
+
you have about using these trademarks, please email zhuangjianguo@steedos.com
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Account = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
/*
|
|
6
|
+
* @Author: baozhoutao@steedos.com
|
|
7
|
+
* @Date: 2022-06-27 15:17:27
|
|
8
|
+
* @LastEditors: baozhoutao@steedos.com
|
|
9
|
+
* @LastEditTime: 2022-07-16 12:01:45
|
|
10
|
+
* @Description:
|
|
11
|
+
*/
|
|
12
|
+
const accounts_1 = require("@steedos/accounts");
|
|
13
|
+
const requestIp = require("request-ip");
|
|
14
|
+
const objectql_1 = require("@steedos/objectql");
|
|
15
|
+
const getUserAgent = (req) => {
|
|
16
|
+
let userAgent = req.headers['user-agent'] || '';
|
|
17
|
+
if (req.headers['x-ucbrowser-ua']) {
|
|
18
|
+
// special case of UC Browser
|
|
19
|
+
userAgent = req.headers['x-ucbrowser-ua'];
|
|
20
|
+
}
|
|
21
|
+
return userAgent;
|
|
22
|
+
};
|
|
23
|
+
class Account {
|
|
24
|
+
static ssoLogin(req, res, options = { user: null, err: null, redirect: true, accessToken: null }) {
|
|
25
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
let { user, err } = options;
|
|
27
|
+
//TODO
|
|
28
|
+
if (err || !user) {
|
|
29
|
+
(0, objectql_1.getSteedosSchema)().broker.logger.error(`oidc sso login error: ${err}`);
|
|
30
|
+
return res.redirect("/api/global/auth/oidc/error-callback");
|
|
31
|
+
}
|
|
32
|
+
let userAgent = getUserAgent(req) || '';
|
|
33
|
+
const ip = requestIp.getClientIp(req);
|
|
34
|
+
let logout_other_clients = false;
|
|
35
|
+
let login_expiration_in_days = null;
|
|
36
|
+
let phone_logout_other_clients = false;
|
|
37
|
+
let phone_login_expiration_in_days = null;
|
|
38
|
+
let space = null;
|
|
39
|
+
// 获取用户简档
|
|
40
|
+
const userProfile = yield accounts_1.accountsServer.getUserProfile(user.id);
|
|
41
|
+
if (userProfile) {
|
|
42
|
+
logout_other_clients = userProfile.logout_other_clients || false;
|
|
43
|
+
login_expiration_in_days = userProfile.login_expiration_in_days;
|
|
44
|
+
phone_logout_other_clients =
|
|
45
|
+
userProfile.phone_logout_other_clients || false;
|
|
46
|
+
phone_login_expiration_in_days =
|
|
47
|
+
userProfile.phone_login_expiration_in_days;
|
|
48
|
+
space = userProfile.space;
|
|
49
|
+
}
|
|
50
|
+
// 更新user_providers
|
|
51
|
+
const loginResult = yield accounts_1.accountsServer.loginWithUser(user, Object.assign({}, {
|
|
52
|
+
ip,
|
|
53
|
+
userAgent
|
|
54
|
+
}, {
|
|
55
|
+
logout_other_clients,
|
|
56
|
+
login_expiration_in_days,
|
|
57
|
+
phone_logout_other_clients,
|
|
58
|
+
phone_login_expiration_in_days,
|
|
59
|
+
space,
|
|
60
|
+
provider: 'jwt',
|
|
61
|
+
// jwtToken: options.accessToken // 如果使用jwt token 会导致cookie太大
|
|
62
|
+
}));
|
|
63
|
+
(0, accounts_1.setAuthCookies)(req, res, loginResult.user._id, loginResult.token, loginResult.tokens.accessToken);
|
|
64
|
+
if (options.redirect) {
|
|
65
|
+
res.redirect(`/accounts/a/?uid=${loginResult.user._id}`);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
return loginResult;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.Account = Account;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
/*
|
|
5
|
+
* @Author: baozhoutao@steedos.com
|
|
6
|
+
* @Date: 2022-06-08 23:28:39
|
|
7
|
+
* @LastEditors: baozhoutao@steedos.com
|
|
8
|
+
* @LastEditTime: 2022-07-16 16:18:31
|
|
9
|
+
* @Description:
|
|
10
|
+
*/
|
|
11
|
+
const express = require("express");
|
|
12
|
+
const account_1 = require("./account");
|
|
13
|
+
const passport = require('passport');
|
|
14
|
+
const router = express.Router();
|
|
15
|
+
router.use('/accounts/jwt/login', passport.authenticate('jwt', { session: false }), (req, res) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
|
|
16
|
+
account_1.Account.ssoLogin(req, res, { err: null, user: req.user, redirect: false, accessToken: null }).then((loginResult) => {
|
|
17
|
+
delete loginResult.user.services;
|
|
18
|
+
delete loginResult.user.thirdPartyUser;
|
|
19
|
+
return res.status(200).send(loginResult);
|
|
20
|
+
}).catch((err) => {
|
|
21
|
+
console.log(`err`, err);
|
|
22
|
+
return res.status(500).send(err.message);
|
|
23
|
+
});
|
|
24
|
+
}));
|
|
25
|
+
exports.default = router;
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@steedos/service-identity-jwt",
|
|
3
|
+
"version": "2.2.54-beta.10",
|
|
4
|
+
"main": "package.service.js",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"steedos"
|
|
7
|
+
],
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc"
|
|
10
|
+
},
|
|
11
|
+
"description": "steedos package",
|
|
12
|
+
"repository": {},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@steedos/accounts": "2.2.54-beta.10",
|
|
15
|
+
"express": "4.18.1",
|
|
16
|
+
"passport-jwt": "^4.0.0"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"private": false,
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"gitHead": "a9abdeb7aaaaf8eee1cecc28efc6cd89ba65a9fe"
|
|
24
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: baozhoutao@steedos.com
|
|
3
|
+
* @Date: 2022-06-11 18:09:20
|
|
4
|
+
* @LastEditors: baozhoutao@steedos.com
|
|
5
|
+
* @LastEditTime: 2022-07-16 18:24:42
|
|
6
|
+
* @Description:
|
|
7
|
+
*/
|
|
8
|
+
"use strict";
|
|
9
|
+
const project = require('./package.json');
|
|
10
|
+
const packageName = project.name;
|
|
11
|
+
const objectql = require('@steedos/objectql');
|
|
12
|
+
const packageLoader = require('@steedos/service-package-loader');
|
|
13
|
+
const passport = require('passport');
|
|
14
|
+
const JwtStrategy = require("passport-jwt").Strategy
|
|
15
|
+
const ExtractJwt = require('passport-jwt').ExtractJwt;
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
const authError = function (done, message, err = null) {
|
|
19
|
+
return done(
|
|
20
|
+
message,
|
|
21
|
+
null
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
module.exports = {
|
|
26
|
+
name: packageName,
|
|
27
|
+
namespace: "steedos",
|
|
28
|
+
mixins: [packageLoader],
|
|
29
|
+
/**
|
|
30
|
+
* Settings
|
|
31
|
+
*/
|
|
32
|
+
settings: {
|
|
33
|
+
packageInfo: {
|
|
34
|
+
path: __dirname,
|
|
35
|
+
name: packageName,
|
|
36
|
+
isPackage: true
|
|
37
|
+
},
|
|
38
|
+
jwt: {
|
|
39
|
+
secret: process.env.STEEDOS_IDENTITY_JWT_SECRET,
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Dependencies
|
|
45
|
+
*/
|
|
46
|
+
dependencies: [],
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Actions
|
|
50
|
+
*/
|
|
51
|
+
actions: {
|
|
52
|
+
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Events
|
|
57
|
+
*/
|
|
58
|
+
events: {
|
|
59
|
+
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Methods
|
|
64
|
+
*/
|
|
65
|
+
methods: {
|
|
66
|
+
beforeStart: async function () {
|
|
67
|
+
if(!this.settings.jwt.secret){
|
|
68
|
+
throw new Error(`${packageName} jwt secret is not defined`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Service created lifecycle event handler
|
|
75
|
+
*/
|
|
76
|
+
created() {
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Service started lifecycle event handler
|
|
81
|
+
*/
|
|
82
|
+
async started() {
|
|
83
|
+
try {
|
|
84
|
+
if(this.settings.jwt.secret){
|
|
85
|
+
const jwtOptions = {
|
|
86
|
+
secretOrKey: this.settings.jwt.secret,
|
|
87
|
+
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const jwtAuthenticate = function (jwt_payload, done) {
|
|
91
|
+
try {
|
|
92
|
+
const { profile } = jwt_payload;
|
|
93
|
+
if(profile && profile._json && profile._json.email){
|
|
94
|
+
objectql.getObject('users').find({filters: [['email', '=', profile._json.email]], fields: ['_id', 'name', 'email', 'username']}).then((records)=>{
|
|
95
|
+
if(records.length > 0){
|
|
96
|
+
const user = records[0];
|
|
97
|
+
return done(null, Object.assign({}, user, {id: user._id}))
|
|
98
|
+
}else{
|
|
99
|
+
return done('user not find', null)
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
}else{
|
|
103
|
+
return done('JWT invalid', null)
|
|
104
|
+
}
|
|
105
|
+
} catch (err) {
|
|
106
|
+
return authError(done, "JWT invalid", err)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
passport.use(new JwtStrategy(jwtOptions, jwtAuthenticate))
|
|
111
|
+
}
|
|
112
|
+
} catch (error) {
|
|
113
|
+
// this.setError(error);
|
|
114
|
+
this.broker.logger.error(error)
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Service stopped lifecycle event handler
|
|
120
|
+
*/
|
|
121
|
+
async stopped() {
|
|
122
|
+
|
|
123
|
+
}
|
|
124
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: baozhoutao@steedos.com
|
|
3
|
+
* @Date: 2022-06-27 15:17:27
|
|
4
|
+
* @LastEditors: baozhoutao@steedos.com
|
|
5
|
+
* @LastEditTime: 2022-07-16 12:01:45
|
|
6
|
+
* @Description:
|
|
7
|
+
*/
|
|
8
|
+
import { accountsServer, setAuthCookies } from '@steedos/accounts';
|
|
9
|
+
|
|
10
|
+
import * as requestIp from 'request-ip';
|
|
11
|
+
|
|
12
|
+
import { getSteedosSchema } from '@steedos/objectql';
|
|
13
|
+
|
|
14
|
+
const getUserAgent = (req: any) => {
|
|
15
|
+
let userAgent: string = (req.headers['user-agent'] as string) || '';
|
|
16
|
+
if (req.headers['x-ucbrowser-ua']) {
|
|
17
|
+
// special case of UC Browser
|
|
18
|
+
userAgent = req.headers['x-ucbrowser-ua'] as string;
|
|
19
|
+
}
|
|
20
|
+
return userAgent;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export class Account {
|
|
24
|
+
static async ssoLogin(req, res, options = { user: null, err: null, redirect: true, accessToken: null }) {
|
|
25
|
+
let { user , err } = options;
|
|
26
|
+
//TODO
|
|
27
|
+
if (err || !user) {
|
|
28
|
+
getSteedosSchema().broker.logger.error(`oidc sso login error: ${err}`);
|
|
29
|
+
return res.redirect("/api/global/auth/oidc/error-callback");
|
|
30
|
+
}
|
|
31
|
+
let userAgent = getUserAgent(req) || '';
|
|
32
|
+
const ip = requestIp.getClientIp(req);
|
|
33
|
+
let logout_other_clients = false;
|
|
34
|
+
let login_expiration_in_days = null;
|
|
35
|
+
let phone_logout_other_clients = false;
|
|
36
|
+
let phone_login_expiration_in_days = null;
|
|
37
|
+
let space = null;
|
|
38
|
+
// 获取用户简档
|
|
39
|
+
const userProfile = await accountsServer.getUserProfile(
|
|
40
|
+
user.id
|
|
41
|
+
);
|
|
42
|
+
if (userProfile) {
|
|
43
|
+
logout_other_clients = userProfile.logout_other_clients || false;
|
|
44
|
+
login_expiration_in_days = userProfile.login_expiration_in_days;
|
|
45
|
+
phone_logout_other_clients =
|
|
46
|
+
userProfile.phone_logout_other_clients || false;
|
|
47
|
+
phone_login_expiration_in_days =
|
|
48
|
+
userProfile.phone_login_expiration_in_days;
|
|
49
|
+
space = userProfile.space;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 更新user_providers
|
|
53
|
+
const loginResult = await accountsServer.loginWithUser(
|
|
54
|
+
user,
|
|
55
|
+
Object.assign({}, {
|
|
56
|
+
ip,
|
|
57
|
+
userAgent
|
|
58
|
+
}, {
|
|
59
|
+
logout_other_clients,
|
|
60
|
+
login_expiration_in_days,
|
|
61
|
+
phone_logout_other_clients,
|
|
62
|
+
phone_login_expiration_in_days,
|
|
63
|
+
space,
|
|
64
|
+
provider: 'jwt',
|
|
65
|
+
// jwtToken: options.accessToken // 如果使用jwt token 会导致cookie太大
|
|
66
|
+
})
|
|
67
|
+
);
|
|
68
|
+
setAuthCookies(req, res, loginResult.user._id, loginResult.token, loginResult.tokens.accessToken);
|
|
69
|
+
|
|
70
|
+
if(options.redirect){
|
|
71
|
+
res.redirect(`/accounts/a/?uid=${loginResult.user._id}`);
|
|
72
|
+
}else{
|
|
73
|
+
return loginResult;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: baozhoutao@steedos.com
|
|
3
|
+
* @Date: 2022-06-08 23:28:39
|
|
4
|
+
* @LastEditors: baozhoutao@steedos.com
|
|
5
|
+
* @LastEditTime: 2022-07-16 16:18:31
|
|
6
|
+
* @Description:
|
|
7
|
+
*/
|
|
8
|
+
import * as express from 'express';
|
|
9
|
+
import { Account } from './account'
|
|
10
|
+
const passport = require('passport');
|
|
11
|
+
|
|
12
|
+
const router = express.Router();
|
|
13
|
+
|
|
14
|
+
router.use('/accounts/jwt/login', passport.authenticate('jwt', { session: false }), async (req: any, res) => {
|
|
15
|
+
Account.ssoLogin(req, res, { err: null, user: req.user, redirect: false, accessToken: null }).then((loginResult) => {
|
|
16
|
+
delete loginResult.user.services;
|
|
17
|
+
delete loginResult.user.thirdPartyUser;
|
|
18
|
+
return res.status(200).send(loginResult)
|
|
19
|
+
}).catch((err) => {
|
|
20
|
+
console.log(`err`, err)
|
|
21
|
+
return res.status(500).send(err.message);
|
|
22
|
+
})
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
exports.default = router;
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"outDir": "./main/default/routes",
|
|
4
|
+
"target": "es6",
|
|
5
|
+
"module": "commonjs",
|
|
6
|
+
"moduleResolution": "node",
|
|
7
|
+
"importHelpers": true,
|
|
8
|
+
"emitDecoratorMetadata": true,
|
|
9
|
+
"experimentalDecorators": true,
|
|
10
|
+
"sourceMap": false,
|
|
11
|
+
"declarationMap": false,
|
|
12
|
+
"noImplicitAny": false,
|
|
13
|
+
"declaration": true,
|
|
14
|
+
"noFallthroughCasesInSwitch": true,
|
|
15
|
+
//"noImplicitReturns": true,
|
|
16
|
+
"stripInternal": true,
|
|
17
|
+
"pretty": true,
|
|
18
|
+
"noUnusedLocals": true,
|
|
19
|
+
"downlevelIteration": true,
|
|
20
|
+
"strictNullChecks": false,
|
|
21
|
+
"skipLibCheck": true,
|
|
22
|
+
"lib": [
|
|
23
|
+
"es5",
|
|
24
|
+
"es6",
|
|
25
|
+
"es2015",
|
|
26
|
+
"es2016",
|
|
27
|
+
"es2017",
|
|
28
|
+
"esnext"
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
"include": [
|
|
32
|
+
"./src/**/*"
|
|
33
|
+
],
|
|
34
|
+
"exclude": [
|
|
35
|
+
"../../node_modules/"
|
|
36
|
+
]
|
|
37
|
+
}
|