@stacksjs/auth 0.75.264 → 0.75.267
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/tokens.d.ts +12 -0
- package/dist/tokens.js +4 -2
- package/package.json +14 -14
package/dist/tokens.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { AccessToken, CreateClientOptions, CreateClientResult, OAuthClient, PersonalAccessTokenResult, RefreshTokenResult, TokenScopes } from '@stacksjs/types';
|
|
2
|
+
/**
|
|
3
|
+
* The refresh token read-back is exactly the row that was written.
|
|
4
|
+
*
|
|
5
|
+
* Exported for tests.
|
|
6
|
+
*/
|
|
7
|
+
export declare function verifyRefreshTokenRow(rows: RefreshTokenReadBack[], expected: { accessTokenId: number }): void;
|
|
2
8
|
/**
|
|
3
9
|
* The row that came back is the row that was written.
|
|
4
10
|
*
|
|
@@ -336,6 +342,12 @@ export declare const DEFAULT_TOKENABLE_TYPE: 'users';
|
|
|
336
342
|
* const t = await token()
|
|
337
343
|
*/
|
|
338
344
|
export declare const token: unknown;
|
|
345
|
+
declare interface RefreshTokenReadBack {
|
|
346
|
+
access_token_id: unknown
|
|
347
|
+
revoked: unknown
|
|
348
|
+
expires_at: unknown
|
|
349
|
+
expires_at_matches: boolean | number | null | undefined
|
|
350
|
+
}
|
|
339
351
|
export declare interface TokenOwnerCredentialState {
|
|
340
352
|
exists: boolean
|
|
341
353
|
passwordChangedAt: Date | null
|
package/dist/tokens.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import{createHash,randomBytes}from"node:crypto";import{config}from"@stacksjs/config";import{db,getDatabaseDialect,markContextWrote,mutationCount}from"@stacksjs/database/runtime";import{HttpError}from"@stacksjs/error-handling";import{getCurrentRequest}from"@stacksjs/router";import{makeHash}from"@stacksjs/security";import{revokeTokenPair,revokeTokenPairs}from"./token-revocation";import{requestToken}from"./request-token";import{tokenDate,tokenTimestamps}from"./token-dates";import{parseSqlDateTime,sqlDateTime,sqlDateTimeLiteral,sqlHelpers}from"@stacksjs/database/runtime";function tokenSql(){return sqlHelpers(getDatabaseDialect())}function appNow(){return sqlDateTimeLiteral()}function validTokenExpiry(value){if(value==null)return!0;const expiry=parseSqlDateTime(value);return expiry!=null&&expiry.getTime()>Date.now()}async function verifyRefreshTokenInsert(trx,hash,accessTokenId,expiresAt){const{param}=tokenSql(),rows=await trx.unsafe(`
|
|
2
|
-
SELECT access_token_id, revoked, expires_at
|
|
3
|
-
|
|
2
|
+
SELECT access_token_id, revoked, expires_at,
|
|
3
|
+
(expires_at = ${param(1)}) AS expires_at_matches
|
|
4
|
+
FROM oauth_refresh_tokens WHERE token = ${param(2)}
|
|
5
|
+
`,[sqlDateTime(expiresAt),hash]);verifyRefreshTokenRow(rows,{accessTokenId})}export function verifyRefreshTokenRow(rows,expected){const row=rows[0];if(rows.length!==1||!row)throw new HttpError(500,`Failed to persist the requested refresh token: ${rows.length===0?"no row came back":`${rows.length} rows came back`}`);failOnMismatch("refresh token",[["access_token_id",String(row.access_token_id)===String(expected.accessTokenId)],["revoked",row.revoked===!1||row.revoked===0],["expires_at",storedAsWritten(row.expires_at_matches)]])}function failOnMismatch(what,checks){const differed=checks.filter(([,ok])=>!ok).map(([field])=>field);if(differed.length>0)throw new HttpError(500,`Failed to persist the requested ${what}: ${differed.join(", ")} did not match what was written`)}function storedAsWritten(matches){return matches===!0||matches===1}export function verifyAccessTokenInsert(row,expected){failOnMismatch("access token",[["tokenable_id",String(row.tokenable_id)===String(expected.ownerId)],["user_id",String(row.user_id)===String(expected.ownerId)],["tokenable_type",row.tokenable_type===expected.ownerType],["oauth_client_id",String(row.oauth_client_id)===String(expected.clientId)],["revoked",row.revoked===!1||row.revoked===0],["expires_at",storedAsWritten(row.expires_at_matches)],["scopes",JSON.stringify(parseScopes(row.scopes))===JSON.stringify(expected.scopes)]])}function refreshDeadline(days){const{isMysql}=tokenSql(),deadline=new Date(Date.now()+days*24*60*60*1000);if(isMysql)deadline.setUTCMilliseconds(0);return deadline}function hashToken(token){return createHash("sha256").update(token).digest("hex")}function bearerLookupHash(bearer){const colonIdx=bearer.indexOf(":"),lookup=colonIdx===-1?bearer:bearer.substring(0,colonIdx);return hashToken(lookup)}function generateSecureToken(bytes=40){return randomBytes(bytes).toString("hex")}export const DEFAULT_TOKENABLE_TYPE="users";function databaseBoolean(value){return value===!0||value===1||value===1n||value==="1"||value==="t"}function delegatedContext(row){return{grantId:row.oauth_grant_id??null,resources:row.oauth_grant_id?parseScopes(row.resources):[],audiences:row.oauth_grant_id?parseScopes(row.audiences):[],workspaceId:row.oauth_grant_id?row.workspace_id??null:null}}export async function getTokenOwnerCredentialState(ownerId,q=db,ownerType=DEFAULT_TOKENABLE_TYPE){const{isMysql,isPostgres,param}=tokenSql();if(ownerId===null||ownerId===void 0)return{exists:!1,passwordChangedAt:null};const quote=isMysql?"`":'"',table=`${quote}${ownerType.replaceAll(quote,quote+quote)}${quote}`,readOwner=async(includePasswordStamp)=>{const row=(await q.unsafe(`
|
|
4
6
|
SELECT ${includePasswordStamp?"id, password_changed_at":"id"} FROM ${table} WHERE id = ${param(1)} LIMIT 1
|
|
5
7
|
`,[ownerId]))[0];if(!row)return{exists:!1,passwordChangedAt:null};const value=row.password_changed_at;return{exists:!0,passwordChangedAt:value===null||value===void 0?null:parseSqlDateTime(value)}};try{if(isMysql){const schema=(await q.unsafe(`
|
|
6
8
|
SELECT
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/auth",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.75.
|
|
5
|
+
"version": "0.75.267",
|
|
6
6
|
"description": "A more simplistic way to authenticate.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -59,19 +59,19 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@stacksjs/bun-router": "^0.1.24",
|
|
62
|
-
"@stacksjs/cache": "0.75.
|
|
63
|
-
"@stacksjs/config": "0.75.
|
|
64
|
-
"@stacksjs/database": "0.75.
|
|
65
|
-
"@stacksjs/email": "0.75.
|
|
66
|
-
"@stacksjs/env": "0.75.
|
|
67
|
-
"@stacksjs/error-handling": "0.75.
|
|
68
|
-
"@stacksjs/logging": "0.75.
|
|
69
|
-
"@stacksjs/orm": "0.75.
|
|
70
|
-
"@stacksjs/path": "0.75.
|
|
71
|
-
"@stacksjs/router": "0.75.
|
|
72
|
-
"@stacksjs/security": "0.75.
|
|
73
|
-
"@stacksjs/socials": "0.75.
|
|
74
|
-
"@stacksjs/storage": "0.75.
|
|
62
|
+
"@stacksjs/cache": "0.75.267",
|
|
63
|
+
"@stacksjs/config": "0.75.267",
|
|
64
|
+
"@stacksjs/database": "0.75.267",
|
|
65
|
+
"@stacksjs/email": "0.75.267",
|
|
66
|
+
"@stacksjs/env": "0.75.267",
|
|
67
|
+
"@stacksjs/error-handling": "0.75.267",
|
|
68
|
+
"@stacksjs/logging": "0.75.267",
|
|
69
|
+
"@stacksjs/orm": "0.75.267",
|
|
70
|
+
"@stacksjs/path": "0.75.267",
|
|
71
|
+
"@stacksjs/router": "0.75.267",
|
|
72
|
+
"@stacksjs/security": "0.75.267",
|
|
73
|
+
"@stacksjs/socials": "0.75.267",
|
|
74
|
+
"@stacksjs/storage": "0.75.267",
|
|
75
75
|
"@stacksjs/ts-auth": "^0.4.7",
|
|
76
76
|
"ts-qr-codes": "^0.1.8"
|
|
77
77
|
},
|