@spfn/auth 0.2.0-beta.70 → 0.2.0-beta.72
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/dist/{authenticate-tmmbh1ux.d.ts → authenticate-DXVtYh8X.d.ts} +10 -1
- package/dist/index.d.ts +3 -3
- package/dist/nextjs/api.js +25 -2
- package/dist/nextjs/api.js.map +1 -1
- package/dist/nextjs/server.js +5 -1
- package/dist/nextjs/server.js.map +1 -1
- package/dist/server.d.ts +89 -55
- package/dist/server.js +259 -13
- package/dist/server.js.map +1 -1
- package/package.json +4 -4
package/dist/server.js
CHANGED
|
@@ -5658,6 +5658,25 @@ var init_keys_repository = __esm({
|
|
|
5658
5658
|
).returning();
|
|
5659
5659
|
return result[0] ?? null;
|
|
5660
5660
|
}
|
|
5661
|
+
/**
|
|
5662
|
+
* 사용자의 모든 활성 공개키 revoke (비활성화)
|
|
5663
|
+
*
|
|
5664
|
+
* 비번 변경 시 전체 세션 로그아웃에 사용. authenticate는 활성 키만 검증하므로,
|
|
5665
|
+
* revoke된 키로 서명한 기존 세션의 요청은 즉시 401이 된다.
|
|
5666
|
+
* Write primary 사용
|
|
5667
|
+
*/
|
|
5668
|
+
async revokeAllActiveByUserId(userId, reason) {
|
|
5669
|
+
return await this.db.update(userPublicKeys).set({
|
|
5670
|
+
isActive: false,
|
|
5671
|
+
revokedAt: /* @__PURE__ */ new Date(),
|
|
5672
|
+
revokedReason: reason
|
|
5673
|
+
}).where(
|
|
5674
|
+
and2(
|
|
5675
|
+
eq2(userPublicKeys.userId, userId),
|
|
5676
|
+
eq2(userPublicKeys.isActive, true)
|
|
5677
|
+
)
|
|
5678
|
+
).returning();
|
|
5679
|
+
}
|
|
5661
5680
|
/**
|
|
5662
5681
|
* 공개키 삭제
|
|
5663
5682
|
* Write primary 사용
|
|
@@ -6936,13 +6955,23 @@ function getPublicKeyObject(publicKeyB64) {
|
|
|
6936
6955
|
publicKeyCache.set(publicKeyB64, keyObject);
|
|
6937
6956
|
return keyObject;
|
|
6938
6957
|
}
|
|
6958
|
+
var INSECURE_JWT_SECRET = "dev-secret-key-change-in-production";
|
|
6959
|
+
function getJwtSecret() {
|
|
6960
|
+
const secret = env2.SPFN_AUTH_JWT_SECRET;
|
|
6961
|
+
if ((!secret || secret === INSECURE_JWT_SECRET) && process.env.NODE_ENV === "production") {
|
|
6962
|
+
throw new Error(
|
|
6963
|
+
"SPFN_AUTH_JWT_SECRET must be set to a strong secret in production (the default is public)."
|
|
6964
|
+
);
|
|
6965
|
+
}
|
|
6966
|
+
return secret;
|
|
6967
|
+
}
|
|
6939
6968
|
function generateToken(payload) {
|
|
6940
|
-
return jwt.sign(payload,
|
|
6969
|
+
return jwt.sign(payload, getJwtSecret(), {
|
|
6941
6970
|
expiresIn: env2.SPFN_AUTH_JWT_EXPIRES_IN
|
|
6942
6971
|
});
|
|
6943
6972
|
}
|
|
6944
6973
|
function verifyToken(token) {
|
|
6945
|
-
return jwt.verify(token,
|
|
6974
|
+
return jwt.verify(token, getJwtSecret(), { algorithms: ["HS256"] });
|
|
6946
6975
|
}
|
|
6947
6976
|
function verifyClientToken(token, publicKeyB64, algorithm) {
|
|
6948
6977
|
const publicKeyObject = getPublicKeyObject(publicKeyB64);
|
|
@@ -7082,6 +7111,9 @@ async function validateVerificationCode(target, code, purpose) {
|
|
|
7082
7111
|
if (!record) {
|
|
7083
7112
|
return { valid: false, error: "Invalid verification code" };
|
|
7084
7113
|
}
|
|
7114
|
+
if (record.attempts >= MAX_VERIFICATION_ATTEMPTS) {
|
|
7115
|
+
return { valid: false, error: "Too many attempts, please request a new code" };
|
|
7116
|
+
}
|
|
7085
7117
|
if (record.code !== code) {
|
|
7086
7118
|
await verificationCodesRepository.incrementAttempts(record.id);
|
|
7087
7119
|
return { valid: false, error: "Invalid verification code" };
|
|
@@ -7092,9 +7124,6 @@ async function validateVerificationCode(target, code, purpose) {
|
|
|
7092
7124
|
if (/* @__PURE__ */ new Date() > new Date(record.expiresAt)) {
|
|
7093
7125
|
return { valid: false, error: "Verification code expired" };
|
|
7094
7126
|
}
|
|
7095
|
-
if (record.attempts >= MAX_VERIFICATION_ATTEMPTS) {
|
|
7096
|
-
return { valid: false, error: "Too many attempts, please request a new code" };
|
|
7097
|
-
}
|
|
7098
7127
|
return { valid: true, codeId: record.id };
|
|
7099
7128
|
}
|
|
7100
7129
|
async function markCodeAsUsed(codeId) {
|
|
@@ -7549,6 +7578,7 @@ async function changePasswordService(params) {
|
|
|
7549
7578
|
}
|
|
7550
7579
|
const newPasswordHash = await hashPassword(newPassword);
|
|
7551
7580
|
await usersRepository.updatePassword(userId, newPasswordHash, true);
|
|
7581
|
+
await keysRepository.revokeAllActiveByUserId(userId, "Revoked by password change");
|
|
7552
7582
|
}
|
|
7553
7583
|
|
|
7554
7584
|
// src/server/services/rbac.service.ts
|
|
@@ -7574,6 +7604,10 @@ var COOKIE_NAMES = {
|
|
|
7574
7604
|
/** Pending OAuth session (privateKey, keyId, algorithm) - temporary during OAuth flow */
|
|
7575
7605
|
get OAUTH_PENDING() {
|
|
7576
7606
|
return `spfn_oauth_pending${getCookieSuffix()}`;
|
|
7607
|
+
},
|
|
7608
|
+
/** OAuth CSRF nonce — double-submit against the (encrypted) state.nonce at callback */
|
|
7609
|
+
get OAUTH_CSRF() {
|
|
7610
|
+
return `spfn_oauth_csrf${getCookieSuffix()}`;
|
|
7577
7611
|
}
|
|
7578
7612
|
};
|
|
7579
7613
|
function parseDuration(duration) {
|
|
@@ -8287,11 +8321,14 @@ function generateNonce() {
|
|
|
8287
8321
|
crypto.getRandomValues(array);
|
|
8288
8322
|
return Array.from(array, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
8289
8323
|
}
|
|
8324
|
+
function generateOAuthNonce() {
|
|
8325
|
+
return generateNonce();
|
|
8326
|
+
}
|
|
8290
8327
|
async function createOAuthState(params) {
|
|
8291
8328
|
const key = await getStateKey();
|
|
8292
8329
|
const state = {
|
|
8293
8330
|
returnUrl: params.returnUrl,
|
|
8294
|
-
nonce: generateNonce(),
|
|
8331
|
+
nonce: params.nonce ?? generateNonce(),
|
|
8295
8332
|
provider: params.provider,
|
|
8296
8333
|
publicKey: params.publicKey,
|
|
8297
8334
|
keyId: params.keyId,
|
|
@@ -8509,7 +8546,7 @@ function tokenExpiryDate(expiresIn) {
|
|
|
8509
8546
|
return new Date(Date.now() + expiresIn * 1e3);
|
|
8510
8547
|
}
|
|
8511
8548
|
async function oauthStartService(params) {
|
|
8512
|
-
const { provider, returnUrl, publicKey, keyId, fingerprint, algorithm, metadata } = params;
|
|
8549
|
+
const { provider, returnUrl, publicKey, keyId, fingerprint, algorithm, metadata, nonce } = params;
|
|
8513
8550
|
const oauthProvider = requireEnabledProvider(provider);
|
|
8514
8551
|
const state = await createOAuthState({
|
|
8515
8552
|
provider,
|
|
@@ -8518,13 +8555,19 @@ async function oauthStartService(params) {
|
|
|
8518
8555
|
keyId,
|
|
8519
8556
|
fingerprint,
|
|
8520
8557
|
algorithm,
|
|
8521
|
-
metadata
|
|
8558
|
+
metadata,
|
|
8559
|
+
nonce
|
|
8522
8560
|
});
|
|
8523
8561
|
return { authUrl: oauthProvider.getAuthUrl(state) };
|
|
8524
8562
|
}
|
|
8525
8563
|
async function oauthCallbackService(params) {
|
|
8526
|
-
const { provider, code, state } = params;
|
|
8564
|
+
const { provider, code, state, expectedNonce } = params;
|
|
8527
8565
|
const stateData = await verifyOAuthState(state);
|
|
8566
|
+
if (!expectedNonce || stateData.nonce !== expectedNonce) {
|
|
8567
|
+
throw new ValidationError5({
|
|
8568
|
+
message: "OAuth state validation failed"
|
|
8569
|
+
});
|
|
8570
|
+
}
|
|
8528
8571
|
if (stateData.provider !== provider) {
|
|
8529
8572
|
throw new ValidationError5({
|
|
8530
8573
|
message: "OAuth state provider mismatch"
|
|
@@ -9251,7 +9294,8 @@ var acceptInvitation2 = route2.post("/_auth/invitations/accept").input({
|
|
|
9251
9294
|
}),
|
|
9252
9295
|
password: Type.String({
|
|
9253
9296
|
minLength: 8,
|
|
9254
|
-
|
|
9297
|
+
maxLength: 72,
|
|
9298
|
+
description: "User password (8\u201372 characters). bcrypt silently ignores bytes past 72, so longer inputs are rejected rather than truncated."
|
|
9255
9299
|
})
|
|
9256
9300
|
})
|
|
9257
9301
|
}).interceptor({
|
|
@@ -9477,6 +9521,193 @@ var userRouter = defineRouter3({
|
|
|
9477
9521
|
|
|
9478
9522
|
// src/server/routes/oauth/index.ts
|
|
9479
9523
|
init_esm();
|
|
9524
|
+
|
|
9525
|
+
// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/utils/url.js
|
|
9526
|
+
var tryDecode = (str, decoder) => {
|
|
9527
|
+
try {
|
|
9528
|
+
return decoder(str);
|
|
9529
|
+
} catch {
|
|
9530
|
+
return str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match) => {
|
|
9531
|
+
try {
|
|
9532
|
+
return decoder(match);
|
|
9533
|
+
} catch {
|
|
9534
|
+
return match;
|
|
9535
|
+
}
|
|
9536
|
+
});
|
|
9537
|
+
}
|
|
9538
|
+
};
|
|
9539
|
+
var decodeURIComponent_ = decodeURIComponent;
|
|
9540
|
+
|
|
9541
|
+
// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/utils/cookie.js
|
|
9542
|
+
var validCookieNameRegEx = /^[\w!#$%&'*.^`|~+-]+$/;
|
|
9543
|
+
var validCookieValueRegEx = /^[ !#-:<-[\]-~]*$/;
|
|
9544
|
+
var trimCookieWhitespace = (value) => {
|
|
9545
|
+
let start = 0;
|
|
9546
|
+
let end = value.length;
|
|
9547
|
+
while (start < end) {
|
|
9548
|
+
const charCode = value.charCodeAt(start);
|
|
9549
|
+
if (charCode !== 32 && charCode !== 9) {
|
|
9550
|
+
break;
|
|
9551
|
+
}
|
|
9552
|
+
start++;
|
|
9553
|
+
}
|
|
9554
|
+
while (end > start) {
|
|
9555
|
+
const charCode = value.charCodeAt(end - 1);
|
|
9556
|
+
if (charCode !== 32 && charCode !== 9) {
|
|
9557
|
+
break;
|
|
9558
|
+
}
|
|
9559
|
+
end--;
|
|
9560
|
+
}
|
|
9561
|
+
return start === 0 && end === value.length ? value : value.slice(start, end);
|
|
9562
|
+
};
|
|
9563
|
+
var parse = (cookie, name) => {
|
|
9564
|
+
if (name && cookie.indexOf(name) === -1) {
|
|
9565
|
+
return {};
|
|
9566
|
+
}
|
|
9567
|
+
const pairs = cookie.split(";");
|
|
9568
|
+
const parsedCookie = /* @__PURE__ */ Object.create(null);
|
|
9569
|
+
for (const pairStr of pairs) {
|
|
9570
|
+
const valueStartPos = pairStr.indexOf("=");
|
|
9571
|
+
if (valueStartPos === -1) {
|
|
9572
|
+
continue;
|
|
9573
|
+
}
|
|
9574
|
+
const cookieName = trimCookieWhitespace(pairStr.substring(0, valueStartPos));
|
|
9575
|
+
if (name && name !== cookieName || !validCookieNameRegEx.test(cookieName) || cookieName in parsedCookie) {
|
|
9576
|
+
continue;
|
|
9577
|
+
}
|
|
9578
|
+
let cookieValue = trimCookieWhitespace(pairStr.substring(valueStartPos + 1));
|
|
9579
|
+
if (cookieValue.startsWith('"') && cookieValue.endsWith('"')) {
|
|
9580
|
+
cookieValue = cookieValue.slice(1, -1);
|
|
9581
|
+
}
|
|
9582
|
+
if (validCookieValueRegEx.test(cookieValue)) {
|
|
9583
|
+
parsedCookie[cookieName] = cookieValue.indexOf("%") !== -1 ? tryDecode(cookieValue, decodeURIComponent_) : cookieValue;
|
|
9584
|
+
if (name) {
|
|
9585
|
+
break;
|
|
9586
|
+
}
|
|
9587
|
+
}
|
|
9588
|
+
}
|
|
9589
|
+
return parsedCookie;
|
|
9590
|
+
};
|
|
9591
|
+
var _serialize = (name, value, opt = {}) => {
|
|
9592
|
+
if (!validCookieNameRegEx.test(name)) {
|
|
9593
|
+
throw new Error("Invalid cookie name");
|
|
9594
|
+
}
|
|
9595
|
+
let cookie = `${name}=${value}`;
|
|
9596
|
+
if (name.startsWith("__Secure-") && !opt.secure) {
|
|
9597
|
+
throw new Error("__Secure- Cookie must have Secure attributes");
|
|
9598
|
+
}
|
|
9599
|
+
if (name.startsWith("__Host-")) {
|
|
9600
|
+
if (!opt.secure) {
|
|
9601
|
+
throw new Error("__Host- Cookie must have Secure attributes");
|
|
9602
|
+
}
|
|
9603
|
+
if (opt.path !== "/") {
|
|
9604
|
+
throw new Error('__Host- Cookie must have Path attributes with "/"');
|
|
9605
|
+
}
|
|
9606
|
+
if (opt.domain) {
|
|
9607
|
+
throw new Error("__Host- Cookie must not have Domain attributes");
|
|
9608
|
+
}
|
|
9609
|
+
}
|
|
9610
|
+
for (const key of ["domain", "path", "sameSite", "priority"]) {
|
|
9611
|
+
if (opt[key] && /[;\r\n]/.test(opt[key])) {
|
|
9612
|
+
throw new Error(`${key} must not contain ";", "\\r", or "\\n"`);
|
|
9613
|
+
}
|
|
9614
|
+
}
|
|
9615
|
+
if (opt && typeof opt.maxAge === "number" && opt.maxAge >= 0) {
|
|
9616
|
+
if (opt.maxAge > 3456e4) {
|
|
9617
|
+
throw new Error(
|
|
9618
|
+
"Cookies Max-Age SHOULD NOT be greater than 400 days (34560000 seconds) in duration."
|
|
9619
|
+
);
|
|
9620
|
+
}
|
|
9621
|
+
cookie += `; Max-Age=${opt.maxAge | 0}`;
|
|
9622
|
+
}
|
|
9623
|
+
if (opt.domain && opt.prefix !== "host") {
|
|
9624
|
+
cookie += `; Domain=${opt.domain}`;
|
|
9625
|
+
}
|
|
9626
|
+
if (opt.path) {
|
|
9627
|
+
cookie += `; Path=${opt.path}`;
|
|
9628
|
+
}
|
|
9629
|
+
if (opt.expires) {
|
|
9630
|
+
if (opt.expires.getTime() - Date.now() > 3456e7) {
|
|
9631
|
+
throw new Error(
|
|
9632
|
+
"Cookies Expires SHOULD NOT be greater than 400 days (34560000 seconds) in the future."
|
|
9633
|
+
);
|
|
9634
|
+
}
|
|
9635
|
+
cookie += `; Expires=${opt.expires.toUTCString()}`;
|
|
9636
|
+
}
|
|
9637
|
+
if (opt.httpOnly) {
|
|
9638
|
+
cookie += "; HttpOnly";
|
|
9639
|
+
}
|
|
9640
|
+
if (opt.secure) {
|
|
9641
|
+
cookie += "; Secure";
|
|
9642
|
+
}
|
|
9643
|
+
if (opt.sameSite) {
|
|
9644
|
+
cookie += `; SameSite=${opt.sameSite.charAt(0).toUpperCase() + opt.sameSite.slice(1)}`;
|
|
9645
|
+
}
|
|
9646
|
+
if (opt.priority) {
|
|
9647
|
+
cookie += `; Priority=${opt.priority.charAt(0).toUpperCase() + opt.priority.slice(1)}`;
|
|
9648
|
+
}
|
|
9649
|
+
if (opt.partitioned) {
|
|
9650
|
+
if (!opt.secure) {
|
|
9651
|
+
throw new Error("Partitioned Cookie must have Secure attributes");
|
|
9652
|
+
}
|
|
9653
|
+
cookie += "; Partitioned";
|
|
9654
|
+
}
|
|
9655
|
+
return cookie;
|
|
9656
|
+
};
|
|
9657
|
+
var serialize = (name, value, opt) => {
|
|
9658
|
+
value = encodeURIComponent(value);
|
|
9659
|
+
return _serialize(name, value, opt);
|
|
9660
|
+
};
|
|
9661
|
+
|
|
9662
|
+
// ../../node_modules/.pnpm/hono@4.12.27/node_modules/hono/dist/helper/cookie/index.js
|
|
9663
|
+
var getCookie = (c, key, prefix) => {
|
|
9664
|
+
const cookie = c.req.raw.headers.get("Cookie");
|
|
9665
|
+
if (typeof key === "string") {
|
|
9666
|
+
if (!cookie) {
|
|
9667
|
+
return void 0;
|
|
9668
|
+
}
|
|
9669
|
+
let finalKey = key;
|
|
9670
|
+
if (prefix === "secure") {
|
|
9671
|
+
finalKey = "__Secure-" + key;
|
|
9672
|
+
} else if (prefix === "host") {
|
|
9673
|
+
finalKey = "__Host-" + key;
|
|
9674
|
+
}
|
|
9675
|
+
const obj2 = parse(cookie, finalKey);
|
|
9676
|
+
return obj2[finalKey];
|
|
9677
|
+
}
|
|
9678
|
+
if (!cookie) {
|
|
9679
|
+
return {};
|
|
9680
|
+
}
|
|
9681
|
+
const obj = parse(cookie);
|
|
9682
|
+
return obj;
|
|
9683
|
+
};
|
|
9684
|
+
var generateCookie = (name, value, opt) => {
|
|
9685
|
+
let cookie;
|
|
9686
|
+
if (opt?.prefix === "secure") {
|
|
9687
|
+
cookie = serialize("__Secure-" + name, value, { path: "/", ...opt, secure: true });
|
|
9688
|
+
} else if (opt?.prefix === "host") {
|
|
9689
|
+
cookie = serialize("__Host-" + name, value, {
|
|
9690
|
+
...opt,
|
|
9691
|
+
path: "/",
|
|
9692
|
+
secure: true,
|
|
9693
|
+
domain: void 0
|
|
9694
|
+
});
|
|
9695
|
+
} else {
|
|
9696
|
+
cookie = serialize(name, value, { path: "/", ...opt });
|
|
9697
|
+
}
|
|
9698
|
+
return cookie;
|
|
9699
|
+
};
|
|
9700
|
+
var setCookie = (c, name, value, opt) => {
|
|
9701
|
+
const cookie = generateCookie(name, value, opt);
|
|
9702
|
+
c.header("Set-Cookie", cookie, { append: true });
|
|
9703
|
+
};
|
|
9704
|
+
var deleteCookie = (c, name, opt) => {
|
|
9705
|
+
const deletedCookie = getCookie(c, name, opt?.prefix);
|
|
9706
|
+
setCookie(c, name, "", { ...opt, maxAge: 0 });
|
|
9707
|
+
return deletedCookie;
|
|
9708
|
+
};
|
|
9709
|
+
|
|
9710
|
+
// src/server/routes/oauth/index.ts
|
|
9480
9711
|
init_types();
|
|
9481
9712
|
import { Transactional as Transactional3 } from "@spfn/core/db";
|
|
9482
9713
|
import { ValidationError as ValidationError7 } from "@spfn/core/errors";
|
|
@@ -9525,11 +9756,14 @@ var oauthGoogleCallback = route4.get("/_auth/oauth/google/callback").input({
|
|
|
9525
9756
|
if (!query.code || !query.state) {
|
|
9526
9757
|
return c.redirect(buildOAuthErrorUrl("Missing authorization code or state"));
|
|
9527
9758
|
}
|
|
9759
|
+
const expectedNonce = getCookie(c.raw, COOKIE_NAMES.OAUTH_CSRF);
|
|
9760
|
+
deleteCookie(c.raw, COOKIE_NAMES.OAUTH_CSRF, { path: "/" });
|
|
9528
9761
|
try {
|
|
9529
9762
|
const result = await oauthCallbackService({
|
|
9530
9763
|
provider: "google",
|
|
9531
9764
|
code: query.code,
|
|
9532
|
-
state: query.state
|
|
9765
|
+
state: query.state,
|
|
9766
|
+
expectedNonce
|
|
9533
9767
|
});
|
|
9534
9768
|
return c.redirect(result.redirectUrl);
|
|
9535
9769
|
} catch (err) {
|
|
@@ -9563,7 +9797,15 @@ var oauthStart = route4.post("/_auth/oauth/start").input({
|
|
|
9563
9797
|
})
|
|
9564
9798
|
}).use([rateLimit2({ limit: 20, windowMs: 6e4 })]).skip(["auth"]).handler(async (c) => {
|
|
9565
9799
|
const { body } = await c.data();
|
|
9566
|
-
const
|
|
9800
|
+
const nonce = generateOAuthNonce();
|
|
9801
|
+
setCookie(c.raw, COOKIE_NAMES.OAUTH_CSRF, nonce, {
|
|
9802
|
+
httpOnly: true,
|
|
9803
|
+
secure: process.env.NODE_ENV === "production",
|
|
9804
|
+
sameSite: "Lax",
|
|
9805
|
+
maxAge: 600,
|
|
9806
|
+
path: "/"
|
|
9807
|
+
});
|
|
9808
|
+
const result = await oauthStartService({ ...body, nonce });
|
|
9567
9809
|
return result;
|
|
9568
9810
|
});
|
|
9569
9811
|
var oauthProviders = route4.get("/_auth/oauth/providers").skip(["auth"]).handler(async () => {
|
|
@@ -9647,11 +9889,14 @@ var oauthProviderCallback = route4.get("/_auth/oauth/:provider/callback").input(
|
|
|
9647
9889
|
if (!query.code || !query.state) {
|
|
9648
9890
|
return c.redirect(buildOAuthErrorUrl("Missing authorization code or state"));
|
|
9649
9891
|
}
|
|
9892
|
+
const expectedNonce = getCookie(c.raw, COOKIE_NAMES.OAUTH_CSRF);
|
|
9893
|
+
deleteCookie(c.raw, COOKIE_NAMES.OAUTH_CSRF, { path: "/" });
|
|
9650
9894
|
try {
|
|
9651
9895
|
const result = await oauthCallbackService({
|
|
9652
9896
|
provider: params.provider,
|
|
9653
9897
|
code: query.code,
|
|
9654
|
-
state: query.state
|
|
9898
|
+
state: query.state,
|
|
9899
|
+
expectedNonce
|
|
9655
9900
|
});
|
|
9656
9901
|
return c.redirect(result.redirectUrl);
|
|
9657
9902
|
} catch (err) {
|
|
@@ -10233,6 +10478,7 @@ export {
|
|
|
10233
10478
|
generateKeyPair,
|
|
10234
10479
|
generateKeyPairES256,
|
|
10235
10480
|
generateKeyPairRS256,
|
|
10481
|
+
generateOAuthNonce,
|
|
10236
10482
|
generateToken,
|
|
10237
10483
|
getAllRoles,
|
|
10238
10484
|
getAuth,
|