webledger-auth-plugin 1.0.10 → 2.0.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/README.md +5 -0
- package/build/adonis-typings/AuthService.d.ts +18 -12
- package/build/instructions.md +3 -3
- package/build/providers/AuthServiceProvider.js +2 -1
- package/build/src/AuthService.d.ts +51 -0
- package/build/src/AuthService.js +81 -9
- package/build/templates/config/AuthService.txt +3 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -12,3 +12,8 @@ node ace configure webledger-auth-plugin
|
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
[**Instructions**](./instructions.md)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## Develop locally
|
|
18
|
+
1. `npm run link` this will build and link locally, somewhere in your `~/node_modules/<package_name>` or `~/.nvm/versions/node/v18.20.3/lib/node_modules`
|
|
19
|
+
2. at the project folder where you want to install locally try `npm link webledger-auth-plugin` (package.json -> name)
|
|
@@ -1,24 +1,30 @@
|
|
|
1
1
|
declare module '@ioc:AuthService' {
|
|
2
2
|
export interface AuthServiceI {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
isEnable: boolean;
|
|
4
|
+
createToken(sub: string): string;
|
|
5
|
+
verifyToken(token: string, sub?: string): object | null;
|
|
6
|
+
getApps(): Promise<any>;
|
|
7
|
+
login(email: string, password: string): Promise<any>;
|
|
8
|
+
signup(params: any): Promise<any>;
|
|
9
|
+
getUser(uuid: string): Promise<any>;
|
|
10
|
+
updateUser(uuid: string, params: any): Promise<any>;
|
|
11
|
+
forgotPassword(email: string): Promise<any>;
|
|
12
|
+
resendEmailVerification(email: string): Promise<any>;
|
|
13
|
+
verifyPin(uuid: string, user_pin: string): Promise<any>;
|
|
14
|
+
forgotPin(uuid: string, password: string, user_pin: string): Promise<any>;
|
|
15
|
+
logoutURL(): string;
|
|
16
|
+
checkLoginURL(): string;
|
|
13
17
|
}
|
|
14
18
|
const authService: AuthServiceI;
|
|
15
19
|
export default authService;
|
|
16
20
|
export interface AuthServiceConfig {
|
|
21
|
+
enable: boolean;
|
|
17
22
|
host: string;
|
|
18
|
-
env: string;
|
|
19
|
-
type: string;
|
|
20
23
|
iss: string;
|
|
24
|
+
client: string;
|
|
21
25
|
secret: string;
|
|
26
|
+
env?: string;
|
|
27
|
+
product?: string;
|
|
22
28
|
expiry?: string;
|
|
23
29
|
timeout?: number;
|
|
24
30
|
paths?: {
|
package/build/instructions.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Congratulations! You have configured `AuthService` package successfully. Make sure to add the following values inside `env.ts` file:
|
|
2
2
|
|
|
3
3
|
```ts
|
|
4
|
+
AUTH_ENABLE: Env.schema.boolean,
|
|
4
5
|
AUTH_HOST: Env.schema.string({ format: 'host' }),
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
AUTH_JWT_TOKEN: Env.schema.string(),
|
|
6
|
+
AUTH_CLIENT: Env.schema.string(),
|
|
7
|
+
AUTH_SECRET: Env.schema.string(),
|
|
8
8
|
```
|
|
@@ -11,7 +11,8 @@ class AuthServiceProvider {
|
|
|
11
11
|
register() {
|
|
12
12
|
this.app.container.singleton('AuthService', () => {
|
|
13
13
|
const config = this.app.container.use('Adonis/Core/Config');
|
|
14
|
-
|
|
14
|
+
const service = new AuthService_1.default(config.get('authService'));
|
|
15
|
+
return service;
|
|
15
16
|
});
|
|
16
17
|
}
|
|
17
18
|
}
|
|
@@ -7,6 +7,55 @@ export default class AuthService implements AuthServiceI {
|
|
|
7
7
|
createToken(sub: string): any;
|
|
8
8
|
verifyToken(token: string, sub?: string): any;
|
|
9
9
|
private setAuthToken;
|
|
10
|
+
/**
|
|
11
|
+
* isEnable is useful if enable both local or server auth
|
|
12
|
+
* if true means you can use server auth else you can do something else
|
|
13
|
+
*
|
|
14
|
+
* Example code for login
|
|
15
|
+
*
|
|
16
|
+
* import User from 'App/Models/User'
|
|
17
|
+
* import AuthService from '@ioc:AuthService'
|
|
18
|
+
*
|
|
19
|
+
public async login(ctx: HttpContextContract) {
|
|
20
|
+
const { email, password } = ctx.request.only(['email', 'password'])
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
let user: User | null,
|
|
24
|
+
token: any = null,
|
|
25
|
+
sso_url = null
|
|
26
|
+
if (AuthService.isEnable) {
|
|
27
|
+
const res = await AuthService.login(email, password)
|
|
28
|
+
const data = res.data.user
|
|
29
|
+
sso_url = res.data.sso_url
|
|
30
|
+
user = await User.findBy('uuid', data.uuid)
|
|
31
|
+
if (!user) user = await User.findBy('email', email)
|
|
32
|
+
|
|
33
|
+
if (user) {
|
|
34
|
+
data.isLocked = false
|
|
35
|
+
user.merge(data)
|
|
36
|
+
await user.save()
|
|
37
|
+
} else {
|
|
38
|
+
user = await User.create(data)
|
|
39
|
+
}
|
|
40
|
+
token = await ctx.auth.use('api').generate(user, { expiresIn: '12 hours' })
|
|
41
|
+
} else {
|
|
42
|
+
token = await ctx.auth.use('api').attempt(email, password)
|
|
43
|
+
user = ctx.auth.use('api').user!
|
|
44
|
+
if (!ctx.auth.use('api').user) {
|
|
45
|
+
return ctx.response.status(400).json({ message: 'Invalid credentials', token })
|
|
46
|
+
}
|
|
47
|
+
await ctx.auth.user?.merge({ isLocked: false }).save()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (user) return ctx.response.json({ ...user.serialize(), token, sso_url })
|
|
51
|
+
} catch (e) {
|
|
52
|
+
this.logger.error(`Error login: ${e.message}`)
|
|
53
|
+
}
|
|
54
|
+
return ctx.response.status(400).json({ message: 'Invalid credentials' })
|
|
55
|
+
}
|
|
56
|
+
*/
|
|
57
|
+
get isEnable(): boolean;
|
|
58
|
+
getApps(): Promise<import("axios").AxiosResponse<any, any>>;
|
|
10
59
|
login(email: string, password: string): Promise<import("axios").AxiosResponse<any, any>>;
|
|
11
60
|
signup(params: any): Promise<import("axios").AxiosResponse<any, any>>;
|
|
12
61
|
getUser(uuid: string): Promise<import("axios").AxiosResponse<any, any>>;
|
|
@@ -15,4 +64,6 @@ export default class AuthService implements AuthServiceI {
|
|
|
15
64
|
resendEmailVerification(email: string): Promise<import("axios").AxiosResponse<any, any>>;
|
|
16
65
|
verifyPin(uuid: string, user_pin: string): Promise<import("axios").AxiosResponse<any, any>>;
|
|
17
66
|
forgotPin(uuid: string, password: string, user_pin: string): Promise<import("axios").AxiosResponse<any, any>>;
|
|
67
|
+
logoutURL(): string;
|
|
68
|
+
checkLoginURL(): string;
|
|
18
69
|
}
|
package/build/src/AuthService.js
CHANGED
|
@@ -9,6 +9,7 @@ class AuthService {
|
|
|
9
9
|
constructor(config) {
|
|
10
10
|
this.config = config;
|
|
11
11
|
this.paths = {
|
|
12
|
+
apps: '/api/apps',
|
|
12
13
|
login: '/api/login',
|
|
13
14
|
signup: '/api/signup',
|
|
14
15
|
get_user: '/api/users',
|
|
@@ -22,34 +23,97 @@ class AuthService {
|
|
|
22
23
|
this.client.defaults.timeout = config.timeout || 30000; // default is 30seconds
|
|
23
24
|
const headers = {
|
|
24
25
|
'Content-Type': 'application/json',
|
|
25
|
-
'x-auth-
|
|
26
|
-
'x-product-type': config.type,
|
|
26
|
+
'x-auth-client': config.client,
|
|
27
27
|
};
|
|
28
|
+
const [product, env] = config.client.split('_');
|
|
29
|
+
config.env = env;
|
|
30
|
+
config.product = product;
|
|
28
31
|
for (const key in headers) {
|
|
29
32
|
this.client.defaults.headers.common[key] = headers[key];
|
|
30
33
|
}
|
|
31
34
|
this.paths = { ...this.paths, ...config.paths };
|
|
32
35
|
}
|
|
33
36
|
createToken(sub) {
|
|
34
|
-
const payload = {
|
|
37
|
+
const payload = {
|
|
38
|
+
env: this.config.env,
|
|
39
|
+
product: this.config.product,
|
|
40
|
+
iss: this.config.iss,
|
|
41
|
+
sub,
|
|
42
|
+
};
|
|
35
43
|
const jwtAuthToken = (0, jsonwebtoken_1.sign)(payload, this.config.secret, {
|
|
36
44
|
expiresIn: this.config.expiry || '1m',
|
|
37
45
|
});
|
|
38
46
|
return jwtAuthToken;
|
|
39
47
|
}
|
|
40
48
|
verifyToken(token, sub) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (sub
|
|
49
|
+
try {
|
|
50
|
+
const data = (0, jsonwebtoken_1.verify)(token, this.config.secret);
|
|
51
|
+
if (!sub)
|
|
44
52
|
return data;
|
|
45
|
-
|
|
53
|
+
return sub === data.sub ? data : null;
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
46
56
|
return null;
|
|
47
57
|
}
|
|
48
|
-
return data;
|
|
49
58
|
}
|
|
50
59
|
setAuthToken(sub) {
|
|
51
60
|
const jwtAuthToken = this.createToken(sub);
|
|
52
|
-
this.client.defaults.headers.common['Authorization'] =
|
|
61
|
+
this.client.defaults.headers.common['Authorization'] = jwtAuthToken;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* isEnable is useful if enable both local or server auth
|
|
65
|
+
* if true means you can use server auth else you can do something else
|
|
66
|
+
*
|
|
67
|
+
* Example code for login
|
|
68
|
+
*
|
|
69
|
+
* import User from 'App/Models/User'
|
|
70
|
+
* import AuthService from '@ioc:AuthService'
|
|
71
|
+
*
|
|
72
|
+
public async login(ctx: HttpContextContract) {
|
|
73
|
+
const { email, password } = ctx.request.only(['email', 'password'])
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
let user: User | null,
|
|
77
|
+
token: any = null,
|
|
78
|
+
sso_url = null
|
|
79
|
+
if (AuthService.isEnable) {
|
|
80
|
+
const res = await AuthService.login(email, password)
|
|
81
|
+
const data = res.data.user
|
|
82
|
+
sso_url = res.data.sso_url
|
|
83
|
+
user = await User.findBy('uuid', data.uuid)
|
|
84
|
+
if (!user) user = await User.findBy('email', email)
|
|
85
|
+
|
|
86
|
+
if (user) {
|
|
87
|
+
data.isLocked = false
|
|
88
|
+
user.merge(data)
|
|
89
|
+
await user.save()
|
|
90
|
+
} else {
|
|
91
|
+
user = await User.create(data)
|
|
92
|
+
}
|
|
93
|
+
token = await ctx.auth.use('api').generate(user, { expiresIn: '12 hours' })
|
|
94
|
+
} else {
|
|
95
|
+
token = await ctx.auth.use('api').attempt(email, password)
|
|
96
|
+
user = ctx.auth.use('api').user!
|
|
97
|
+
if (!ctx.auth.use('api').user) {
|
|
98
|
+
return ctx.response.status(400).json({ message: 'Invalid credentials', token })
|
|
99
|
+
}
|
|
100
|
+
await ctx.auth.user?.merge({ isLocked: false }).save()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (user) return ctx.response.json({ ...user.serialize(), token, sso_url })
|
|
104
|
+
} catch (e) {
|
|
105
|
+
this.logger.error(`Error login: ${e.message}`)
|
|
106
|
+
}
|
|
107
|
+
return ctx.response.status(400).json({ message: 'Invalid credentials' })
|
|
108
|
+
}
|
|
109
|
+
*/
|
|
110
|
+
get isEnable() {
|
|
111
|
+
return this.config.enable;
|
|
112
|
+
}
|
|
113
|
+
getApps() {
|
|
114
|
+
const subject = 'apps';
|
|
115
|
+
this.setAuthToken(subject);
|
|
116
|
+
return this.client.get(this.paths[subject]);
|
|
53
117
|
}
|
|
54
118
|
login(email, password) {
|
|
55
119
|
const subject = 'login';
|
|
@@ -91,5 +155,13 @@ class AuthService {
|
|
|
91
155
|
this.setAuthToken(subject);
|
|
92
156
|
return this.client.post(`${this.paths[subject]}/${uuid}/forgot_pin`, { password, user_pin });
|
|
93
157
|
}
|
|
158
|
+
logoutURL() {
|
|
159
|
+
const url = `${this.config.host}/sso/${this.config.env}/logout?product=${this.config.product}`;
|
|
160
|
+
return url;
|
|
161
|
+
}
|
|
162
|
+
checkLoginURL() {
|
|
163
|
+
const url = `${this.config.host}/sso/${this.config.env}/jump/${this.config.product}`;
|
|
164
|
+
return url;
|
|
165
|
+
}
|
|
94
166
|
}
|
|
95
167
|
exports.default = AuthService;
|
|
@@ -2,11 +2,13 @@ import { AuthServiceConfig } from '@ioc:AuthService'
|
|
|
2
2
|
import Env from '@ioc:Adonis/Core/Env'
|
|
3
3
|
|
|
4
4
|
const authServiceConfig: AuthServiceConfig = {
|
|
5
|
+
enable: Env.get('AUTH_ENABLE', true),
|
|
5
6
|
host: Env.get('AUTH_HOST'),
|
|
6
7
|
env: Env.get('AUTH_ENV'),
|
|
7
8
|
type: Env.get('AUTH_PRODUCT_TYPE'),
|
|
8
9
|
iss: Env.get('BASE_URL'),
|
|
9
|
-
|
|
10
|
+
client: Env.get('AUTH_CLIENT'),
|
|
11
|
+
secret: Env.get('AUTH_SECRET'),
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export default authServiceConfig
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webledger-auth-plugin",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "webledger auth service AdonisJS 5 login plugin",
|
|
5
5
|
"main": "build/providers/AuthServiceProvider.js",
|
|
6
6
|
"scripts": {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"build": "npm run compile",
|
|
13
13
|
"prepublishOnly": "npm run build",
|
|
14
14
|
"lint": "eslint . --ext=.ts",
|
|
15
|
+
"link": "npm run build && npm link",
|
|
15
16
|
"format": "prettier --write .",
|
|
16
17
|
"commit": "git-cz",
|
|
17
18
|
"release": "np --message=\"chore(release): %s\"",
|