@getstrata/core 2.2.29 → 2.2.30
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/CHANGELOG.md +4 -0
- package/dist/core/auth/guard.d.ts +1 -0
- package/dist/index.js +21 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @getstrata/core changelog
|
|
2
2
|
|
|
3
|
+
## 2.2.30
|
|
4
|
+
|
|
5
|
+
Basic authentication resolution is reused only within the same Request and unchanged credentials, preventing middleware/controller lookups from consuming MFA recovery proofs twice. Adds real HTTP replay/concurrency and credential/guard invalidation regressions.
|
|
6
|
+
|
|
3
7
|
## 2.2.29
|
|
4
8
|
|
|
5
9
|
MFA recovery-code persistence atomically claims the validated snapshot and rejects stale requests before credential issuance. Basic authentication fails closed and consumes under the verified RLS identifier scope. Adds native SQLite/Postgres/MySQL concurrency and restricted-role regressions.
|
|
@@ -26,6 +26,7 @@ declare class CompositeGuard implements AuthGuard {
|
|
|
26
26
|
}
|
|
27
27
|
declare class AuthManager {
|
|
28
28
|
private readonly guard;
|
|
29
|
+
private basicResolutions;
|
|
29
30
|
private readonly namedGuards;
|
|
30
31
|
constructor(guard: AuthGuard);
|
|
31
32
|
registerGuard(name: string, next: AuthGuard): this;
|
package/dist/index.js
CHANGED
|
@@ -2117,6 +2117,7 @@ var SESSION_GUARD_NAMES = ["web", "session", "default"];
|
|
|
2117
2117
|
|
|
2118
2118
|
class AuthManager {
|
|
2119
2119
|
guard;
|
|
2120
|
+
basicResolutions = new WeakMap;
|
|
2120
2121
|
namedGuards = new Map;
|
|
2121
2122
|
constructor(guard) {
|
|
2122
2123
|
this.guard = guard;
|
|
@@ -2128,6 +2129,7 @@ class AuthManager {
|
|
|
2128
2129
|
throw new Error("Auth guard name must not be empty.");
|
|
2129
2130
|
}
|
|
2130
2131
|
this.namedGuards.set(trimmed, next);
|
|
2132
|
+
this.basicResolutions = new WeakMap;
|
|
2131
2133
|
return this;
|
|
2132
2134
|
}
|
|
2133
2135
|
use(name = "default") {
|
|
@@ -2148,7 +2150,25 @@ class AuthManager {
|
|
|
2148
2150
|
if (!request) {
|
|
2149
2151
|
return { user: currentAuthUser(), credentialSource: null };
|
|
2150
2152
|
}
|
|
2151
|
-
|
|
2153
|
+
if (authorizationScheme(request) !== "basic") {
|
|
2154
|
+
this.basicResolutions.delete(request);
|
|
2155
|
+
return await this.authenticateRequest(request);
|
|
2156
|
+
}
|
|
2157
|
+
const authorization = request.headers.get("authorization");
|
|
2158
|
+
const mfaCode = request.headers.get("x-mfa-code");
|
|
2159
|
+
const cached = this.basicResolutions.get(request);
|
|
2160
|
+
if (cached && cached.authorization === authorization && cached.mfaCode === mfaCode) {
|
|
2161
|
+
return await cached.result;
|
|
2162
|
+
}
|
|
2163
|
+
const entry = { authorization, mfaCode, result: this.authenticateRequest(request) };
|
|
2164
|
+
this.basicResolutions.set(request, entry);
|
|
2165
|
+
try {
|
|
2166
|
+
return await entry.result;
|
|
2167
|
+
} catch (error) {
|
|
2168
|
+
if (this.basicResolutions.get(request) === entry)
|
|
2169
|
+
this.basicResolutions.delete(request);
|
|
2170
|
+
throw error;
|
|
2171
|
+
}
|
|
2152
2172
|
}
|
|
2153
2173
|
user(request) {
|
|
2154
2174
|
return this.resolve(request);
|