@adonisjs/auth 9.0.0-1 → 9.0.0-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/build/configure.js +5 -40
- package/build/factories/basic_auth_guard_factory.d.ts +12 -0
- package/build/factories/basic_auth_guard_factory.js +22 -0
- package/build/index.d.ts +1 -2
- package/build/index.js +1 -2
- package/build/src/auth/auth_manager.d.ts +5 -0
- package/build/src/auth/auth_manager.js +7 -0
- package/build/src/auth/authenticator.d.ts +8 -1
- package/build/src/auth/authenticator.js +8 -1
- package/build/src/auth/authenticator_client.d.ts +23 -0
- package/build/src/auth/authenticator_client.js +59 -0
- package/build/src/auth/errors.d.ts +8 -0
- package/build/src/auth/errors.js +22 -2
- package/build/src/auth/plugins/japa/api_client.d.ts +32 -0
- package/build/src/auth/plugins/japa/api_client.js +63 -0
- package/build/src/auth/plugins/japa/browser_client.d.ts +25 -0
- package/build/src/auth/plugins/japa/browser_client.js +64 -0
- package/build/src/auth/types.d.ts +29 -0
- package/build/src/core/token_providers/database.d.ts +1 -1
- package/build/src/guards/basic_auth/define_config.d.ts +16 -0
- package/build/src/guards/basic_auth/define_config.js +38 -0
- package/build/src/guards/basic_auth/guard.d.ts +70 -0
- package/build/src/guards/basic_auth/guard.js +193 -0
- package/build/src/guards/basic_auth/main.d.ts +2 -0
- package/build/{stubs → src/guards/basic_auth}/main.js +2 -2
- package/build/src/guards/basic_auth/types.d.ts +40 -0
- package/build/src/guards/basic_auth/types.js +9 -0
- package/build/src/guards/session/define_config.js +1 -1
- package/build/src/guards/session/guard.d.ts +15 -4
- package/build/src/guards/session/guard.js +74 -6
- package/build/src/guards/session/types.d.ts +19 -2
- package/package.json +52 -31
- package/build/src/auth/middleware/auth_middleware.d.ts +0 -13
- package/build/src/auth/middleware/auth_middleware.js +0 -6
- package/build/stubs/config.stub +0 -35
- package/build/stubs/main.d.ts +0 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @adonisjs/auth
|
|
3
|
+
*
|
|
4
|
+
* (c) AdonisJS
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
import { configProvider } from '@adonisjs/core';
|
|
10
|
+
import { RuntimeException } from '@poppinss/utils';
|
|
11
|
+
import { BasicAuthGuard } from './guard.js';
|
|
12
|
+
/**
|
|
13
|
+
* Helper function to configure the basic auth guard for
|
|
14
|
+
* authentication.
|
|
15
|
+
*
|
|
16
|
+
* This method returns a config builder, which internally
|
|
17
|
+
* returns a factory function to construct a guard
|
|
18
|
+
* during HTTP requests.
|
|
19
|
+
*/
|
|
20
|
+
export function basicAuthGuard(config) {
|
|
21
|
+
return {
|
|
22
|
+
async resolver(guardName, app) {
|
|
23
|
+
const provider = await configProvider.resolve(app, config.provider);
|
|
24
|
+
if (!provider) {
|
|
25
|
+
throw new RuntimeException(`Invalid user provider defined on "${guardName}" guard`);
|
|
26
|
+
}
|
|
27
|
+
const emitter = await app.container.make('emitter');
|
|
28
|
+
/**
|
|
29
|
+
* Factory function needed by Authenticator to switch
|
|
30
|
+
* between guards and perform authentication
|
|
31
|
+
*/
|
|
32
|
+
return (ctx) => {
|
|
33
|
+
const guard = new BasicAuthGuard(guardName, ctx, provider);
|
|
34
|
+
return guard.setEmitter(emitter);
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
2
|
+
import type { EmitterLike } from '@adonisjs/core/types/events';
|
|
3
|
+
import type { BasicAuthGuardEvents } from './types.js';
|
|
4
|
+
import type { GuardContract } from '../../auth/types.js';
|
|
5
|
+
import type { UserProviderContract } from '../../core/types.js';
|
|
6
|
+
import { PROVIDER_REAL_USER, GUARD_KNOWN_EVENTS } from '../../auth/symbols.js';
|
|
7
|
+
/**
|
|
8
|
+
* Implementation of basic auth as an authentication guard
|
|
9
|
+
*/
|
|
10
|
+
export declare class BasicAuthGuard<UserProvider extends UserProviderContract<unknown>> implements GuardContract<UserProvider[typeof PROVIDER_REAL_USER]> {
|
|
11
|
+
#private;
|
|
12
|
+
[GUARD_KNOWN_EVENTS]: BasicAuthGuardEvents<UserProvider[typeof PROVIDER_REAL_USER]>;
|
|
13
|
+
/**
|
|
14
|
+
* Driver name of the guard
|
|
15
|
+
*/
|
|
16
|
+
driverName: 'basic_auth';
|
|
17
|
+
/**
|
|
18
|
+
* Whether or not the authentication has been attempted
|
|
19
|
+
* during the current request
|
|
20
|
+
*/
|
|
21
|
+
authenticationAttempted: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* A boolean to know if the current request has
|
|
24
|
+
* been authenticated
|
|
25
|
+
*/
|
|
26
|
+
isAuthenticated: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Reference to an instance of the authenticated or logged-in
|
|
29
|
+
* user. The value only exists after calling one of the
|
|
30
|
+
* following methods.
|
|
31
|
+
*
|
|
32
|
+
* - authenticate
|
|
33
|
+
*
|
|
34
|
+
* You can use the "getUserOrFail" method to throw an exception if
|
|
35
|
+
* the request is not authenticated.
|
|
36
|
+
*/
|
|
37
|
+
user?: UserProvider[typeof PROVIDER_REAL_USER];
|
|
38
|
+
constructor(name: string, ctx: HttpContext, userProvider: UserProvider);
|
|
39
|
+
/**
|
|
40
|
+
* Register an event emitter to listen for global events for
|
|
41
|
+
* authentication lifecycle.
|
|
42
|
+
*/
|
|
43
|
+
setEmitter(emitter: EmitterLike<any>): this;
|
|
44
|
+
/**
|
|
45
|
+
* Returns an instance of the authenticated user. Or throws
|
|
46
|
+
* an exception if the request is not authenticated.
|
|
47
|
+
*/
|
|
48
|
+
getUserOrFail(): UserProvider[typeof PROVIDER_REAL_USER];
|
|
49
|
+
/**
|
|
50
|
+
* Verifies user credentials and returns an instance of
|
|
51
|
+
* the user or throws "E_INVALID_BASIC_AUTH_CREDENTIALS" exception.
|
|
52
|
+
*/
|
|
53
|
+
verifyCredentials(uid: string, password: string): Promise<UserProvider[typeof PROVIDER_REAL_USER]>;
|
|
54
|
+
/**
|
|
55
|
+
* Authenticates the current HTTP request for basic
|
|
56
|
+
* auth credentials
|
|
57
|
+
*/
|
|
58
|
+
authenticate(): Promise<UserProvider[typeof PROVIDER_REAL_USER]>;
|
|
59
|
+
/**
|
|
60
|
+
* Silently attempt to authenticate the user.
|
|
61
|
+
*
|
|
62
|
+
* The method returns a boolean indicating if the authentication
|
|
63
|
+
* succeeded or failed.
|
|
64
|
+
*/
|
|
65
|
+
check(): Promise<boolean>;
|
|
66
|
+
/**
|
|
67
|
+
* Not support
|
|
68
|
+
*/
|
|
69
|
+
authenticateAsClient(_: UserProvider[typeof PROVIDER_REAL_USER]): Promise<never>;
|
|
70
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @adonisjs/auth
|
|
3
|
+
*
|
|
4
|
+
* (c) AdonisJS
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
import auth from 'basic-auth';
|
|
10
|
+
import { RuntimeException } from '@poppinss/utils';
|
|
11
|
+
import debug from '../../auth/debug.js';
|
|
12
|
+
import { AuthenticationException } from '../../auth/errors.js';
|
|
13
|
+
import { GUARD_KNOWN_EVENTS } from '../../auth/symbols.js';
|
|
14
|
+
/**
|
|
15
|
+
* Implementation of basic auth as an authentication guard
|
|
16
|
+
*/
|
|
17
|
+
export class BasicAuthGuard {
|
|
18
|
+
/**
|
|
19
|
+
* A unique name for the guard. It is used while
|
|
20
|
+
* emitting events
|
|
21
|
+
*/
|
|
22
|
+
#name;
|
|
23
|
+
/**
|
|
24
|
+
* Reference to the current HTTP context
|
|
25
|
+
*/
|
|
26
|
+
#ctx;
|
|
27
|
+
/**
|
|
28
|
+
* Provider to lookup user details
|
|
29
|
+
*/
|
|
30
|
+
#userProvider;
|
|
31
|
+
/**
|
|
32
|
+
* Emitter to emit events
|
|
33
|
+
*/
|
|
34
|
+
#emitter;
|
|
35
|
+
/**
|
|
36
|
+
* Driver name of the guard
|
|
37
|
+
*/
|
|
38
|
+
driverName = 'basic_auth';
|
|
39
|
+
/**
|
|
40
|
+
* Whether or not the authentication has been attempted
|
|
41
|
+
* during the current request
|
|
42
|
+
*/
|
|
43
|
+
authenticationAttempted = false;
|
|
44
|
+
/**
|
|
45
|
+
* A boolean to know if the current request has
|
|
46
|
+
* been authenticated
|
|
47
|
+
*/
|
|
48
|
+
isAuthenticated = false;
|
|
49
|
+
/**
|
|
50
|
+
* Reference to an instance of the authenticated or logged-in
|
|
51
|
+
* user. The value only exists after calling one of the
|
|
52
|
+
* following methods.
|
|
53
|
+
*
|
|
54
|
+
* - authenticate
|
|
55
|
+
*
|
|
56
|
+
* You can use the "getUserOrFail" method to throw an exception if
|
|
57
|
+
* the request is not authenticated.
|
|
58
|
+
*/
|
|
59
|
+
user;
|
|
60
|
+
constructor(name, ctx, userProvider) {
|
|
61
|
+
this.#ctx = ctx;
|
|
62
|
+
this.#name = name;
|
|
63
|
+
this.#userProvider = userProvider;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Notifies about authentication failure and throws the exception
|
|
67
|
+
*/
|
|
68
|
+
#authenticationFailed(error) {
|
|
69
|
+
if (this.#emitter) {
|
|
70
|
+
this.#emitter.emit('basic_auth:authentication_failed', {
|
|
71
|
+
ctx: this.#ctx,
|
|
72
|
+
guardName: this.#name,
|
|
73
|
+
error,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Register an event emitter to listen for global events for
|
|
80
|
+
* authentication lifecycle.
|
|
81
|
+
*/
|
|
82
|
+
setEmitter(emitter) {
|
|
83
|
+
this.#emitter = emitter;
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Returns an instance of the authenticated user. Or throws
|
|
88
|
+
* an exception if the request is not authenticated.
|
|
89
|
+
*/
|
|
90
|
+
getUserOrFail() {
|
|
91
|
+
if (!this.user) {
|
|
92
|
+
throw AuthenticationException.E_INVALID_BASIC_AUTH_CREDENTIALS();
|
|
93
|
+
}
|
|
94
|
+
return this.user;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Verifies user credentials and returns an instance of
|
|
98
|
+
* the user or throws "E_INVALID_BASIC_AUTH_CREDENTIALS" exception.
|
|
99
|
+
*/
|
|
100
|
+
async verifyCredentials(uid, password) {
|
|
101
|
+
debug('basic_auth_guard: attempting to verify credentials for uid "%s"', uid);
|
|
102
|
+
/**
|
|
103
|
+
* Attempt to find a user by the uid and raise
|
|
104
|
+
* error when unable to find one
|
|
105
|
+
*/
|
|
106
|
+
const providerUser = await this.#userProvider.findByUid(uid);
|
|
107
|
+
if (!providerUser) {
|
|
108
|
+
this.#authenticationFailed(AuthenticationException.E_INVALID_BASIC_AUTH_CREDENTIALS());
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Raise error when unable to verify password
|
|
112
|
+
*/
|
|
113
|
+
const user = providerUser.getOriginal();
|
|
114
|
+
/**
|
|
115
|
+
* Raise error when unable to verify password
|
|
116
|
+
*/
|
|
117
|
+
if (!(await providerUser.verifyPassword(password))) {
|
|
118
|
+
this.#authenticationFailed(AuthenticationException.E_INVALID_BASIC_AUTH_CREDENTIALS());
|
|
119
|
+
}
|
|
120
|
+
return user;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Authenticates the current HTTP request for basic
|
|
124
|
+
* auth credentials
|
|
125
|
+
*/
|
|
126
|
+
async authenticate() {
|
|
127
|
+
/**
|
|
128
|
+
* Avoid re-authenticating when already authenticated
|
|
129
|
+
*/
|
|
130
|
+
if (this.authenticationAttempted) {
|
|
131
|
+
return this.getUserOrFail();
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Beginning authentication attempt
|
|
135
|
+
*/
|
|
136
|
+
this.authenticationAttempted = true;
|
|
137
|
+
if (this.#emitter) {
|
|
138
|
+
this.#emitter.emit('basic_auth:authentication_attempted', {
|
|
139
|
+
ctx: this.#ctx,
|
|
140
|
+
guardName: this.#name,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Fetch credentials from the header
|
|
145
|
+
*/
|
|
146
|
+
const credentials = auth(this.#ctx.request.request);
|
|
147
|
+
if (!credentials) {
|
|
148
|
+
this.#authenticationFailed(AuthenticationException.E_INVALID_BASIC_AUTH_CREDENTIALS());
|
|
149
|
+
}
|
|
150
|
+
debug('basic_auth_guard: authenticating user using credentials');
|
|
151
|
+
/**
|
|
152
|
+
* Verifying user credentials
|
|
153
|
+
*/
|
|
154
|
+
this.user = await this.verifyCredentials(credentials.name, credentials.pass);
|
|
155
|
+
this.isAuthenticated = true;
|
|
156
|
+
debug('basic_auth_guard: marking user as authenticated');
|
|
157
|
+
if (this.#emitter) {
|
|
158
|
+
this.#emitter.emit('basic_auth:authentication_succeeded', {
|
|
159
|
+
ctx: this.#ctx,
|
|
160
|
+
guardName: this.#name,
|
|
161
|
+
user: this.user,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Return user
|
|
166
|
+
*/
|
|
167
|
+
return this.getUserOrFail();
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Silently attempt to authenticate the user.
|
|
171
|
+
*
|
|
172
|
+
* The method returns a boolean indicating if the authentication
|
|
173
|
+
* succeeded or failed.
|
|
174
|
+
*/
|
|
175
|
+
async check() {
|
|
176
|
+
try {
|
|
177
|
+
await this.authenticate();
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
if (error instanceof AuthenticationException) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Not support
|
|
189
|
+
*/
|
|
190
|
+
async authenticateAsClient(_) {
|
|
191
|
+
throw new RuntimeException('Cannot authenticate as a client when using basic auth');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
* For the full copyright and license information, please view the LICENSE
|
|
7
7
|
* file that was distributed with this source code.
|
|
8
8
|
*/
|
|
9
|
-
|
|
10
|
-
export
|
|
9
|
+
export { BasicAuthGuard } from './guard.js';
|
|
10
|
+
export { basicAuthGuard } from './define_config.js';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Exception } from '@poppinss/utils';
|
|
2
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
3
|
+
/**
|
|
4
|
+
* Events emitted by the basic auth guard
|
|
5
|
+
*/
|
|
6
|
+
export type BasicAuthGuardEvents<User> = {
|
|
7
|
+
/**
|
|
8
|
+
* The event is emitted when the user credentials
|
|
9
|
+
* have been verified successfully.
|
|
10
|
+
*/
|
|
11
|
+
'basic_auth:credentials_verified': {
|
|
12
|
+
ctx: HttpContext;
|
|
13
|
+
guardName: string;
|
|
14
|
+
uid: string;
|
|
15
|
+
user: User;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Attempting to authenticate the user
|
|
19
|
+
*/
|
|
20
|
+
'basic_auth:authentication_attempted': {
|
|
21
|
+
ctx: HttpContext;
|
|
22
|
+
guardName: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Authentication was successful
|
|
26
|
+
*/
|
|
27
|
+
'basic_auth:authentication_succeeded': {
|
|
28
|
+
ctx: HttpContext;
|
|
29
|
+
guardName: string;
|
|
30
|
+
user: User;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Authentication failed
|
|
34
|
+
*/
|
|
35
|
+
'basic_auth:authentication_failed': {
|
|
36
|
+
ctx: HttpContext;
|
|
37
|
+
guardName: string;
|
|
38
|
+
error: Exception;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Emitter } from '@adonisjs/core/events';
|
|
2
1
|
import type { HttpContext } from '@adonisjs/core/http';
|
|
2
|
+
import type { EmitterLike } from '@adonisjs/core/types/events';
|
|
3
3
|
import type { GuardContract } from '../../auth/types.js';
|
|
4
4
|
import { GUARD_KNOWN_EVENTS, PROVIDER_REAL_USER } from '../../auth/symbols.js';
|
|
5
5
|
import type { SessionGuardEvents, SessionGuardConfig, RememberMeProviderContract, SessionUserProviderContract } from './types.js';
|
|
@@ -71,7 +71,7 @@ export declare class SessionGuard<UserProvider extends SessionUserProviderContra
|
|
|
71
71
|
* Register an event emitter to listen for global events for
|
|
72
72
|
* authentication lifecycle.
|
|
73
73
|
*/
|
|
74
|
-
|
|
74
|
+
setEmitter(emitter: EmitterLike<any>): this;
|
|
75
75
|
/**
|
|
76
76
|
* Returns an instance of the authenticated user. Or throws
|
|
77
77
|
* an exception if the request is not authenticated.
|
|
@@ -86,13 +86,13 @@ export declare class SessionGuard<UserProvider extends SessionUserProviderContra
|
|
|
86
86
|
* Attempt to login a user after verifying their
|
|
87
87
|
* credentials.
|
|
88
88
|
*/
|
|
89
|
-
attempt(uid: string, password: string): Promise<UserProvider[typeof PROVIDER_REAL_USER]>;
|
|
89
|
+
attempt(uid: string, password: string, remember?: boolean): Promise<UserProvider[typeof PROVIDER_REAL_USER]>;
|
|
90
90
|
/**
|
|
91
91
|
* Attempt to login a user using the user id. The
|
|
92
92
|
* user will be first fetched from the db before
|
|
93
93
|
* marking them as logged-in
|
|
94
94
|
*/
|
|
95
|
-
loginViaId(id: string | number): Promise<UserProvider[typeof PROVIDER_REAL_USER]>;
|
|
95
|
+
loginViaId(id: string | number, remember?: boolean): Promise<UserProvider[typeof PROVIDER_REAL_USER]>;
|
|
96
96
|
/**
|
|
97
97
|
* Login a user using the user object.
|
|
98
98
|
*/
|
|
@@ -109,4 +109,15 @@ export declare class SessionGuard<UserProvider extends SessionUserProviderContra
|
|
|
109
109
|
* succeeded or failed.
|
|
110
110
|
*/
|
|
111
111
|
check(): Promise<boolean>;
|
|
112
|
+
/**
|
|
113
|
+
* Logout user and revoke remember me token (if any)
|
|
114
|
+
*/
|
|
115
|
+
logout(): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Returns the session state for the user to be
|
|
118
|
+
* logged-in as a client
|
|
119
|
+
*/
|
|
120
|
+
authenticateAsClient(user: UserProvider[typeof PROVIDER_REAL_USER]): Promise<{
|
|
121
|
+
session: Record<string, string | number>;
|
|
122
|
+
}>;
|
|
112
123
|
}
|
|
@@ -125,6 +125,8 @@ export class SessionGuard {
|
|
|
125
125
|
#authenticationFailed(error, sessionId) {
|
|
126
126
|
if (this.#emitter) {
|
|
127
127
|
this.#emitter.emit('session_auth:authentication_failed', {
|
|
128
|
+
ctx: this.#ctx,
|
|
129
|
+
guardName: this.#name,
|
|
128
130
|
error,
|
|
129
131
|
sessionId: sessionId,
|
|
130
132
|
});
|
|
@@ -137,6 +139,8 @@ export class SessionGuard {
|
|
|
137
139
|
#loginFailed(error, user) {
|
|
138
140
|
if (this.#emitter) {
|
|
139
141
|
this.#emitter.emit('session_auth:login_failed', {
|
|
142
|
+
ctx: this.#ctx,
|
|
143
|
+
guardName: this.#name,
|
|
140
144
|
error,
|
|
141
145
|
user,
|
|
142
146
|
});
|
|
@@ -159,7 +163,7 @@ export class SessionGuard {
|
|
|
159
163
|
* Register an event emitter to listen for global events for
|
|
160
164
|
* authentication lifecycle.
|
|
161
165
|
*/
|
|
162
|
-
|
|
166
|
+
setEmitter(emitter) {
|
|
163
167
|
this.#emitter = emitter;
|
|
164
168
|
return this;
|
|
165
169
|
}
|
|
@@ -202,6 +206,8 @@ export class SessionGuard {
|
|
|
202
206
|
*/
|
|
203
207
|
if (this.#emitter) {
|
|
204
208
|
this.#emitter.emit('session_auth:credentials_verified', {
|
|
209
|
+
ctx: this.#ctx,
|
|
210
|
+
guardName: this.#name,
|
|
205
211
|
uid,
|
|
206
212
|
user,
|
|
207
213
|
});
|
|
@@ -212,29 +218,33 @@ export class SessionGuard {
|
|
|
212
218
|
* Attempt to login a user after verifying their
|
|
213
219
|
* credentials.
|
|
214
220
|
*/
|
|
215
|
-
async attempt(uid, password) {
|
|
221
|
+
async attempt(uid, password, remember) {
|
|
216
222
|
const user = await this.verifyCredentials(uid, password);
|
|
217
|
-
return this.login(user);
|
|
223
|
+
return this.login(user, remember);
|
|
218
224
|
}
|
|
219
225
|
/**
|
|
220
226
|
* Attempt to login a user using the user id. The
|
|
221
227
|
* user will be first fetched from the db before
|
|
222
228
|
* marking them as logged-in
|
|
223
229
|
*/
|
|
224
|
-
async loginViaId(id) {
|
|
230
|
+
async loginViaId(id, remember) {
|
|
225
231
|
debug('session_guard: attempting to login user via id "%s"', id);
|
|
226
232
|
const providerUser = await this.#userProvider.findById(id);
|
|
227
233
|
if (!providerUser) {
|
|
228
234
|
this.#loginFailed(InvalidCredentialsException.E_INVALID_CREDENTIALS(this.driverName), null);
|
|
229
235
|
}
|
|
230
|
-
return this.login(providerUser.getOriginal());
|
|
236
|
+
return this.login(providerUser.getOriginal(), remember);
|
|
231
237
|
}
|
|
232
238
|
/**
|
|
233
239
|
* Login a user using the user object.
|
|
234
240
|
*/
|
|
235
241
|
async login(user, remember = false) {
|
|
236
242
|
if (this.#emitter) {
|
|
237
|
-
this.#emitter.emit('session_auth:login_attempted', {
|
|
243
|
+
this.#emitter.emit('session_auth:login_attempted', {
|
|
244
|
+
ctx: this.#ctx,
|
|
245
|
+
user,
|
|
246
|
+
guardName: this.#name,
|
|
247
|
+
});
|
|
238
248
|
}
|
|
239
249
|
const providerUser = await this.#userProvider.createUserForGuard(user);
|
|
240
250
|
const session = this.#getSession();
|
|
@@ -281,6 +291,8 @@ export class SessionGuard {
|
|
|
281
291
|
*/
|
|
282
292
|
if (this.#emitter) {
|
|
283
293
|
this.#emitter.emit('session_auth:login_succeeded', {
|
|
294
|
+
ctx: this.#ctx,
|
|
295
|
+
guardName: this.#name,
|
|
284
296
|
user,
|
|
285
297
|
sessionId: session.sessionId,
|
|
286
298
|
rememberMeToken: token,
|
|
@@ -303,6 +315,8 @@ export class SessionGuard {
|
|
|
303
315
|
*/
|
|
304
316
|
if (this.#emitter) {
|
|
305
317
|
this.#emitter.emit('session_auth:authentication_attempted', {
|
|
318
|
+
ctx: this.#ctx,
|
|
319
|
+
guardName: this.#name,
|
|
306
320
|
sessionId: session.sessionId,
|
|
307
321
|
});
|
|
308
322
|
}
|
|
@@ -322,6 +336,7 @@ export class SessionGuard {
|
|
|
322
336
|
if (!providerUser) {
|
|
323
337
|
this.#authenticationFailed(AuthenticationException.E_INVALID_AUTH_SESSION(), session.sessionId);
|
|
324
338
|
}
|
|
339
|
+
debug('session_guard: marking user with id "%s" as authenticated', providerUser.getId());
|
|
325
340
|
this.user = providerUser.getOriginal();
|
|
326
341
|
this.isAuthenticated = true;
|
|
327
342
|
this.isLoggedOut = false;
|
|
@@ -331,6 +346,8 @@ export class SessionGuard {
|
|
|
331
346
|
*/
|
|
332
347
|
if (this.#emitter) {
|
|
333
348
|
this.#emitter.emit('session_auth:authentication_succeeded', {
|
|
349
|
+
ctx: this.#ctx,
|
|
350
|
+
guardName: this.#name,
|
|
334
351
|
sessionId: session.sessionId,
|
|
335
352
|
user: this.user,
|
|
336
353
|
});
|
|
@@ -384,6 +401,7 @@ export class SessionGuard {
|
|
|
384
401
|
debug('session_guard: marking user with id "%s" as logged in from remember me cookie', userId);
|
|
385
402
|
session.put(this.sessionKeyName, userId);
|
|
386
403
|
session.regenerate();
|
|
404
|
+
debug('session_guard: marking user with id "%s" as authenticated', userId);
|
|
387
405
|
this.user = providerUser.getOriginal();
|
|
388
406
|
this.isAuthenticated = true;
|
|
389
407
|
this.isLoggedOut = false;
|
|
@@ -393,6 +411,8 @@ export class SessionGuard {
|
|
|
393
411
|
*/
|
|
394
412
|
if (this.#emitter) {
|
|
395
413
|
this.#emitter.emit('session_auth:authentication_succeeded', {
|
|
414
|
+
ctx: this.#ctx,
|
|
415
|
+
guardName: this.#name,
|
|
396
416
|
sessionId: session.sessionId,
|
|
397
417
|
user: this.user,
|
|
398
418
|
rememberMeToken: token,
|
|
@@ -451,4 +471,52 @@ export class SessionGuard {
|
|
|
451
471
|
throw error;
|
|
452
472
|
}
|
|
453
473
|
}
|
|
474
|
+
/**
|
|
475
|
+
* Logout user and revoke remember me token (if any)
|
|
476
|
+
*/
|
|
477
|
+
async logout() {
|
|
478
|
+
debug('session_auth: logging out');
|
|
479
|
+
const session = this.#getSession();
|
|
480
|
+
/**
|
|
481
|
+
* Clear client side state
|
|
482
|
+
*/
|
|
483
|
+
session.forget(this.sessionKeyName);
|
|
484
|
+
this.#ctx.response.clearCookie(this.rememberMeKeyName);
|
|
485
|
+
/**
|
|
486
|
+
* Notify the user has been logged out
|
|
487
|
+
*/
|
|
488
|
+
if (this.#emitter) {
|
|
489
|
+
this.#emitter.emit('session_auth:logged_out', {
|
|
490
|
+
ctx: this.#ctx,
|
|
491
|
+
guardName: this.#name,
|
|
492
|
+
user: this.user || null,
|
|
493
|
+
sessionId: session.sessionId,
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
const rememberMeCookie = this.#ctx.request.encryptedCookie(this.rememberMeKeyName);
|
|
497
|
+
if (!rememberMeCookie || !this.#rememberMeTokenProvider) {
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
debug('session_auth: decoding remember me token');
|
|
501
|
+
const decodedToken = RememberMeToken.decode(rememberMeCookie);
|
|
502
|
+
if (!decodedToken) {
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
debug('session_auth: deleting remember me token');
|
|
506
|
+
await this.#rememberMeTokenProvider.deleteTokenBySeries(decodedToken.series);
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Returns the session state for the user to be
|
|
510
|
+
* logged-in as a client
|
|
511
|
+
*/
|
|
512
|
+
async authenticateAsClient(user) {
|
|
513
|
+
const providerUser = await this.#userProvider.createUserForGuard(user);
|
|
514
|
+
const userId = providerUser.getId();
|
|
515
|
+
debug('session_guard: returning client session for user id "%s"', userId);
|
|
516
|
+
return {
|
|
517
|
+
session: {
|
|
518
|
+
[this.sessionKeyName]: userId,
|
|
519
|
+
},
|
|
520
|
+
};
|
|
521
|
+
}
|
|
454
522
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Exception } from '@poppinss/utils';
|
|
1
|
+
import type { Exception } from '@poppinss/utils';
|
|
2
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
2
3
|
import type { RememberMeToken } from './token.js';
|
|
3
4
|
import type { UserProviderContract, TokenProviderContract, DatabaseTokenProviderOptions } from '../../core/types.js';
|
|
4
5
|
/**
|
|
@@ -32,6 +33,8 @@ export type SessionGuardEvents<User> = {
|
|
|
32
33
|
* have been verified successfully.
|
|
33
34
|
*/
|
|
34
35
|
'session_auth:credentials_verified': {
|
|
36
|
+
ctx: HttpContext;
|
|
37
|
+
guardName: string;
|
|
35
38
|
uid: string;
|
|
36
39
|
user: User;
|
|
37
40
|
};
|
|
@@ -40,6 +43,8 @@ export type SessionGuardEvents<User> = {
|
|
|
40
43
|
* user.
|
|
41
44
|
*/
|
|
42
45
|
'session_auth:login_failed': {
|
|
46
|
+
ctx: HttpContext;
|
|
47
|
+
guardName: string;
|
|
43
48
|
error: Exception;
|
|
44
49
|
user: User | null;
|
|
45
50
|
};
|
|
@@ -48,6 +53,8 @@ export type SessionGuardEvents<User> = {
|
|
|
48
53
|
* a given user.
|
|
49
54
|
*/
|
|
50
55
|
'session_auth:login_attempted': {
|
|
56
|
+
ctx: HttpContext;
|
|
57
|
+
guardName: string;
|
|
51
58
|
user: User;
|
|
52
59
|
};
|
|
53
60
|
/**
|
|
@@ -55,6 +62,8 @@ export type SessionGuardEvents<User> = {
|
|
|
55
62
|
* successfully
|
|
56
63
|
*/
|
|
57
64
|
'session_auth:login_succeeded': {
|
|
65
|
+
ctx: HttpContext;
|
|
66
|
+
guardName: string;
|
|
58
67
|
user: User;
|
|
59
68
|
sessionId: string;
|
|
60
69
|
rememberMeToken?: RememberMeToken;
|
|
@@ -63,12 +72,16 @@ export type SessionGuardEvents<User> = {
|
|
|
63
72
|
* Attempting to authenticate the user
|
|
64
73
|
*/
|
|
65
74
|
'session_auth:authentication_attempted': {
|
|
75
|
+
ctx: HttpContext;
|
|
76
|
+
guardName: string;
|
|
66
77
|
sessionId: string;
|
|
67
78
|
};
|
|
68
79
|
/**
|
|
69
80
|
* Authentication was successful
|
|
70
81
|
*/
|
|
71
82
|
'session_auth:authentication_succeeded': {
|
|
83
|
+
ctx: HttpContext;
|
|
84
|
+
guardName: string;
|
|
72
85
|
user: User;
|
|
73
86
|
sessionId: string;
|
|
74
87
|
rememberMeToken?: RememberMeToken;
|
|
@@ -77,6 +90,8 @@ export type SessionGuardEvents<User> = {
|
|
|
77
90
|
* Authentication failed
|
|
78
91
|
*/
|
|
79
92
|
'session_auth:authentication_failed': {
|
|
93
|
+
ctx: HttpContext;
|
|
94
|
+
guardName: string;
|
|
80
95
|
error: Exception;
|
|
81
96
|
sessionId: string;
|
|
82
97
|
};
|
|
@@ -85,7 +100,9 @@ export type SessionGuardEvents<User> = {
|
|
|
85
100
|
* sucessfully
|
|
86
101
|
*/
|
|
87
102
|
'session_auth:logged_out': {
|
|
88
|
-
|
|
103
|
+
ctx: HttpContext;
|
|
104
|
+
guardName: string;
|
|
105
|
+
user: User | null;
|
|
89
106
|
sessionId: string;
|
|
90
107
|
};
|
|
91
108
|
};
|