@kevisual/auth 1.0.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/dist/create-token.d.ts +18 -0
- package/dist/create-token.js +6339 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.js +7506 -0
- package/dist/proxy.d.ts +39 -0
- package/dist/proxy.js +83 -0
- package/dist/salt.d.ts +22 -0
- package/dist/salt.js +1130 -0
- package/package.json +63 -0
- package/readme.md +26 -0
- package/src/create-token.ts +29 -0
- package/src/index.ts +6 -0
- package/src/proxy.ts +99 -0
- package/src/route.ts +44 -0
- package/src/salt.ts +32 -0
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kevisual/auth",
|
|
3
|
+
"version": "1.0.4",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"typings": "dist/index.d.js",
|
|
8
|
+
"private": false,
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "npm run clean &&rollup -c",
|
|
11
|
+
"clean": "rimraf dist"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"src",
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"keywords": [
|
|
18
|
+
"router",
|
|
19
|
+
"auth"
|
|
20
|
+
],
|
|
21
|
+
"author": "",
|
|
22
|
+
"license": "ISC",
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"@kevisual/router": "^0.0.4"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@rollup/plugin-commonjs": "^28.0.1",
|
|
28
|
+
"@rollup/plugin-node-resolve": "^15.3.0",
|
|
29
|
+
"@rollup/plugin-typescript": "^12.1.1",
|
|
30
|
+
"@types/crypto-js": "^4.2.2",
|
|
31
|
+
"@types/jsonwebtoken": "^9.0.7",
|
|
32
|
+
"crypto-js": "^4.2.0",
|
|
33
|
+
"jsonwebtoken": "^9.0.2",
|
|
34
|
+
"rollup": "^4.27.2",
|
|
35
|
+
"rollup-plugin-dts": "^6.1.1",
|
|
36
|
+
"tslib": "^2.8.1"
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/abearxiong/kevisual-router.git"
|
|
41
|
+
},
|
|
42
|
+
"exports": {
|
|
43
|
+
".": {
|
|
44
|
+
"import": "./dist/index.js",
|
|
45
|
+
"require": "./dist/index.js"
|
|
46
|
+
},
|
|
47
|
+
"./token": {
|
|
48
|
+
"import": "./dist/create-token.js",
|
|
49
|
+
"require": "./dist/create-token.js"
|
|
50
|
+
},
|
|
51
|
+
"./salt": {
|
|
52
|
+
"import": "./dist/create-token.js",
|
|
53
|
+
"require": "./dist/create-token.js"
|
|
54
|
+
},
|
|
55
|
+
"./proxy": {
|
|
56
|
+
"import": "./dist/proxy.js",
|
|
57
|
+
"require": "./dist/proxy.js"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public"
|
|
62
|
+
}
|
|
63
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# router query auth
|
|
2
|
+
|
|
3
|
+
for kevisual/router
|
|
4
|
+
|
|
5
|
+
配置项
|
|
6
|
+
|
|
7
|
+
```json5
|
|
8
|
+
{
|
|
9
|
+
tokenSercet: 'xx'
|
|
10
|
+
}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## use
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { App } from '@kevisual/router';
|
|
17
|
+
import { createAuthRoute } from '@kevisual/auth';
|
|
18
|
+
|
|
19
|
+
const app = new App();
|
|
20
|
+
createAuthRoute({
|
|
21
|
+
app: app,
|
|
22
|
+
addToApp: true
|
|
23
|
+
});
|
|
24
|
+
app.listen(3000);
|
|
25
|
+
// curl http://localhost:3000/api/router?path=auth
|
|
26
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import jwt from 'jsonwebtoken';
|
|
2
|
+
|
|
3
|
+
// https://www.robinwieruch.de/graphql-apollo-server-tutorial#apollo-server-authentication
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param user
|
|
7
|
+
* @param secret
|
|
8
|
+
*
|
|
9
|
+
* @param expiresIn default 7d expressed in seconds or a string describing a time span [zeit/ms](https://github.com/zeit/ms.js). Eg: 60, "2 days", "10h", "7d"
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
export const createToken = async (
|
|
13
|
+
user: {
|
|
14
|
+
id: string;
|
|
15
|
+
username: string;
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
},
|
|
18
|
+
secret: string,
|
|
19
|
+
expiresIn = '7d'
|
|
20
|
+
) => {
|
|
21
|
+
const { id, username, ...rest } = user;
|
|
22
|
+
return jwt.sign({ id, username, ...rest }, secret, {
|
|
23
|
+
expiresIn
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const checkToken = async (token: string, secret: string) => {
|
|
28
|
+
return jwt.verify(token, secret, { complete: true });
|
|
29
|
+
};
|
package/src/index.ts
ADDED
package/src/proxy.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
export const proxyFetch = async (url: string, data: any) => {
|
|
2
|
+
const res = await fetch(url, {
|
|
3
|
+
method: 'POST',
|
|
4
|
+
headers: {
|
|
5
|
+
'Content-Type': 'application/json'
|
|
6
|
+
},
|
|
7
|
+
body: JSON.stringify(data)
|
|
8
|
+
});
|
|
9
|
+
const _res = await res.json();
|
|
10
|
+
return _res;
|
|
11
|
+
};
|
|
12
|
+
type AuthProxyOptions = {
|
|
13
|
+
host: string;
|
|
14
|
+
path?: string;
|
|
15
|
+
protol?: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Auth Query 轻量级代理
|
|
19
|
+
*/
|
|
20
|
+
export class AuthQuery {
|
|
21
|
+
url: string;
|
|
22
|
+
host: string;
|
|
23
|
+
path: string;
|
|
24
|
+
constructor(opts?: AuthProxyOptions) {
|
|
25
|
+
this.host = opts?.host || 'localhost:114000';
|
|
26
|
+
this.path = opts?.path || '/api/auth';
|
|
27
|
+
const protol = opts?.protol || 'http';
|
|
28
|
+
this.url = `${protol}://${this.host}${this.path}`;
|
|
29
|
+
}
|
|
30
|
+
async queryMe(token: string) {
|
|
31
|
+
return proxyFetch(this.url, {
|
|
32
|
+
path: 'user',
|
|
33
|
+
key: 'me',
|
|
34
|
+
token
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
async login(username: string, password: string) {
|
|
38
|
+
return proxyFetch(this.url, {
|
|
39
|
+
path: 'user',
|
|
40
|
+
key: 'login',
|
|
41
|
+
data: {
|
|
42
|
+
username,
|
|
43
|
+
password
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
async query(data: any) {
|
|
48
|
+
return proxyFetch(this.url, data);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
type AuthProxy = {
|
|
52
|
+
queryMe: (token: string) => Promise<any>;
|
|
53
|
+
/**
|
|
54
|
+
* 代理设置token用户
|
|
55
|
+
* @param ctx
|
|
56
|
+
* @param data
|
|
57
|
+
* @returns
|
|
58
|
+
*/
|
|
59
|
+
setTokenUser?: (ctx: any, data: any) => Promise<any>;
|
|
60
|
+
};
|
|
61
|
+
type CreateAuthRouteOptions = {
|
|
62
|
+
app?: any;
|
|
63
|
+
addToApp?: boolean;
|
|
64
|
+
proxy: AuthProxy;
|
|
65
|
+
};
|
|
66
|
+
export const createAuthRoute = ({ app, addToApp = true, proxy }: CreateAuthRouteOptions) => {
|
|
67
|
+
/**
|
|
68
|
+
* 中间件执行函数
|
|
69
|
+
* @param ctx
|
|
70
|
+
*/
|
|
71
|
+
const authRouteFn = async (ctx: any) => {
|
|
72
|
+
const token = ctx.query.token;
|
|
73
|
+
if (!token) {
|
|
74
|
+
app.throw(401, 'Token is Unauthorized');
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
const result = await proxy?.queryMe?.(token);
|
|
78
|
+
if (result.code === 200) {
|
|
79
|
+
result.payload = result.data;
|
|
80
|
+
}
|
|
81
|
+
if (proxy?.setTokenUser) {
|
|
82
|
+
await proxy?.setTokenUser?.(ctx, result.data);
|
|
83
|
+
} else {
|
|
84
|
+
ctx.state['tokenUser'] = result.payload;
|
|
85
|
+
}
|
|
86
|
+
} catch (e) {
|
|
87
|
+
app.throw(401, 'Token is invalid');
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
let authRoute;
|
|
91
|
+
if (app) {
|
|
92
|
+
authRoute = app.route('auth', '', { id: 'auth' });
|
|
93
|
+
authRoute.run = authRouteFn;
|
|
94
|
+
if (addToApp) {
|
|
95
|
+
authRoute.addTo(app);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return { route: authRoute, authRouteFn };
|
|
99
|
+
};
|
package/src/route.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { checkToken } from './create-token.ts';
|
|
2
|
+
|
|
3
|
+
type CreateAuthRouteOptions = {
|
|
4
|
+
secret: string;
|
|
5
|
+
app?: any;
|
|
6
|
+
addToApp?: boolean;
|
|
7
|
+
};
|
|
8
|
+
export const createAuthRoute = ({ secret, app, addToApp = true }: CreateAuthRouteOptions) => {
|
|
9
|
+
/**
|
|
10
|
+
* 中间件执行函数
|
|
11
|
+
* @param ctx
|
|
12
|
+
*/
|
|
13
|
+
const authRouteFn = async (ctx: any) => {
|
|
14
|
+
const token = ctx.query.token;
|
|
15
|
+
if (!token) {
|
|
16
|
+
// throw new CustomError(401, 'Token is Unauthorized');
|
|
17
|
+
app.throw(401, 'Token is Unauthorized');
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
const result = await checkToken(token, secret);
|
|
21
|
+
ctx.state['tokenUser'] = result.payload;
|
|
22
|
+
} catch (e) {
|
|
23
|
+
if (e.name === 'TokenExpiredError') {
|
|
24
|
+
app.throw(401, 'Token is expired');
|
|
25
|
+
} else if (e.name === 'JsonWebTokenError') {
|
|
26
|
+
app.throw(401, 'Token is invalid');
|
|
27
|
+
} else if (e.name === 'NotBeforeError') {
|
|
28
|
+
app.throw(401, 'Token is not active');
|
|
29
|
+
} else {
|
|
30
|
+
console.error('checkToken error', e);
|
|
31
|
+
app.throw(401, 'Token is invalid');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
let authRoute;
|
|
36
|
+
if (app) {
|
|
37
|
+
authRoute = app.route('auth', '', { id: 'auth' });
|
|
38
|
+
authRoute.run = authRouteFn;
|
|
39
|
+
if (addToApp) {
|
|
40
|
+
authRoute.addTo(app);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return { route: authRoute, authRouteFn };
|
|
44
|
+
};
|
package/src/salt.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import MD5 from 'crypto-js/md5.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 生成随机盐
|
|
5
|
+
* @returns
|
|
6
|
+
*/
|
|
7
|
+
export const getRandomSalt = () => {
|
|
8
|
+
return Math.random().toString().slice(2, 7);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 加密密码
|
|
13
|
+
* @param password
|
|
14
|
+
* @param salt
|
|
15
|
+
* @returns
|
|
16
|
+
*/
|
|
17
|
+
export const cryptPwd = (password: string, salt = '') => {
|
|
18
|
+
const saltPassword = password + ':' + salt;
|
|
19
|
+
const md5 = MD5(saltPassword);
|
|
20
|
+
return md5.toString();
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Check password
|
|
25
|
+
* @param password
|
|
26
|
+
* @param salt
|
|
27
|
+
* @param md5
|
|
28
|
+
* @returns
|
|
29
|
+
*/
|
|
30
|
+
export const checkPwd = (password: string, salt: string, md5: string) => {
|
|
31
|
+
return cryptPwd(password, salt) === md5;
|
|
32
|
+
};
|