@spinajs/rbac-http-user 2.0.486 → 2.0.487
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/lib/cjs/config/rbac-http.d.ts +0 -15
- package/lib/cjs/config/rbac-http.d.ts.map +1 -1
- package/lib/cjs/config/rbac-http.js +6 -16
- package/lib/cjs/config/rbac-http.js.map +1 -1
- package/lib/cjs/controllers/ActiveRoleController.d.ts +2 -1
- package/lib/cjs/controllers/ActiveRoleController.d.ts.map +1 -1
- package/lib/cjs/controllers/ActiveRoleController.js +7 -17
- package/lib/cjs/controllers/ActiveRoleController.js.map +1 -1
- package/lib/cjs/controllers/ImpersonationController.d.ts +7 -9
- package/lib/cjs/controllers/ImpersonationController.d.ts.map +1 -1
- package/lib/cjs/controllers/ImpersonationController.js +31 -56
- package/lib/cjs/controllers/ImpersonationController.js.map +1 -1
- package/lib/cjs/controllers/LoginController.d.ts +10 -3
- package/lib/cjs/controllers/LoginController.d.ts.map +1 -1
- package/lib/cjs/controllers/LoginController.js +39 -40
- package/lib/cjs/controllers/LoginController.js.map +1 -1
- package/lib/cjs/controllers/PasswordResetController.d.ts +54 -0
- package/lib/cjs/controllers/PasswordResetController.d.ts.map +1 -0
- package/lib/cjs/controllers/PasswordResetController.js +129 -0
- package/lib/cjs/controllers/PasswordResetController.js.map +1 -0
- package/lib/cjs/controllers/SessionsController.d.ts +65 -0
- package/lib/cjs/controllers/SessionsController.d.ts.map +1 -0
- package/lib/cjs/controllers/SessionsController.js +143 -0
- package/lib/cjs/controllers/SessionsController.js.map +1 -0
- package/lib/cjs/controllers/TwoFactorAuthController.d.ts +24 -23
- package/lib/cjs/controllers/TwoFactorAuthController.d.ts.map +1 -1
- package/lib/cjs/controllers/TwoFactorAuthController.js +39 -72
- package/lib/cjs/controllers/TwoFactorAuthController.js.map +1 -1
- package/lib/cjs/controllers/TwoFactorAuthUserController.d.ts +98 -0
- package/lib/cjs/controllers/TwoFactorAuthUserController.d.ts.map +1 -0
- package/lib/cjs/controllers/TwoFactorAuthUserController.js +195 -0
- package/lib/cjs/controllers/TwoFactorAuthUserController.js.map +1 -0
- package/lib/cjs/controllers/UserController.d.ts +10 -7
- package/lib/cjs/controllers/UserController.d.ts.map +1 -1
- package/lib/cjs/controllers/UserController.js +56 -58
- package/lib/cjs/controllers/UserController.js.map +1 -1
- package/lib/cjs/controllers/UserMetadataController.d.ts +6 -12
- package/lib/cjs/controllers/UserMetadataController.d.ts.map +1 -1
- package/lib/cjs/controllers/UserMetadataController.js +23 -72
- package/lib/cjs/controllers/UserMetadataController.js.map +1 -1
- package/lib/cjs/dto/confirm-password-dto.d.ts +23 -0
- package/lib/cjs/dto/confirm-password-dto.d.ts.map +1 -0
- package/lib/cjs/dto/{restore-password-dto.js → confirm-password-dto.js} +16 -12
- package/lib/cjs/dto/confirm-password-dto.js.map +1 -0
- package/lib/cjs/dto/password-reset-dto.d.ts +58 -0
- package/lib/cjs/dto/password-reset-dto.d.ts.map +1 -0
- package/lib/cjs/dto/password-reset-dto.js +57 -0
- package/lib/cjs/dto/password-reset-dto.js.map +1 -0
- package/lib/cjs/handlers/DefaultLogoutHandler.d.ts +4 -1
- package/lib/cjs/handlers/DefaultLogoutHandler.d.ts.map +1 -1
- package/lib/cjs/handlers/DefaultLogoutHandler.js +20 -13
- package/lib/cjs/handlers/DefaultLogoutHandler.js.map +1 -1
- package/lib/cjs/handlers/ImpersonationLogoutHandler.d.ts +4 -7
- package/lib/cjs/handlers/ImpersonationLogoutHandler.d.ts.map +1 -1
- package/lib/cjs/handlers/ImpersonationLogoutHandler.js +30 -31
- package/lib/cjs/handlers/ImpersonationLogoutHandler.js.map +1 -1
- package/lib/cjs/index.d.ts +20 -0
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +22 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/logout.d.ts +7 -0
- package/lib/cjs/logout.d.ts.map +1 -1
- package/lib/cjs/logout.js.map +1 -1
- package/lib/cjs/policies/2FaPolicy.d.ts +21 -1
- package/lib/cjs/policies/2FaPolicy.d.ts.map +1 -1
- package/lib/cjs/policies/2FaPolicy.js +31 -7
- package/lib/cjs/policies/2FaPolicy.js.map +1 -1
- package/lib/cjs/services/ImpersonationService.d.ts +90 -0
- package/lib/cjs/services/ImpersonationService.d.ts.map +1 -0
- package/lib/cjs/services/ImpersonationService.js +147 -0
- package/lib/cjs/services/ImpersonationService.js.map +1 -0
- package/lib/cjs/services/SessionCookies.d.ts +41 -0
- package/lib/cjs/services/SessionCookies.d.ts.map +1 -0
- package/lib/cjs/services/SessionCookies.js +62 -0
- package/lib/cjs/services/SessionCookies.js.map +1 -0
- package/lib/cjs/services/UserMetadataService.d.ts +53 -0
- package/lib/cjs/services/UserMetadataService.d.ts.map +1 -0
- package/lib/cjs/services/UserMetadataService.js +94 -0
- package/lib/cjs/services/UserMetadataService.js.map +1 -0
- package/lib/cjs/services/grants.d.ts +29 -0
- package/lib/cjs/services/grants.d.ts.map +1 -0
- package/lib/cjs/services/grants.js +43 -0
- package/lib/cjs/services/grants.js.map +1 -0
- package/lib/mjs/config/rbac-http.d.ts +0 -15
- package/lib/mjs/config/rbac-http.d.ts.map +1 -1
- package/lib/mjs/config/rbac-http.js +6 -16
- package/lib/mjs/config/rbac-http.js.map +1 -1
- package/lib/mjs/controllers/ActiveRoleController.d.ts +2 -1
- package/lib/mjs/controllers/ActiveRoleController.d.ts.map +1 -1
- package/lib/mjs/controllers/ActiveRoleController.js +8 -18
- package/lib/mjs/controllers/ActiveRoleController.js.map +1 -1
- package/lib/mjs/controllers/ImpersonationController.d.ts +7 -9
- package/lib/mjs/controllers/ImpersonationController.d.ts.map +1 -1
- package/lib/mjs/controllers/ImpersonationController.js +32 -57
- package/lib/mjs/controllers/ImpersonationController.js.map +1 -1
- package/lib/mjs/controllers/LoginController.d.ts +10 -3
- package/lib/mjs/controllers/LoginController.d.ts.map +1 -1
- package/lib/mjs/controllers/LoginController.js +42 -43
- package/lib/mjs/controllers/LoginController.js.map +1 -1
- package/lib/mjs/controllers/PasswordResetController.d.ts +54 -0
- package/lib/mjs/controllers/PasswordResetController.d.ts.map +1 -0
- package/lib/mjs/controllers/PasswordResetController.js +126 -0
- package/lib/mjs/controllers/PasswordResetController.js.map +1 -0
- package/lib/mjs/controllers/SessionsController.d.ts +65 -0
- package/lib/mjs/controllers/SessionsController.d.ts.map +1 -0
- package/lib/mjs/controllers/SessionsController.js +140 -0
- package/lib/mjs/controllers/SessionsController.js.map +1 -0
- package/lib/mjs/controllers/TwoFactorAuthController.d.ts +24 -23
- package/lib/mjs/controllers/TwoFactorAuthController.d.ts.map +1 -1
- package/lib/mjs/controllers/TwoFactorAuthController.js +43 -76
- package/lib/mjs/controllers/TwoFactorAuthController.js.map +1 -1
- package/lib/mjs/controllers/TwoFactorAuthUserController.d.ts +98 -0
- package/lib/mjs/controllers/TwoFactorAuthUserController.d.ts.map +1 -0
- package/lib/mjs/controllers/TwoFactorAuthUserController.js +192 -0
- package/lib/mjs/controllers/TwoFactorAuthUserController.js.map +1 -0
- package/lib/mjs/controllers/UserController.d.ts +10 -7
- package/lib/mjs/controllers/UserController.d.ts.map +1 -1
- package/lib/mjs/controllers/UserController.js +59 -28
- package/lib/mjs/controllers/UserController.js.map +1 -1
- package/lib/mjs/controllers/UserMetadataController.d.ts +6 -12
- package/lib/mjs/controllers/UserMetadataController.d.ts.map +1 -1
- package/lib/mjs/controllers/UserMetadataController.js +23 -72
- package/lib/mjs/controllers/UserMetadataController.js.map +1 -1
- package/lib/mjs/dto/confirm-password-dto.d.ts +23 -0
- package/lib/mjs/dto/confirm-password-dto.d.ts.map +1 -0
- package/lib/mjs/dto/{user-dto.js → confirm-password-dto.js} +15 -10
- package/lib/mjs/dto/confirm-password-dto.js.map +1 -0
- package/lib/mjs/dto/password-reset-dto.d.ts +58 -0
- package/lib/mjs/dto/password-reset-dto.d.ts.map +1 -0
- package/lib/mjs/dto/password-reset-dto.js +54 -0
- package/lib/mjs/dto/password-reset-dto.js.map +1 -0
- package/lib/mjs/handlers/DefaultLogoutHandler.d.ts +4 -1
- package/lib/mjs/handlers/DefaultLogoutHandler.d.ts.map +1 -1
- package/lib/mjs/handlers/DefaultLogoutHandler.js +23 -16
- package/lib/mjs/handlers/DefaultLogoutHandler.js.map +1 -1
- package/lib/mjs/handlers/ImpersonationLogoutHandler.d.ts +4 -7
- package/lib/mjs/handlers/ImpersonationLogoutHandler.d.ts.map +1 -1
- package/lib/mjs/handlers/ImpersonationLogoutHandler.js +31 -32
- package/lib/mjs/handlers/ImpersonationLogoutHandler.js.map +1 -1
- package/lib/mjs/index.d.ts +20 -0
- package/lib/mjs/index.d.ts.map +1 -1
- package/lib/mjs/index.js +22 -0
- package/lib/mjs/index.js.map +1 -1
- package/lib/mjs/logout.d.ts +7 -0
- package/lib/mjs/logout.d.ts.map +1 -1
- package/lib/mjs/logout.js.map +1 -1
- package/lib/mjs/policies/2FaPolicy.d.ts +21 -1
- package/lib/mjs/policies/2FaPolicy.d.ts.map +1 -1
- package/lib/mjs/policies/2FaPolicy.js +29 -6
- package/lib/mjs/policies/2FaPolicy.js.map +1 -1
- package/lib/mjs/services/ImpersonationService.d.ts +90 -0
- package/lib/mjs/services/ImpersonationService.d.ts.map +1 -0
- package/lib/mjs/services/ImpersonationService.js +144 -0
- package/lib/mjs/services/ImpersonationService.js.map +1 -0
- package/lib/mjs/services/SessionCookies.d.ts +41 -0
- package/lib/mjs/services/SessionCookies.d.ts.map +1 -0
- package/lib/mjs/services/SessionCookies.js +59 -0
- package/lib/mjs/services/SessionCookies.js.map +1 -0
- package/lib/mjs/services/UserMetadataService.d.ts +53 -0
- package/lib/mjs/services/UserMetadataService.d.ts.map +1 -0
- package/lib/mjs/services/UserMetadataService.js +91 -0
- package/lib/mjs/services/UserMetadataService.js.map +1 -0
- package/lib/mjs/services/grants.d.ts +29 -0
- package/lib/mjs/services/grants.d.ts.map +1 -0
- package/lib/mjs/services/grants.js +38 -0
- package/lib/mjs/services/grants.js.map +1 -0
- package/lib/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/tsconfig.mjs.tsbuildinfo +1 -1
- package/package.json +17 -11
- package/lib/cjs/controllers/AuthController.d.ts +0 -1
- package/lib/cjs/controllers/AuthController.d.ts.map +0 -1
- package/lib/cjs/controllers/AuthController.js +0 -211
- package/lib/cjs/controllers/AuthController.js.map +0 -1
- package/lib/cjs/controllers/FederatedLoginController.d.ts +0 -1
- package/lib/cjs/controllers/FederatedLoginController.d.ts.map +0 -1
- package/lib/cjs/controllers/FederatedLoginController.js +0 -38
- package/lib/cjs/controllers/FederatedLoginController.js.map +0 -1
- package/lib/cjs/dto/login-dto.d.ts +0 -17
- package/lib/cjs/dto/login-dto.d.ts.map +0 -1
- package/lib/cjs/dto/login-dto.js +0 -33
- package/lib/cjs/dto/login-dto.js.map +0 -1
- package/lib/cjs/dto/restore-password-dto.d.ts +0 -24
- package/lib/cjs/dto/restore-password-dto.d.ts.map +0 -1
- package/lib/cjs/dto/restore-password-dto.js.map +0 -1
- package/lib/cjs/dto/user-dto.d.ts +0 -22
- package/lib/cjs/dto/user-dto.d.ts.map +0 -1
- package/lib/cjs/dto/user-dto.js +0 -33
- package/lib/cjs/dto/user-dto.js.map +0 -1
- package/lib/cjs/fingerprint/FingerprintJs.d.ts +0 -1
- package/lib/cjs/fingerprint/FingerprintJs.d.ts.map +0 -1
- package/lib/cjs/fingerprint/FingerprintJs.js +0 -5
- package/lib/cjs/fingerprint/FingerprintJs.js.map +0 -1
- package/lib/cjs/middlewares/AttributeFilter.d.ts +0 -11
- package/lib/cjs/middlewares/AttributeFilter.d.ts.map +0 -1
- package/lib/cjs/middlewares/AttributeFilter.js +0 -19
- package/lib/cjs/middlewares/AttributeFilter.js.map +0 -1
- package/lib/cjs/policies/AllowFederatedLoginPolicy.d.ts +0 -7
- package/lib/cjs/policies/AllowFederatedLoginPolicy.d.ts.map +0 -1
- package/lib/cjs/policies/AllowFederatedLoginPolicy.js +0 -32
- package/lib/cjs/policies/AllowFederatedLoginPolicy.js.map +0 -1
- package/lib/cjs/policies/CaptchaPolicy.d.ts +0 -1
- package/lib/cjs/policies/CaptchaPolicy.d.ts.map +0 -1
- package/lib/cjs/policies/CaptchaPolicy.js +0 -1
- package/lib/cjs/policies/CaptchaPolicy.js.map +0 -1
- package/lib/mjs/controllers/AuthController.d.ts +0 -2
- package/lib/mjs/controllers/AuthController.d.ts.map +0 -1
- package/lib/mjs/controllers/AuthController.js +0 -212
- package/lib/mjs/controllers/AuthController.js.map +0 -1
- package/lib/mjs/controllers/FederatedLoginController.d.ts +0 -2
- package/lib/mjs/controllers/FederatedLoginController.d.ts.map +0 -1
- package/lib/mjs/controllers/FederatedLoginController.js +0 -39
- package/lib/mjs/controllers/FederatedLoginController.js.map +0 -1
- package/lib/mjs/dto/login-dto.d.ts +0 -17
- package/lib/mjs/dto/login-dto.d.ts.map +0 -1
- package/lib/mjs/dto/login-dto.js +0 -30
- package/lib/mjs/dto/login-dto.js.map +0 -1
- package/lib/mjs/dto/restore-password-dto.d.ts +0 -24
- package/lib/mjs/dto/restore-password-dto.d.ts.map +0 -1
- package/lib/mjs/dto/restore-password-dto.js +0 -31
- package/lib/mjs/dto/restore-password-dto.js.map +0 -1
- package/lib/mjs/dto/user-dto.d.ts +0 -22
- package/lib/mjs/dto/user-dto.d.ts.map +0 -1
- package/lib/mjs/dto/user-dto.js.map +0 -1
- package/lib/mjs/fingerprint/FingerprintJs.d.ts +0 -2
- package/lib/mjs/fingerprint/FingerprintJs.d.ts.map +0 -1
- package/lib/mjs/fingerprint/FingerprintJs.js +0 -6
- package/lib/mjs/fingerprint/FingerprintJs.js.map +0 -1
- package/lib/mjs/middlewares/AttributeFilter.d.ts +0 -11
- package/lib/mjs/middlewares/AttributeFilter.d.ts.map +0 -1
- package/lib/mjs/middlewares/AttributeFilter.js +0 -15
- package/lib/mjs/middlewares/AttributeFilter.js.map +0 -1
- package/lib/mjs/policies/AllowFederatedLoginPolicy.d.ts +0 -7
- package/lib/mjs/policies/AllowFederatedLoginPolicy.d.ts.map +0 -1
- package/lib/mjs/policies/AllowFederatedLoginPolicy.js +0 -28
- package/lib/mjs/policies/AllowFederatedLoginPolicy.js.map +0 -1
- package/lib/mjs/policies/CaptchaPolicy.d.ts +0 -2
- package/lib/mjs/policies/CaptchaPolicy.d.ts.map +0 -1
- package/lib/mjs/policies/CaptchaPolicy.js +0 -2
- package/lib/mjs/policies/CaptchaPolicy.js.map +0 -1
|
@@ -22,6 +22,9 @@ const configuration_1 = require("@spinajs/configuration");
|
|
|
22
22
|
const rbac_http_1 = require("@spinajs/rbac-http");
|
|
23
23
|
const rbac_2 = require("@spinajs/rbac");
|
|
24
24
|
const logout_js_1 = require("../logout.js");
|
|
25
|
+
const SessionCookies_js_1 = require("../services/SessionCookies.js");
|
|
26
|
+
const grants_js_1 = require("../services/grants.js");
|
|
27
|
+
const Default2FaToken_js_1 = require("../2fa/Default2FaToken.js");
|
|
25
28
|
/**
|
|
26
29
|
* Authentication endpoints.
|
|
27
30
|
* Handles user login, logout, and current-session inspection.
|
|
@@ -62,7 +65,8 @@ let LoginController = class LoginController extends http_1.BaseController {
|
|
|
62
65
|
// user is automatically authorized at login
|
|
63
66
|
session.Data.set('Logged', true);
|
|
64
67
|
session.UserId = user.Id;
|
|
65
|
-
|
|
68
|
+
const twoFaEnabledForUser = Boolean(user.Metadata[Default2FaToken_js_1.TWO_FA_METATADATA_KEYS.ENABLED]);
|
|
69
|
+
if (this.TwoFactorAuthForceUser && !twoFaEnabledForUser) {
|
|
66
70
|
this._log.trace('User logged in, 2fa init required', {
|
|
67
71
|
Uuid: user.Uuid
|
|
68
72
|
});
|
|
@@ -70,7 +74,7 @@ let LoginController = class LoginController extends http_1.BaseController {
|
|
|
70
74
|
session.Data.set('TwoFactorAuth', true);
|
|
71
75
|
result = { TwoFactorInitRequired: true };
|
|
72
76
|
}
|
|
73
|
-
else if (this.TwoFactorAuthEnabled &&
|
|
77
|
+
else if (this.TwoFactorAuthEnabled && twoFaEnabledForUser) {
|
|
74
78
|
this._log.trace('User logged in, 2fa required', {
|
|
75
79
|
Uuid: user.Uuid
|
|
76
80
|
});
|
|
@@ -80,40 +84,25 @@ let LoginController = class LoginController extends http_1.BaseController {
|
|
|
80
84
|
}
|
|
81
85
|
else {
|
|
82
86
|
session.Data.set('Authorized', true);
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
result = {
|
|
88
|
-
...user.dehydrateWithRelations({ dateTimeFormat: "iso" }),
|
|
89
|
-
Role: user.Role, // temp fix for role grants, as dehydrateWithRelations returns string of roles, not array
|
|
90
|
-
ActiveRole: activeRole,
|
|
91
|
-
Grants: combinedGrants,
|
|
92
|
-
};
|
|
87
|
+
this._log.trace('User logged in, no 2fa required', {
|
|
88
|
+
Uuid: user.Uuid
|
|
89
|
+
});
|
|
90
|
+
result = (0, grants_js_1.buildUserWithGrants)(user, activeRole, this.AC);
|
|
93
91
|
}
|
|
94
|
-
this._log.trace('User logged in, no 2fa required', {
|
|
95
|
-
Uuid: user.Uuid
|
|
96
|
-
});
|
|
97
92
|
// save() schedules the session's initial expiration via the configured
|
|
98
93
|
// strategy; the cookie maxAge is then derived from that real expiry (B1),
|
|
99
94
|
// no longer the bogus `expiration * 1000` (~2 min) value.
|
|
100
95
|
await this.SessionProvider.save(session);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
signed: true,
|
|
107
|
-
httpOnly: true,
|
|
108
|
-
// cookie lifetime tracks the session's real expiration
|
|
109
|
-
maxAge: (0, rbac_1.sessionCookieMaxAge)(session),
|
|
110
|
-
// any optional cookie options / override default ones
|
|
111
|
-
...this.SessionCookieConfig
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
];
|
|
96
|
+
this._log.info(`Session created`, {
|
|
97
|
+
// never the raw id — a log file must not be a bag of live credentials
|
|
98
|
+
Session: (0, rbac_1.hashSessionId)(session.SessionId),
|
|
99
|
+
User: user.Uuid,
|
|
100
|
+
});
|
|
115
101
|
return new http_1.Ok(result, {
|
|
116
|
-
Coockies:
|
|
102
|
+
Coockies: [this.SessionCookies.issue(session)],
|
|
103
|
+
// The response carries the session id in a Set-Cookie and the user's
|
|
104
|
+
// own data in the body. Neither may be written to any cache.
|
|
105
|
+
Headers: [{ Name: 'Cache-Control', Value: 'no-store' }],
|
|
117
106
|
});
|
|
118
107
|
}
|
|
119
108
|
catch (err) {
|
|
@@ -145,6 +134,10 @@ let LoginController = class LoginController extends http_1.BaseController {
|
|
|
145
134
|
* If an impersonation is active, the session is NOT destroyed — instead the
|
|
146
135
|
* impersonation is ended and the original user resumes their session.
|
|
147
136
|
* Requires the user to be logged in (session exists), but full authorization (2FA) is not required.
|
|
137
|
+
*
|
|
138
|
+
* POST, not GET: under `SameSite=Lax` a cookie rides a top-level cross-site
|
|
139
|
+
* GET, so a third-party page could log any visitor out simply by linking to
|
|
140
|
+
* this route.
|
|
148
141
|
* @security cookieAuth
|
|
149
142
|
* @response 401 No active session
|
|
150
143
|
*/
|
|
@@ -166,7 +159,10 @@ let LoginController = class LoginController extends http_1.BaseController {
|
|
|
166
159
|
for (const handler of sorted) {
|
|
167
160
|
const result = await handler.handle(ctx);
|
|
168
161
|
if (result) {
|
|
169
|
-
return new http_1.Ok(result.Body ?? null, {
|
|
162
|
+
return new http_1.Ok(result.Body ?? null, {
|
|
163
|
+
Coockies: result.Cookies ?? [],
|
|
164
|
+
Headers: result.Headers ?? [],
|
|
165
|
+
});
|
|
170
166
|
}
|
|
171
167
|
}
|
|
172
168
|
// No handler claimed the request — should not happen as long as the
|
|
@@ -176,16 +172,18 @@ let LoginController = class LoginController extends http_1.BaseController {
|
|
|
176
172
|
/**
|
|
177
173
|
* Get current user
|
|
178
174
|
* Returns the user object associated with the current session along with the
|
|
179
|
-
* currently active role
|
|
175
|
+
* currently active role and whether the session has completed 2FA (when
|
|
176
|
+
* required). Roles the user may switch to are listed in Role.
|
|
180
177
|
* Requires the user to be logged in (session exists), but full authorization (2FA) is not required.
|
|
181
178
|
* @security cookieAuth
|
|
182
179
|
* @returns {User} User data from the current session
|
|
183
180
|
* @response 401 No active session
|
|
184
181
|
*/
|
|
185
|
-
async whoami(User, ActiveRole) {
|
|
182
|
+
async whoami(User, ActiveRole, session) {
|
|
186
183
|
return new http_1.Ok({
|
|
187
184
|
...User.dehydrateWithRelations({ dateTimeFormat: 'iso' }),
|
|
188
185
|
ActiveRole: ActiveRole ?? User.Role?.[0],
|
|
186
|
+
Authorized: session.Data.get('Authorized') ?? true,
|
|
189
187
|
});
|
|
190
188
|
}
|
|
191
189
|
};
|
|
@@ -215,9 +213,9 @@ __decorate([
|
|
|
215
213
|
__metadata("design:type", Boolean)
|
|
216
214
|
], LoginController.prototype, "TwoFactorAuthForceUser", void 0);
|
|
217
215
|
__decorate([
|
|
218
|
-
(0,
|
|
219
|
-
__metadata("design:type",
|
|
220
|
-
], LoginController.prototype, "
|
|
216
|
+
(0, di_1.Autoinject)(SessionCookies_js_1.SessionCookieFactory),
|
|
217
|
+
__metadata("design:type", SessionCookies_js_1.SessionCookieFactory)
|
|
218
|
+
], LoginController.prototype, "SessionCookies", void 0);
|
|
221
219
|
__decorate([
|
|
222
220
|
(0, di_1.Autoinject)(rbac_1.AccessControl),
|
|
223
221
|
__metadata("design:type", rbac_1.AccessControl)
|
|
@@ -226,16 +224,16 @@ __decorate([
|
|
|
226
224
|
(0, http_1.Post)(),
|
|
227
225
|
(0, rbac_http_1.SkipModelPermission)(),
|
|
228
226
|
__param(0, (0, rbac_http_1.User)()),
|
|
229
|
-
__param(1, (0,
|
|
227
|
+
__param(1, (0, rbac_http_1.SessionId)()),
|
|
230
228
|
__param(2, (0, http_1.Body)()),
|
|
231
229
|
__metadata("design:type", Function),
|
|
232
230
|
__metadata("design:paramtypes", [rbac_2.User, String, userLogin_dto_js_1.UserLoginDto]),
|
|
233
231
|
__metadata("design:returntype", Promise)
|
|
234
232
|
], LoginController.prototype, "login", null);
|
|
235
233
|
__decorate([
|
|
236
|
-
(0, http_1.
|
|
234
|
+
(0, http_1.Post)(),
|
|
237
235
|
(0, http_1.Policy)(rbac_http_1.LoggedPolicy),
|
|
238
|
-
__param(0, (0,
|
|
236
|
+
__param(0, (0, rbac_http_1.SessionId)()),
|
|
239
237
|
__param(1, (0, rbac_http_1.Session)()),
|
|
240
238
|
__param(2, (0, rbac_http_1.User)()),
|
|
241
239
|
__metadata("design:type", Function),
|
|
@@ -247,8 +245,9 @@ __decorate([
|
|
|
247
245
|
(0, http_1.Policy)(rbac_http_1.LoggedPolicy),
|
|
248
246
|
__param(0, (0, rbac_http_1.User)()),
|
|
249
247
|
__param(1, (0, rbac_http_1.FromSession)()),
|
|
248
|
+
__param(2, (0, rbac_http_1.Session)()),
|
|
250
249
|
__metadata("design:type", Function),
|
|
251
|
-
__metadata("design:paramtypes", [rbac_2.User, String]),
|
|
250
|
+
__metadata("design:paramtypes", [rbac_2.User, String, Object]),
|
|
252
251
|
__metadata("design:returntype", Promise)
|
|
253
252
|
], LoginController.prototype, "whoami", null);
|
|
254
253
|
exports.LoginController = LoginController = __decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoginController.js","sourceRoot":"","sources":["../../../src/controllers/LoginController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,8DAAuD;AACvD,
|
|
1
|
+
{"version":3,"file":"LoginController.js","sourceRoot":"","sources":["../../../src/controllers/LoginController.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { BaseController, BadRequestResponse, Ok } from '@spinajs/http';
|
|
2
|
+
import { PasswordResetConfirmDto, PasswordResetRequestDto } from '../dto/password-reset-dto.js';
|
|
3
|
+
/** Reply shared by both reset routes — deliberately says nothing about the account. */
|
|
4
|
+
export interface IPasswordResetAck {
|
|
5
|
+
Ok: true;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Password reset for users who cannot log in.
|
|
9
|
+
*
|
|
10
|
+
* Two public, unauthenticated steps: request a token, then redeem it. The token
|
|
11
|
+
* itself is issued into the user's metadata by `passwordChangeRequest` and
|
|
12
|
+
* delivered out of band (the `UserPasswordChangeRequest` event is what an app
|
|
13
|
+
* hooks to send the mail) — it is never returned over HTTP, so possession of
|
|
14
|
+
* the mailbox is what authorizes the reset.
|
|
15
|
+
*
|
|
16
|
+
* Neither route reveals whether an account exists. Both answer the same way for
|
|
17
|
+
* a known and an unknown address, which is the whole point of a reset endpoint
|
|
18
|
+
* that anybody may call: an attacker must not be able to farm valid addresses
|
|
19
|
+
* from it, and a failed redemption must not distinguish "no such user" from
|
|
20
|
+
* "wrong token".
|
|
21
|
+
*
|
|
22
|
+
* NOTE: these routes are unauthenticated and cheap to call in a loop. Put a
|
|
23
|
+
* rate limit in front of them at the edge — this package does not provide one.
|
|
24
|
+
*
|
|
25
|
+
* @tags Authentication
|
|
26
|
+
*/
|
|
27
|
+
export declare class PasswordResetController extends BaseController {
|
|
28
|
+
/**
|
|
29
|
+
* Request a password reset
|
|
30
|
+
* Issues a reset token for the account and emits `UserPasswordChangeRequest` so the
|
|
31
|
+
* application can deliver it. Always succeeds, whether or not the address is known.
|
|
32
|
+
* @security []
|
|
33
|
+
* @returns {IPasswordResetAck} Acknowledgement — never indicates whether the account exists
|
|
34
|
+
*/
|
|
35
|
+
requestReset(payload: PasswordResetRequestDto): Promise<Ok<IPasswordResetAck>>;
|
|
36
|
+
/**
|
|
37
|
+
* Complete a password reset
|
|
38
|
+
* Redeems the token issued by `POST /auth/password/reset-request` and sets the new
|
|
39
|
+
* password. The token is single-use and expires after `rbac.password.passwordResetWaitTime`.
|
|
40
|
+
* @security []
|
|
41
|
+
* @returns {IPasswordResetAck} Acknowledgement of a successful reset
|
|
42
|
+
* @response 400 New passwords do not match, or the token is invalid or expired
|
|
43
|
+
*/
|
|
44
|
+
confirmReset(payload: PasswordResetConfirmDto): Promise<Ok<IPasswordResetAck> | BadRequestResponse>;
|
|
45
|
+
/**
|
|
46
|
+
* Issue a reset token into the user's metadata and emit
|
|
47
|
+
* `UserPasswordChangeRequest`. Wraps the module-level action so tests can
|
|
48
|
+
* stub it without a database.
|
|
49
|
+
*/
|
|
50
|
+
protected issueToken(email: string): Promise<unknown>;
|
|
51
|
+
/** Redeem a reset token. Wrapped for the same reason as {@link issueToken}. */
|
|
52
|
+
protected redeemToken(email: string, password: string, token: string): Promise<unknown>;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=PasswordResetController.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PasswordResetController.d.ts","sourceRoot":"","sources":["../../../src/controllers/PasswordResetController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAkB,kBAAkB,EAAE,EAAE,EAAQ,MAAM,eAAe,CAAC;AAI7F,OAAO,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEhG,uFAAuF;AACvF,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,IAAI,CAAC;CACV;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBACa,uBAAwB,SAAQ,cAAc;IACzD;;;;;;OAMG;IAGU,YAAY,CAAS,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC;IAcnG;;;;;;;OAOG;IAGU,YAAY,CAAS,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,EAAE,CAAC,iBAAiB,CAAC,GAAG,kBAAkB,CAAC;IA+BxH;;;;OAIG;IACH,SAAS,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrD,+EAA+E;IAC/E,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAGxF"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.PasswordResetController = void 0;
|
|
16
|
+
const http_1 = require("@spinajs/http");
|
|
17
|
+
const rbac_1 = require("@spinajs/rbac");
|
|
18
|
+
const exceptions_1 = require("@spinajs/exceptions");
|
|
19
|
+
const rbac_http_1 = require("@spinajs/rbac-http");
|
|
20
|
+
const password_reset_dto_js_1 = require("../dto/password-reset-dto.js");
|
|
21
|
+
/**
|
|
22
|
+
* Password reset for users who cannot log in.
|
|
23
|
+
*
|
|
24
|
+
* Two public, unauthenticated steps: request a token, then redeem it. The token
|
|
25
|
+
* itself is issued into the user's metadata by `passwordChangeRequest` and
|
|
26
|
+
* delivered out of band (the `UserPasswordChangeRequest` event is what an app
|
|
27
|
+
* hooks to send the mail) — it is never returned over HTTP, so possession of
|
|
28
|
+
* the mailbox is what authorizes the reset.
|
|
29
|
+
*
|
|
30
|
+
* Neither route reveals whether an account exists. Both answer the same way for
|
|
31
|
+
* a known and an unknown address, which is the whole point of a reset endpoint
|
|
32
|
+
* that anybody may call: an attacker must not be able to farm valid addresses
|
|
33
|
+
* from it, and a failed redemption must not distinguish "no such user" from
|
|
34
|
+
* "wrong token".
|
|
35
|
+
*
|
|
36
|
+
* NOTE: these routes are unauthenticated and cheap to call in a loop. Put a
|
|
37
|
+
* rate limit in front of them at the edge — this package does not provide one.
|
|
38
|
+
*
|
|
39
|
+
* @tags Authentication
|
|
40
|
+
*/
|
|
41
|
+
let PasswordResetController = class PasswordResetController extends http_1.BaseController {
|
|
42
|
+
/**
|
|
43
|
+
* Request a password reset
|
|
44
|
+
* Issues a reset token for the account and emits `UserPasswordChangeRequest` so the
|
|
45
|
+
* application can deliver it. Always succeeds, whether or not the address is known.
|
|
46
|
+
* @security []
|
|
47
|
+
* @returns {IPasswordResetAck} Acknowledgement — never indicates whether the account exists
|
|
48
|
+
*/
|
|
49
|
+
async requestReset(payload) {
|
|
50
|
+
try {
|
|
51
|
+
await this.issueToken(payload.Email);
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
// Swallowed on purpose. An unknown address, a deleted account or a
|
|
55
|
+
// banned one must produce exactly the response a valid address does —
|
|
56
|
+
// otherwise this route becomes an account enumeration oracle. Real
|
|
57
|
+
// faults ( mail queue, database ) are logged for operators.
|
|
58
|
+
this._log.warn(err, `Password reset request could not be processed for ${payload.Email}`);
|
|
59
|
+
}
|
|
60
|
+
return new http_1.Ok({ Ok: true });
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Complete a password reset
|
|
64
|
+
* Redeems the token issued by `POST /auth/password/reset-request` and sets the new
|
|
65
|
+
* password. The token is single-use and expires after `rbac.password.passwordResetWaitTime`.
|
|
66
|
+
* @security []
|
|
67
|
+
* @returns {IPasswordResetAck} Acknowledgement of a successful reset
|
|
68
|
+
* @response 400 New passwords do not match, or the token is invalid or expired
|
|
69
|
+
*/
|
|
70
|
+
async confirmReset(payload) {
|
|
71
|
+
if (payload.Password !== payload.ConfirmPassword) {
|
|
72
|
+
throw new exceptions_1.InvalidArgument('password does not match');
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
await this.redeemToken(payload.Email, payload.Password, payload.Token);
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
// One opaque failure for every rejection reason: unknown account, wrong
|
|
79
|
+
// token, expired token. Distinguishing them would tell a caller which
|
|
80
|
+
// addresses exist and let them probe tokens by the error they get back.
|
|
81
|
+
const isRedemptionFailure = err instanceof exceptions_1.ErrorCode || err instanceof exceptions_1.InvalidArgument;
|
|
82
|
+
if (!isRedemptionFailure) {
|
|
83
|
+
this._log.error(err, `Password reset failed unexpectedly for ${payload.Email}`);
|
|
84
|
+
throw err;
|
|
85
|
+
}
|
|
86
|
+
this._log.warn(err, `Password reset rejected for ${payload.Email}`);
|
|
87
|
+
return new http_1.BadRequestResponse({
|
|
88
|
+
error: {
|
|
89
|
+
code: 'E_RESET_TOKEN_INVALID',
|
|
90
|
+
message: 'Password reset token is invalid or has expired',
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return new http_1.Ok({ Ok: true });
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Issue a reset token into the user's metadata and emit
|
|
98
|
+
* `UserPasswordChangeRequest`. Wraps the module-level action so tests can
|
|
99
|
+
* stub it without a database.
|
|
100
|
+
*/
|
|
101
|
+
issueToken(email) {
|
|
102
|
+
return (0, rbac_1.passwordChangeRequest)(email);
|
|
103
|
+
}
|
|
104
|
+
/** Redeem a reset token. Wrapped for the same reason as {@link issueToken}. */
|
|
105
|
+
redeemToken(email, password, token) {
|
|
106
|
+
return (0, rbac_1.confirmPasswordReset)(email, password, token);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
exports.PasswordResetController = PasswordResetController;
|
|
110
|
+
__decorate([
|
|
111
|
+
(0, http_1.Post)('password/reset-request'),
|
|
112
|
+
(0, rbac_http_1.SkipModelPermission)(),
|
|
113
|
+
__param(0, (0, http_1.Body)()),
|
|
114
|
+
__metadata("design:type", Function),
|
|
115
|
+
__metadata("design:paramtypes", [password_reset_dto_js_1.PasswordResetRequestDto]),
|
|
116
|
+
__metadata("design:returntype", Promise)
|
|
117
|
+
], PasswordResetController.prototype, "requestReset", null);
|
|
118
|
+
__decorate([
|
|
119
|
+
(0, http_1.Post)('password/reset'),
|
|
120
|
+
(0, rbac_http_1.SkipModelPermission)(),
|
|
121
|
+
__param(0, (0, http_1.Body)()),
|
|
122
|
+
__metadata("design:type", Function),
|
|
123
|
+
__metadata("design:paramtypes", [password_reset_dto_js_1.PasswordResetConfirmDto]),
|
|
124
|
+
__metadata("design:returntype", Promise)
|
|
125
|
+
], PasswordResetController.prototype, "confirmReset", null);
|
|
126
|
+
exports.PasswordResetController = PasswordResetController = __decorate([
|
|
127
|
+
(0, http_1.BasePath)('auth')
|
|
128
|
+
], PasswordResetController);
|
|
129
|
+
//# sourceMappingURL=PasswordResetController.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PasswordResetController.js","sourceRoot":"","sources":["../../../src/controllers/PasswordResetController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,wCAA6F;AAC7F,wCAA4E;AAC5E,oDAAiE;AACjE,kDAAyD;AACzD,wEAAgG;AAOhG;;;;;;;;;;;;;;;;;;;GAmBG;AAEI,IAAM,uBAAuB,GAA7B,MAAM,uBAAwB,SAAQ,qBAAc;IACzD;;;;;;OAMG;IAGU,AAAN,KAAK,CAAC,YAAY,CAAS,OAAgC;QAChE,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,mEAAmE;YACnE,sEAAsE;YACtE,mEAAmE;YACnE,4DAA4D;YAC5D,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAY,EAAE,qDAAqD,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACrG,CAAC;QAED,OAAO,IAAI,SAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAuB,CAAC,CAAC;IACnD,CAAC;IAED;;;;;;;OAOG;IAGU,AAAN,KAAK,CAAC,YAAY,CAAS,OAAgC;QAChE,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,eAAe,EAAE,CAAC;YACjD,MAAM,IAAI,4BAAe,CAAC,yBAAyB,CAAC,CAAC;QACvD,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QACzE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,wEAAwE;YACxE,sEAAsE;YACtE,wEAAwE;YACxE,MAAM,mBAAmB,GAAG,GAAG,YAAY,sBAAS,IAAI,GAAG,YAAY,4BAAe,CAAC;YAEvF,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBACzB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAY,EAAE,0CAA0C,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;gBACzF,MAAM,GAAG,CAAC;YACZ,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAY,EAAE,+BAA+B,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;YAE7E,OAAO,IAAI,yBAAkB,CAAC;gBAC5B,KAAK,EAAE;oBACL,IAAI,EAAE,uBAAuB;oBAC7B,OAAO,EAAE,gDAAgD;iBAC1D;aACF,CAAC,CAAC;QACL,CAAC;QAED,OAAO,IAAI,SAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAuB,CAAC,CAAC;IACnD,CAAC;IAED;;;;OAIG;IACO,UAAU,CAAC,KAAa;QAChC,OAAO,IAAA,4BAAqB,EAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IAED,+EAA+E;IACrE,WAAW,CAAC,KAAa,EAAE,QAAgB,EAAE,KAAa;QAClE,OAAO,IAAA,2BAAoB,EAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;CACF,CAAA;AA9EY,0DAAuB;AAUrB;IAFZ,IAAA,WAAI,EAAC,wBAAwB,CAAC;IAC9B,IAAA,+BAAmB,GAAE;IACK,WAAA,IAAA,WAAI,GAAE,CAAA;;qCAAU,+CAAuB;;2DAYjE;AAYY;IAFZ,IAAA,WAAI,EAAC,gBAAgB,CAAC;IACtB,IAAA,+BAAmB,GAAE;IACK,WAAA,IAAA,WAAI,GAAE,CAAA;;qCAAU,+CAAuB;;2DA6BjE;kCA/DU,uBAAuB;IADnC,IAAA,eAAQ,EAAC,MAAM,CAAC;GACJ,uBAAuB,CA8EnC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { BaseController, NotFound, Ok } from '@spinajs/http';
|
|
2
|
+
import { SessionProvider, User as UserModel } from '@spinajs/rbac';
|
|
3
|
+
import type { ISession } from '@spinajs/rbac';
|
|
4
|
+
import { Log } from '@spinajs/log';
|
|
5
|
+
/** One live session of the calling user. */
|
|
6
|
+
export interface IUserSessionEntry {
|
|
7
|
+
/**
|
|
8
|
+
* Opaque, stable handle for the session. Deliberately NOT the session id:
|
|
9
|
+
* listing your own sessions must not hand out working credentials for them,
|
|
10
|
+
* because the response ( and anything that caches or logs it ) would then be
|
|
11
|
+
* as good as the cookies themselves.
|
|
12
|
+
*/
|
|
13
|
+
Handle: string;
|
|
14
|
+
/** ISO instant the session was opened */
|
|
15
|
+
Created: string;
|
|
16
|
+
/** ISO instant the session expires, or null when it never does */
|
|
17
|
+
Expires: string | null;
|
|
18
|
+
/** True for the session making this request */
|
|
19
|
+
Current: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Active sessions of the calling user — "where am I logged in", plus the means
|
|
23
|
+
* to end any of them.
|
|
24
|
+
*
|
|
25
|
+
* OWASP asks for exactly this: the user should be able to see concurrent
|
|
26
|
+
* sessions and terminate them remotely, which is how a person who suspects a
|
|
27
|
+
* stolen cookie gets rid of it without an administrator.
|
|
28
|
+
*
|
|
29
|
+
* @tags User
|
|
30
|
+
*/
|
|
31
|
+
export declare class SessionsController extends BaseController {
|
|
32
|
+
protected Log: Log;
|
|
33
|
+
protected SessionProvider: SessionProvider;
|
|
34
|
+
/**
|
|
35
|
+
* List own sessions
|
|
36
|
+
* Returns every live session of the authenticated user, newest first, with the
|
|
37
|
+
* one making the request flagged.
|
|
38
|
+
* @security cookieAuth
|
|
39
|
+
* @returns {IUserSessionEntry[]} Live sessions of the calling user
|
|
40
|
+
* @response 401 Unauthorized — valid session required
|
|
41
|
+
*/
|
|
42
|
+
list(user: UserModel, ssid: string): Promise<Ok<IUserSessionEntry[]>>;
|
|
43
|
+
/**
|
|
44
|
+
* Revoke one session
|
|
45
|
+
* Ends the session identified by its handle. Revoking the current session is
|
|
46
|
+
* allowed and logs the caller out.
|
|
47
|
+
* @security cookieAuth
|
|
48
|
+
* @param handle Session handle as returned by `GET /user/sessions`
|
|
49
|
+
* @response 200 Session revoked
|
|
50
|
+
* @response 401 Unauthorized — valid session required
|
|
51
|
+
* @response 404 No such session for this user
|
|
52
|
+
*/
|
|
53
|
+
revoke(user: UserModel, handle: string): Promise<Ok | NotFound>;
|
|
54
|
+
/**
|
|
55
|
+
* Revoke every other session
|
|
56
|
+
* Ends all sessions of the user except the one making the request — the
|
|
57
|
+
* "log out everywhere else" action after a suspected compromise.
|
|
58
|
+
* @security cookieAuth
|
|
59
|
+
* @response 200 Other sessions revoked
|
|
60
|
+
* @response 401 Unauthorized — valid session required
|
|
61
|
+
*/
|
|
62
|
+
revokeOthers(user: UserModel, ssid: string): Promise<Ok>;
|
|
63
|
+
protected toEntry(session: ISession, currentHandle: string | null): IUserSessionEntry;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=SessionsController.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionsController.d.ts","sourceRoot":"","sources":["../../../src/controllers/SessionsController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAsB,QAAQ,EAAE,EAAE,EAAiB,MAAM,eAAe,CAAC;AAChG,OAAO,EAAE,eAAe,EAAE,IAAI,IAAI,SAAS,EAAiB,MAAM,eAAe,CAAC;AAClF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAG3C,4CAA4C;AAC5C,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAEhB,kEAAkE;IAClE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvB,+CAA+C;IAC/C,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,qBAGa,kBAAmB,SAAQ,cAAc;IAEpD,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAGnB,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAE3C;;;;;;;OAOG;IAGU,IAAI,CAAS,IAAI,EAAE,SAAS,EAAkB,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAW1G;;;;;;;;;OASG;IAGU,MAAM,CAAS,IAAI,EAAE,SAAS,EAAW,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,GAAG,QAAQ,CAAC;IAkB7F;;;;;;;OAOG;IAGU,YAAY,CAAS,IAAI,EAAE,SAAS,EAAkB,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;IAkB7F,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,iBAAiB;CAUtF"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.SessionsController = void 0;
|
|
16
|
+
const http_1 = require("@spinajs/http");
|
|
17
|
+
const rbac_1 = require("@spinajs/rbac");
|
|
18
|
+
const configuration_1 = require("@spinajs/configuration");
|
|
19
|
+
const log_1 = require("@spinajs/log");
|
|
20
|
+
const rbac_http_1 = require("@spinajs/rbac-http");
|
|
21
|
+
/**
|
|
22
|
+
* Active sessions of the calling user — "where am I logged in", plus the means
|
|
23
|
+
* to end any of them.
|
|
24
|
+
*
|
|
25
|
+
* OWASP asks for exactly this: the user should be able to see concurrent
|
|
26
|
+
* sessions and terminate them remotely, which is how a person who suspects a
|
|
27
|
+
* stolen cookie gets rid of it without an administrator.
|
|
28
|
+
*
|
|
29
|
+
* @tags User
|
|
30
|
+
*/
|
|
31
|
+
let SessionsController = class SessionsController extends http_1.BaseController {
|
|
32
|
+
/**
|
|
33
|
+
* List own sessions
|
|
34
|
+
* Returns every live session of the authenticated user, newest first, with the
|
|
35
|
+
* one making the request flagged.
|
|
36
|
+
* @security cookieAuth
|
|
37
|
+
* @returns {IUserSessionEntry[]} Live sessions of the calling user
|
|
38
|
+
* @response 401 Unauthorized — valid session required
|
|
39
|
+
*/
|
|
40
|
+
async list(user, ssid) {
|
|
41
|
+
const sessions = await this.SessionProvider.listByUser(user.Id);
|
|
42
|
+
const current = ssid ? (0, rbac_1.hashSessionId)(ssid) : null;
|
|
43
|
+
const entries = sessions
|
|
44
|
+
.map((s) => this.toEntry(s, current))
|
|
45
|
+
.sort((a, b) => (a.Created < b.Created ? 1 : -1));
|
|
46
|
+
return new http_1.Ok(entries);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Revoke one session
|
|
50
|
+
* Ends the session identified by its handle. Revoking the current session is
|
|
51
|
+
* allowed and logs the caller out.
|
|
52
|
+
* @security cookieAuth
|
|
53
|
+
* @param handle Session handle as returned by `GET /user/sessions`
|
|
54
|
+
* @response 200 Session revoked
|
|
55
|
+
* @response 401 Unauthorized — valid session required
|
|
56
|
+
* @response 404 No such session for this user
|
|
57
|
+
*/
|
|
58
|
+
async revoke(user, handle) {
|
|
59
|
+
// Resolved through the user's OWN session list, so a handle belonging to
|
|
60
|
+
// somebody else's session simply is not found here — the route cannot be
|
|
61
|
+
// used to end a stranger's session even if its handle leaks.
|
|
62
|
+
const sessions = await this.SessionProvider.listByUser(user.Id);
|
|
63
|
+
const match = sessions.find((s) => (0, rbac_1.hashSessionId)(s.SessionId) === handle);
|
|
64
|
+
if (!match) {
|
|
65
|
+
return new http_1.NotFound({ error: { code: 'E_SESSION_NOT_FOUND', message: 'No such session' } });
|
|
66
|
+
}
|
|
67
|
+
await this.SessionProvider.delete(match.SessionId);
|
|
68
|
+
this.Log.info(`Session revoked by its owner`, { Session: handle, User: user.Uuid });
|
|
69
|
+
return new http_1.Ok(null, { Headers: [{ Name: 'Cache-Control', Value: 'no-store' }] });
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Revoke every other session
|
|
73
|
+
* Ends all sessions of the user except the one making the request — the
|
|
74
|
+
* "log out everywhere else" action after a suspected compromise.
|
|
75
|
+
* @security cookieAuth
|
|
76
|
+
* @response 200 Other sessions revoked
|
|
77
|
+
* @response 401 Unauthorized — valid session required
|
|
78
|
+
*/
|
|
79
|
+
async revokeOthers(user, ssid) {
|
|
80
|
+
const sessions = await this.SessionProvider.listByUser(user.Id);
|
|
81
|
+
let revoked = 0;
|
|
82
|
+
for (const session of sessions) {
|
|
83
|
+
if (session.SessionId === ssid) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
await this.SessionProvider.delete(session.SessionId);
|
|
87
|
+
revoked++;
|
|
88
|
+
}
|
|
89
|
+
this.Log.info(`Revoked ${revoked} other session(s)`, { User: user.Uuid });
|
|
90
|
+
return new http_1.Ok({ Revoked: revoked }, { Headers: [{ Name: 'Cache-Control', Value: 'no-store' }] });
|
|
91
|
+
}
|
|
92
|
+
toEntry(session, currentHandle) {
|
|
93
|
+
const handle = (0, rbac_1.hashSessionId)(session.SessionId);
|
|
94
|
+
return {
|
|
95
|
+
Handle: handle,
|
|
96
|
+
Created: session.Creation?.toISO() ?? '',
|
|
97
|
+
Expires: session.Expiration?.toISO() ?? null,
|
|
98
|
+
Current: handle === currentHandle,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
exports.SessionsController = SessionsController;
|
|
103
|
+
__decorate([
|
|
104
|
+
(0, log_1.Logger)('rbac-session'),
|
|
105
|
+
__metadata("design:type", log_1.Log)
|
|
106
|
+
], SessionsController.prototype, "Log", void 0);
|
|
107
|
+
__decorate([
|
|
108
|
+
(0, configuration_1.AutoinjectService)('rbac.session'),
|
|
109
|
+
__metadata("design:type", rbac_1.SessionProvider)
|
|
110
|
+
], SessionsController.prototype, "SessionProvider", void 0);
|
|
111
|
+
__decorate([
|
|
112
|
+
(0, http_1.Get)('sessions'),
|
|
113
|
+
(0, rbac_http_1.Permission)(['readOwn']),
|
|
114
|
+
__param(0, (0, rbac_http_1.User)()),
|
|
115
|
+
__param(1, (0, rbac_http_1.SessionId)()),
|
|
116
|
+
__metadata("design:type", Function),
|
|
117
|
+
__metadata("design:paramtypes", [rbac_1.User, String]),
|
|
118
|
+
__metadata("design:returntype", Promise)
|
|
119
|
+
], SessionsController.prototype, "list", null);
|
|
120
|
+
__decorate([
|
|
121
|
+
(0, http_1.Del)('sessions/:handle'),
|
|
122
|
+
(0, rbac_http_1.Permission)(['updateOwn']),
|
|
123
|
+
__param(0, (0, rbac_http_1.User)()),
|
|
124
|
+
__param(1, (0, http_1.Param)()),
|
|
125
|
+
__metadata("design:type", Function),
|
|
126
|
+
__metadata("design:paramtypes", [rbac_1.User, String]),
|
|
127
|
+
__metadata("design:returntype", Promise)
|
|
128
|
+
], SessionsController.prototype, "revoke", null);
|
|
129
|
+
__decorate([
|
|
130
|
+
(0, http_1.Del)('sessions'),
|
|
131
|
+
(0, rbac_http_1.Permission)(['updateOwn']),
|
|
132
|
+
__param(0, (0, rbac_http_1.User)()),
|
|
133
|
+
__param(1, (0, rbac_http_1.SessionId)()),
|
|
134
|
+
__metadata("design:type", Function),
|
|
135
|
+
__metadata("design:paramtypes", [rbac_1.User, String]),
|
|
136
|
+
__metadata("design:returntype", Promise)
|
|
137
|
+
], SessionsController.prototype, "revokeOthers", null);
|
|
138
|
+
exports.SessionsController = SessionsController = __decorate([
|
|
139
|
+
(0, http_1.BasePath)('user'),
|
|
140
|
+
(0, rbac_http_1.Resource)('user'),
|
|
141
|
+
(0, http_1.Policy)(rbac_http_1.AuthorizedPolicy)
|
|
142
|
+
], SessionsController);
|
|
143
|
+
//# sourceMappingURL=SessionsController.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionsController.js","sourceRoot":"","sources":["../../../src/controllers/SessionsController.ts"],"names":[],"mappings":"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"}
|