@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
package/build/configure.js
CHANGED
|
@@ -6,50 +6,15 @@
|
|
|
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
|
-
* Configures the user provider to use for finding
|
|
11
|
-
* users
|
|
12
|
-
*/
|
|
13
|
-
async function configureProvider(command) {
|
|
14
|
-
const provider = await command.prompt.choice('Select the user provider you want to use', [
|
|
15
|
-
{
|
|
16
|
-
name: 'lucid',
|
|
17
|
-
message: 'Lucid models',
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
name: 'db',
|
|
21
|
-
message: 'Database query builder',
|
|
22
|
-
},
|
|
23
|
-
]);
|
|
24
|
-
/**
|
|
25
|
-
* Publish config file
|
|
26
|
-
*/
|
|
27
|
-
await command.publishStub('config.stub', { provider });
|
|
28
|
-
}
|
|
9
|
+
import { presetAuth } from '@adonisjs/presets/auth';
|
|
29
10
|
/**
|
|
30
11
|
* Configures the auth package
|
|
31
12
|
*/
|
|
32
13
|
export async function configure(command) {
|
|
33
|
-
await configureProvider(command);
|
|
34
14
|
const codemods = await command.createCodemods();
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
rcFile.addProvider('@adonisjs/auth/auth_provider');
|
|
15
|
+
// let guard: string | undefined = command.parsedFlags.guard
|
|
16
|
+
await presetAuth(codemods, command.app, {
|
|
17
|
+
guard: 'session',
|
|
18
|
+
userProvider: 'lucid',
|
|
40
19
|
});
|
|
41
|
-
/**
|
|
42
|
-
* Register middleware
|
|
43
|
-
*/
|
|
44
|
-
await codemods.registerMiddleware('router', [
|
|
45
|
-
{
|
|
46
|
-
path: '@adonisjs/auth/initialize_auth_middleware',
|
|
47
|
-
},
|
|
48
|
-
]);
|
|
49
|
-
await codemods.registerMiddleware('named', [
|
|
50
|
-
{
|
|
51
|
-
name: 'auth',
|
|
52
|
-
path: '@adonisjs/auth/auth_middleware',
|
|
53
|
-
},
|
|
54
|
-
]);
|
|
55
20
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
2
|
+
import { FactoryUser, TestLucidUserProvider } from './lucid_user_provider.js';
|
|
3
|
+
import { BasicAuthGuard } from '../src/guards/basic_auth/guard.js';
|
|
4
|
+
import type { UserProviderContract } from '../src/core/types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Exposes the API to create a basic auth guard for testing. Under
|
|
7
|
+
* the hood configures Lucid models for looking up users
|
|
8
|
+
*/
|
|
9
|
+
export declare class BasicAuthGuardFactory {
|
|
10
|
+
merge(): this;
|
|
11
|
+
create<UserProvider extends UserProviderContract<unknown> = TestLucidUserProvider<typeof FactoryUser>>(ctx: HttpContext, provider?: UserProvider): BasicAuthGuard<TestLucidUserProvider<typeof FactoryUser> | UserProvider>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
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 { LucidUserProviderFactory, } from './lucid_user_provider.js';
|
|
10
|
+
import { BasicAuthGuard } from '../src/guards/basic_auth/guard.js';
|
|
11
|
+
/**
|
|
12
|
+
* Exposes the API to create a basic auth guard for testing. Under
|
|
13
|
+
* the hood configures Lucid models for looking up users
|
|
14
|
+
*/
|
|
15
|
+
export class BasicAuthGuardFactory {
|
|
16
|
+
merge() {
|
|
17
|
+
return this;
|
|
18
|
+
}
|
|
19
|
+
create(ctx, provider) {
|
|
20
|
+
return new BasicAuthGuard('basic', ctx, provider || new LucidUserProviderFactory().create());
|
|
21
|
+
}
|
|
22
|
+
}
|
package/build/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { configure } from './configure.js';
|
|
2
|
-
export { stubsRoot } from './stubs/main.js';
|
|
3
|
-
export * as errors from './src/auth/errors.js';
|
|
4
2
|
export * as symbols from './src/auth/symbols.js';
|
|
5
3
|
export { AuthManager } from './src/auth/auth_manager.js';
|
|
6
4
|
export { Authenticator } from './src/auth/authenticator.js';
|
|
7
5
|
export { defineConfig, providers } from './src/auth/define_config.js';
|
|
6
|
+
export { AuthenticationException, InvalidCredentialsException } from './src/auth/errors.js';
|
package/build/index.js
CHANGED
|
@@ -7,9 +7,8 @@
|
|
|
7
7
|
* file that was distributed with this source code.
|
|
8
8
|
*/
|
|
9
9
|
export { configure } from './configure.js';
|
|
10
|
-
export { stubsRoot } from './stubs/main.js';
|
|
11
|
-
export * as errors from './src/auth/errors.js';
|
|
12
10
|
export * as symbols from './src/auth/symbols.js';
|
|
13
11
|
export { AuthManager } from './src/auth/auth_manager.js';
|
|
14
12
|
export { Authenticator } from './src/auth/authenticator.js';
|
|
15
13
|
export { defineConfig, providers } from './src/auth/define_config.js';
|
|
14
|
+
export { AuthenticationException, InvalidCredentialsException } from './src/auth/errors.js';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { HttpContext } from '@adonisjs/core/http';
|
|
2
2
|
import type { GuardFactory } from './types.js';
|
|
3
3
|
import { Authenticator } from './authenticator.js';
|
|
4
|
+
import { AuthenticatorClient } from './authenticator_client.js';
|
|
4
5
|
/**
|
|
5
6
|
* Auth manager exposes the API to register and manage authentication
|
|
6
7
|
* guards from the config
|
|
@@ -19,4 +20,8 @@ export declare class AuthManager<KnownGuards extends Record<string, GuardFactory
|
|
|
19
20
|
* Create an authenticator for a given HTTP request
|
|
20
21
|
*/
|
|
21
22
|
createAuthenticator(ctx: HttpContext): Authenticator<KnownGuards>;
|
|
23
|
+
/**
|
|
24
|
+
* Creates an instance of the authenticator client
|
|
25
|
+
*/
|
|
26
|
+
createAuthenticatorClient(): AuthenticatorClient<KnownGuards>;
|
|
22
27
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* file that was distributed with this source code.
|
|
8
8
|
*/
|
|
9
9
|
import { Authenticator } from './authenticator.js';
|
|
10
|
+
import { AuthenticatorClient } from './authenticator_client.js';
|
|
10
11
|
/**
|
|
11
12
|
* Auth manager exposes the API to register and manage authentication
|
|
12
13
|
* guards from the config
|
|
@@ -31,4 +32,10 @@ export class AuthManager {
|
|
|
31
32
|
createAuthenticator(ctx) {
|
|
32
33
|
return new Authenticator(ctx, this.#config);
|
|
33
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates an instance of the authenticator client
|
|
37
|
+
*/
|
|
38
|
+
createAuthenticatorClient() {
|
|
39
|
+
return new AuthenticatorClient(this.#config);
|
|
40
|
+
}
|
|
34
41
|
}
|
|
@@ -35,6 +35,13 @@ export declare class Authenticator<KnownGuards extends Record<string, GuardFacto
|
|
|
35
35
|
default: keyof KnownGuards;
|
|
36
36
|
guards: KnownGuards;
|
|
37
37
|
});
|
|
38
|
+
/**
|
|
39
|
+
* Returns an instance of the logged-in user or throws an
|
|
40
|
+
* exception
|
|
41
|
+
*/
|
|
42
|
+
getUserOrFail(): {
|
|
43
|
+
[K in keyof KnownGuards]: ReturnType<ReturnType<KnownGuards[K]>['getUserOrFail']>;
|
|
44
|
+
}[keyof KnownGuards];
|
|
38
45
|
/**
|
|
39
46
|
* Returns an instance of a known guard. Guards instances are
|
|
40
47
|
* cached during the lifecycle of an HTTP request.
|
|
@@ -51,6 +58,6 @@ export declare class Authenticator<KnownGuards extends Record<string, GuardFacto
|
|
|
51
58
|
* Otherwise, "AuthenticationException" will be raised.
|
|
52
59
|
*/
|
|
53
60
|
authenticateUsing(guards?: (keyof KnownGuards)[], options?: {
|
|
54
|
-
|
|
61
|
+
loginRoute?: string;
|
|
55
62
|
}): Promise<boolean>;
|
|
56
63
|
}
|
|
@@ -68,6 +68,13 @@ export class Authenticator {
|
|
|
68
68
|
this.#config = config;
|
|
69
69
|
debug('creating authenticator. config %O', this.#config);
|
|
70
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Returns an instance of the logged-in user or throws an
|
|
73
|
+
* exception
|
|
74
|
+
*/
|
|
75
|
+
getUserOrFail() {
|
|
76
|
+
return this.use(this.#authenticatedViaGuard || this.defaultGuard).getUserOrFail();
|
|
77
|
+
}
|
|
71
78
|
/**
|
|
72
79
|
* Returns an instance of a known guard. Guards instances are
|
|
73
80
|
* cached during the lifecycle of an HTTP request.
|
|
@@ -116,7 +123,7 @@ export class Authenticator {
|
|
|
116
123
|
throw new AuthenticationException('Unauthorized access', {
|
|
117
124
|
code: 'E_UNAUTHORIZED_ACCESS',
|
|
118
125
|
guardDriverName: lastUsedGuardDriver,
|
|
119
|
-
redirectTo: options?.
|
|
126
|
+
redirectTo: options?.loginRoute,
|
|
120
127
|
});
|
|
121
128
|
}
|
|
122
129
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { GuardFactory } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Authenticator client is used to create guard instances for
|
|
4
|
+
* testing. It passes a fake HTTPContext to the guards, so
|
|
5
|
+
* make sure to not call server side APIs that might be
|
|
6
|
+
* relying on a real HTTPContext instance
|
|
7
|
+
*/
|
|
8
|
+
export declare class AuthenticatorClient<KnownGuards extends Record<string, GuardFactory>> {
|
|
9
|
+
#private;
|
|
10
|
+
/**
|
|
11
|
+
* Name of the default guard
|
|
12
|
+
*/
|
|
13
|
+
get defaultGuard(): keyof KnownGuards;
|
|
14
|
+
constructor(config: {
|
|
15
|
+
default: keyof KnownGuards;
|
|
16
|
+
guards: KnownGuards;
|
|
17
|
+
});
|
|
18
|
+
/**
|
|
19
|
+
* Returns an instance of a known guard. Guards instances are
|
|
20
|
+
* cached during the lifecycle of an HTTP request.
|
|
21
|
+
*/
|
|
22
|
+
use<Guard extends keyof KnownGuards>(guard?: Guard): ReturnType<KnownGuards[Guard]>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
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 debug from './debug.js';
|
|
10
|
+
import { HttpContextFactory } from '@adonisjs/core/factories/http';
|
|
11
|
+
/**
|
|
12
|
+
* Authenticator client is used to create guard instances for
|
|
13
|
+
* testing. It passes a fake HTTPContext to the guards, so
|
|
14
|
+
* make sure to not call server side APIs that might be
|
|
15
|
+
* relying on a real HTTPContext instance
|
|
16
|
+
*/
|
|
17
|
+
export class AuthenticatorClient {
|
|
18
|
+
/**
|
|
19
|
+
* Registered guards
|
|
20
|
+
*/
|
|
21
|
+
#config;
|
|
22
|
+
/**
|
|
23
|
+
* Cache of guards
|
|
24
|
+
*/
|
|
25
|
+
#guardsCache = {};
|
|
26
|
+
/**
|
|
27
|
+
* Name of the default guard
|
|
28
|
+
*/
|
|
29
|
+
get defaultGuard() {
|
|
30
|
+
return this.#config.default;
|
|
31
|
+
}
|
|
32
|
+
constructor(config) {
|
|
33
|
+
this.#config = config;
|
|
34
|
+
debug('creating authenticator client. config %O', this.#config);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Returns an instance of a known guard. Guards instances are
|
|
38
|
+
* cached during the lifecycle of an HTTP request.
|
|
39
|
+
*/
|
|
40
|
+
use(guard) {
|
|
41
|
+
const guardToUse = guard || this.#config.default;
|
|
42
|
+
/**
|
|
43
|
+
* Use cached copy if exists
|
|
44
|
+
*/
|
|
45
|
+
const cachedGuard = this.#guardsCache[guardToUse];
|
|
46
|
+
if (cachedGuard) {
|
|
47
|
+
debug('using guard from cache. name: "%s"', guardToUse);
|
|
48
|
+
return cachedGuard;
|
|
49
|
+
}
|
|
50
|
+
const guardFactory = this.#config.guards[guardToUse];
|
|
51
|
+
/**
|
|
52
|
+
* Construct guard and cache it
|
|
53
|
+
*/
|
|
54
|
+
debug('creating guard. name: "%s"', guardToUse);
|
|
55
|
+
const guardInstance = guardFactory(new HttpContextFactory().create());
|
|
56
|
+
this.#guardsCache[guardToUse] = guardInstance;
|
|
57
|
+
return guardInstance;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -5,11 +5,18 @@ import { HttpContext } from '@adonisjs/core/http';
|
|
|
5
5
|
* made to authenticate an HTTP request
|
|
6
6
|
*/
|
|
7
7
|
export declare class AuthenticationException extends Exception {
|
|
8
|
+
static status?: number | undefined;
|
|
9
|
+
static code?: string | undefined;
|
|
8
10
|
/**
|
|
9
11
|
* Raises authentication exception when session guard
|
|
10
12
|
* is unable to authenticate the request
|
|
11
13
|
*/
|
|
12
14
|
static E_INVALID_AUTH_SESSION(): AuthenticationException;
|
|
15
|
+
/**
|
|
16
|
+
* Raises authentication exception when session guard
|
|
17
|
+
* is unable to authenticate the request
|
|
18
|
+
*/
|
|
19
|
+
static E_INVALID_BASIC_AUTH_CREDENTIALS(): AuthenticationException;
|
|
13
20
|
guardDriverName: string;
|
|
14
21
|
redirectTo?: string;
|
|
15
22
|
identifier: string;
|
|
@@ -49,6 +56,7 @@ export declare class AuthenticationException extends Exception {
|
|
|
49
56
|
export declare class InvalidCredentialsException extends Exception {
|
|
50
57
|
static message: string;
|
|
51
58
|
static code: string;
|
|
59
|
+
static status?: number | undefined;
|
|
52
60
|
static E_INVALID_CREDENTIALS(guardDriverName: string): InvalidCredentialsException;
|
|
53
61
|
guardDriverName: string;
|
|
54
62
|
identifier: string;
|
package/build/src/auth/errors.js
CHANGED
|
@@ -12,6 +12,8 @@ import { Exception } from '@poppinss/utils';
|
|
|
12
12
|
* made to authenticate an HTTP request
|
|
13
13
|
*/
|
|
14
14
|
export class AuthenticationException extends Exception {
|
|
15
|
+
static status = 401;
|
|
16
|
+
static code = 'E_UNAUTHORIZED_ACCESS';
|
|
15
17
|
/**
|
|
16
18
|
* Raises authentication exception when session guard
|
|
17
19
|
* is unable to authenticate the request
|
|
@@ -23,6 +25,17 @@ export class AuthenticationException extends Exception {
|
|
|
23
25
|
guardDriverName: 'session',
|
|
24
26
|
});
|
|
25
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Raises authentication exception when session guard
|
|
30
|
+
* is unable to authenticate the request
|
|
31
|
+
*/
|
|
32
|
+
static E_INVALID_BASIC_AUTH_CREDENTIALS() {
|
|
33
|
+
return new AuthenticationException('Invalid basic auth credentials', {
|
|
34
|
+
code: 'E_INVALID_BASIC_AUTH_CREDENTIALS',
|
|
35
|
+
status: 401,
|
|
36
|
+
guardDriverName: 'basic_auth',
|
|
37
|
+
});
|
|
38
|
+
}
|
|
26
39
|
guardDriverName;
|
|
27
40
|
redirectTo;
|
|
28
41
|
identifier = 'auth.authenticate';
|
|
@@ -58,7 +71,7 @@ export class AuthenticationException extends Exception {
|
|
|
58
71
|
case 'html':
|
|
59
72
|
case null:
|
|
60
73
|
ctx.session.flashExcept(['_csrf']);
|
|
61
|
-
ctx.session.
|
|
74
|
+
ctx.session.flashErrors({ [error.identifier]: [message] });
|
|
62
75
|
ctx.response.redirect(error.redirectTo || '/', true);
|
|
63
76
|
break;
|
|
64
77
|
case 'json':
|
|
@@ -82,6 +95,12 @@ export class AuthenticationException extends Exception {
|
|
|
82
95
|
break;
|
|
83
96
|
}
|
|
84
97
|
},
|
|
98
|
+
basic_auth: (message, _, ctx) => {
|
|
99
|
+
ctx.response
|
|
100
|
+
.status(this.status)
|
|
101
|
+
.header('WWW-Authenticate', `Basic realm="Authenticate", charset="UTF-8"`)
|
|
102
|
+
.send(message);
|
|
103
|
+
},
|
|
85
104
|
};
|
|
86
105
|
/**
|
|
87
106
|
* Self handles the auth exception and converts it to an
|
|
@@ -103,6 +122,7 @@ export class AuthenticationException extends Exception {
|
|
|
103
122
|
export class InvalidCredentialsException extends Exception {
|
|
104
123
|
static message = 'Invalid credentials';
|
|
105
124
|
static code = 'E_INVALID_CREDENTIALS';
|
|
125
|
+
static status = 400;
|
|
106
126
|
static E_INVALID_CREDENTIALS(guardDriverName) {
|
|
107
127
|
return new InvalidCredentialsException(InvalidCredentialsException.message, {
|
|
108
128
|
guardDriverName,
|
|
@@ -141,7 +161,7 @@ export class InvalidCredentialsException extends Exception {
|
|
|
141
161
|
case 'html':
|
|
142
162
|
case null:
|
|
143
163
|
ctx.session.flashExcept(['_csrf']);
|
|
144
|
-
ctx.session.
|
|
164
|
+
ctx.session.flashErrors({ [this.identifier]: [message] });
|
|
145
165
|
ctx.response.redirect().withQs().back();
|
|
146
166
|
break;
|
|
147
167
|
case 'json':
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { PluginFn } from '@japa/runner/types';
|
|
2
|
+
import type { ApplicationService } from '@adonisjs/core/types';
|
|
3
|
+
import type { Authenticators, GuardContract, GuardFactory } from '../../types.js';
|
|
4
|
+
declare module '@japa/api-client' {
|
|
5
|
+
interface ApiRequest {
|
|
6
|
+
authData: {
|
|
7
|
+
guard: string;
|
|
8
|
+
user: unknown;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Login a user using the default authentication
|
|
12
|
+
* guard when making an API call
|
|
13
|
+
*/
|
|
14
|
+
loginAs(user: {
|
|
15
|
+
[K in keyof Authenticators]: Authenticators[K] extends GuardFactory ? ReturnType<Authenticators[K]> extends GuardContract<infer A> ? A : never : never;
|
|
16
|
+
}): this;
|
|
17
|
+
/**
|
|
18
|
+
* Define the authentication guard for login
|
|
19
|
+
*/
|
|
20
|
+
withGuard<K extends keyof Authenticators, Self extends ApiRequest>(this: Self, guard: K): {
|
|
21
|
+
/**
|
|
22
|
+
* Login a user using a specific auth guard
|
|
23
|
+
*/
|
|
24
|
+
loginAs(user: Authenticators[K] extends GuardFactory ? ReturnType<Authenticators[K]> extends GuardContract<infer A> ? A : never : never): Self;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Auth API client to authenticate users when making
|
|
30
|
+
* HTTP requests using the Japa API client
|
|
31
|
+
*/
|
|
32
|
+
export declare const authApiClient: (app: ApplicationService) => PluginFn;
|
|
@@ -0,0 +1,63 @@
|
|
|
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 { ApiClient, ApiRequest } from '@japa/api-client';
|
|
10
|
+
import debug from '../../debug.js';
|
|
11
|
+
/**
|
|
12
|
+
* Auth API client to authenticate users when making
|
|
13
|
+
* HTTP requests using the Japa API client
|
|
14
|
+
*/
|
|
15
|
+
export const authApiClient = (app) => {
|
|
16
|
+
const pluginFn = function () {
|
|
17
|
+
debug('installing auth api client plugin');
|
|
18
|
+
ApiRequest.macro('loginAs', function (user) {
|
|
19
|
+
this.authData = {
|
|
20
|
+
guard: '__default__',
|
|
21
|
+
user: user,
|
|
22
|
+
};
|
|
23
|
+
return this;
|
|
24
|
+
});
|
|
25
|
+
ApiRequest.macro('withGuard', function (guard) {
|
|
26
|
+
return {
|
|
27
|
+
loginAs: (user) => {
|
|
28
|
+
this.authData = {
|
|
29
|
+
guard,
|
|
30
|
+
user: user,
|
|
31
|
+
};
|
|
32
|
+
return this;
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* Hook into the request and login the user
|
|
38
|
+
*/
|
|
39
|
+
ApiClient.setup(async (request) => {
|
|
40
|
+
const auth = await app.container.make('auth.manager');
|
|
41
|
+
const authData = request['authData'];
|
|
42
|
+
if (!authData) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const client = auth.createAuthenticatorClient();
|
|
46
|
+
const guard = authData.guard === '__default__' ? client.use() : client.use(authData.guard);
|
|
47
|
+
const requestData = await guard.authenticateAsClient(authData.user);
|
|
48
|
+
if (requestData.headers) {
|
|
49
|
+
debug('defining headers with api client request %O', requestData.headers);
|
|
50
|
+
request.headers(requestData.headers);
|
|
51
|
+
}
|
|
52
|
+
if (requestData.session) {
|
|
53
|
+
debug('defining session with api client request %O', requestData.session);
|
|
54
|
+
request.withSession(requestData.session);
|
|
55
|
+
}
|
|
56
|
+
if (requestData.cookies) {
|
|
57
|
+
debug('defining session with api client request %O', requestData.session);
|
|
58
|
+
request.cookies(requestData.cookies);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
return pluginFn;
|
|
63
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { PluginFn } from '@japa/runner/types';
|
|
2
|
+
import type { ApplicationService } from '@adonisjs/core/types';
|
|
3
|
+
import type { Authenticators, GuardContract, GuardFactory } from '../../types.js';
|
|
4
|
+
declare module 'playwright' {
|
|
5
|
+
interface BrowserContext {
|
|
6
|
+
/**
|
|
7
|
+
* Login a user using the default authentication
|
|
8
|
+
* guard when using the browser context to
|
|
9
|
+
* make page visits
|
|
10
|
+
*/
|
|
11
|
+
loginAs(user: {
|
|
12
|
+
[K in keyof Authenticators]: Authenticators[K] extends GuardFactory ? ReturnType<Authenticators[K]> extends GuardContract<infer A> ? A : never : never;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Define the authentication guard for login
|
|
16
|
+
*/
|
|
17
|
+
withGuard<K extends keyof Authenticators>(guard: K): {
|
|
18
|
+
/**
|
|
19
|
+
* Login a user using a specific auth guard
|
|
20
|
+
*/
|
|
21
|
+
loginAs(user: Authenticators[K] extends GuardFactory ? ReturnType<Authenticators[K]> extends GuardContract<infer A> ? A : never : never): Promise<void>;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export declare const authBrowserClient: (app: ApplicationService) => PluginFn;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @adoniss/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
|
+
/// <reference types="@japa/plugin-adonisjs" />
|
|
10
|
+
/// <reference types="@adonisjs/session/plugins/browser_client" />
|
|
11
|
+
import { RuntimeException } from '@poppinss/utils';
|
|
12
|
+
import { decoratorsCollection } from '@japa/browser-client';
|
|
13
|
+
import debug from '../../debug.js';
|
|
14
|
+
export const authBrowserClient = (app) => {
|
|
15
|
+
const pluginFn = async function () {
|
|
16
|
+
debug('installing auth browser client plugin');
|
|
17
|
+
const auth = await app.container.make('auth.manager');
|
|
18
|
+
decoratorsCollection.register({
|
|
19
|
+
context(context) {
|
|
20
|
+
context.withGuard = function (guardName) {
|
|
21
|
+
return {
|
|
22
|
+
async loginAs(user) {
|
|
23
|
+
const client = auth.createAuthenticatorClient();
|
|
24
|
+
const guard = client.use(guardName);
|
|
25
|
+
const requestData = await guard.authenticateAsClient(user);
|
|
26
|
+
if (requestData.headers) {
|
|
27
|
+
throw new RuntimeException(`Cannot use "${guard.driverName}" guard with browser client`);
|
|
28
|
+
}
|
|
29
|
+
if (requestData.cookies) {
|
|
30
|
+
debug('defining cookies with browser context %O', requestData.cookies);
|
|
31
|
+
Object.keys(requestData.cookies).forEach((cookie) => {
|
|
32
|
+
context.setCookie(cookie, requestData.cookies[cookie]);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
if (requestData.session) {
|
|
36
|
+
debug('defining session with browser context %O', requestData.session);
|
|
37
|
+
context.setSession(requestData.session);
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
context.loginAs = async function (user) {
|
|
43
|
+
const client = auth.createAuthenticatorClient();
|
|
44
|
+
const guard = client.use();
|
|
45
|
+
const requestData = await guard.authenticateAsClient(user);
|
|
46
|
+
if (requestData.headers) {
|
|
47
|
+
throw new RuntimeException(`Cannot use "${guard.driverName}" guard with browser client`);
|
|
48
|
+
}
|
|
49
|
+
if (requestData.cookies) {
|
|
50
|
+
debug('defining cookies with browser context %O', requestData.cookies);
|
|
51
|
+
Object.keys(requestData.cookies).forEach((cookie) => {
|
|
52
|
+
context.setCookie(cookie, requestData.cookies[cookie]);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (requestData.session) {
|
|
56
|
+
debug('defining session with browser context %O', requestData.session);
|
|
57
|
+
context.setSession(requestData.session);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
return pluginFn;
|
|
64
|
+
};
|
|
@@ -2,6 +2,14 @@ import type { HttpContext } from '@adonisjs/core/http';
|
|
|
2
2
|
import type { ApplicationService, ConfigProvider } from '@adonisjs/core/types';
|
|
3
3
|
import type { AuthManager } from './auth_manager.js';
|
|
4
4
|
import type { GUARD_KNOWN_EVENTS } from './symbols.js';
|
|
5
|
+
/**
|
|
6
|
+
* The client response for authentication.
|
|
7
|
+
*/
|
|
8
|
+
export interface AuthClientResponse {
|
|
9
|
+
headers?: Record<string, any>;
|
|
10
|
+
cookies?: Record<string, any>;
|
|
11
|
+
session?: Record<string, any>;
|
|
12
|
+
}
|
|
5
13
|
/**
|
|
6
14
|
* A set of properties a guard must implement.
|
|
7
15
|
*/
|
|
@@ -10,6 +18,10 @@ export interface GuardContract<User> {
|
|
|
10
18
|
* Reference to the currently authenticated user
|
|
11
19
|
*/
|
|
12
20
|
user?: User;
|
|
21
|
+
/**
|
|
22
|
+
* Returns logged-in user or throws an exception
|
|
23
|
+
*/
|
|
24
|
+
getUserOrFail(): User;
|
|
13
25
|
/**
|
|
14
26
|
* A boolean to know if the current request has
|
|
15
27
|
* been authenticated
|
|
@@ -26,6 +38,12 @@ export interface GuardContract<User> {
|
|
|
26
38
|
* exception
|
|
27
39
|
*/
|
|
28
40
|
check(): Promise<boolean>;
|
|
41
|
+
/**
|
|
42
|
+
* The method is used to authenticate the user as
|
|
43
|
+
* client. This method should return cookies,
|
|
44
|
+
* headers, or session state.
|
|
45
|
+
*/
|
|
46
|
+
authenticateAsClient(user: User): Promise<AuthClientResponse>;
|
|
29
47
|
/**
|
|
30
48
|
* Authenticates the current request and throws
|
|
31
49
|
* an exception if the request is not authenticated.
|
|
@@ -60,6 +78,16 @@ export type InferAuthenticators<Config extends ConfigProvider<{
|
|
|
60
78
|
default: unknown;
|
|
61
79
|
guards: unknown;
|
|
62
80
|
}>> = Awaited<ReturnType<Config['resolver']>>['guards'];
|
|
81
|
+
/**
|
|
82
|
+
* Helper to convert union to intersection
|
|
83
|
+
*/
|
|
84
|
+
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
85
|
+
/**
|
|
86
|
+
* Infer events based upon the configure authenticators
|
|
87
|
+
*/
|
|
88
|
+
export type InferAuthEvents<KnownAuthenticators extends Record<string, GuardFactory>> = UnionToIntersection<{
|
|
89
|
+
[K in keyof KnownAuthenticators]: ReturnType<KnownAuthenticators[K]>[typeof GUARD_KNOWN_EVENTS];
|
|
90
|
+
}[keyof KnownAuthenticators]>;
|
|
63
91
|
/**
|
|
64
92
|
* Auth service is a singleton instance of the AuthManager
|
|
65
93
|
* configured using the config stored within the user
|
|
@@ -73,3 +101,4 @@ export interface AuthService extends AuthManager<Authenticators extends Record<s
|
|
|
73
101
|
export type GuardConfigProvider<Guard extends GuardFactory> = {
|
|
74
102
|
resolver: (name: string, app: ApplicationService) => Promise<Guard>;
|
|
75
103
|
};
|
|
104
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
2
|
+
import type { ConfigProvider } from '@adonisjs/core/types';
|
|
3
|
+
import type { GuardConfigProvider } from '../../auth/types.js';
|
|
4
|
+
import type { UserProviderContract } from '../../core/types.js';
|
|
5
|
+
import { BasicAuthGuard } from './guard.js';
|
|
6
|
+
/**
|
|
7
|
+
* Helper function to configure the basic auth guard for
|
|
8
|
+
* authentication.
|
|
9
|
+
*
|
|
10
|
+
* This method returns a config builder, which internally
|
|
11
|
+
* returns a factory function to construct a guard
|
|
12
|
+
* during HTTP requests.
|
|
13
|
+
*/
|
|
14
|
+
export declare function basicAuthGuard<UserProvider extends UserProviderContract<unknown>>(config: {
|
|
15
|
+
provider: ConfigProvider<UserProvider>;
|
|
16
|
+
}): GuardConfigProvider<(ctx: HttpContext) => BasicAuthGuard<UserProvider>>;
|