Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@a-type/auth

Package Overview
Dependencies
Maintainers
1
Versions
53
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@a-type/auth - npm Package Compare versions

Comparing version 0.4.9 to 0.4.11

28

dist/esm/handlers.js

@@ -353,10 +353,22 @@ import { AuthError } from './error.js';

}
const { headers, searchParams } = await sessions.refreshSession(accessToken, refreshToken);
return new Response(JSON.stringify({
ok: true,
refreshToken: searchParams.get('refreshToken'),
}), {
status: 200,
headers: Object.assign(Object.assign({}, headers), { 'content-type': 'application/json' }),
});
try {
const { headers, searchParams } = await sessions.refreshSession(accessToken, refreshToken);
return new Response(JSON.stringify({
ok: true,
refreshToken: searchParams.get('refreshToken'),
}), {
status: 200,
headers: Object.assign(Object.assign({}, headers), { 'content-type': 'application/json' }),
});
}
catch (err) {
if (err instanceof AuthError && err.statusCode === 401) {
return new Response(JSON.stringify({
ok: false,
}), {
status: 401,
headers: Object.assign(Object.assign({}, sessions.clearSession().headers), { 'content-type': 'application/json' }),
});
}
}
}

@@ -363,0 +375,0 @@ return {

@@ -69,14 +69,23 @@ import { parse, serialize } from 'cookie';

this.refreshSession = async (accessToken, refreshToken) => {
const refreshData = await jwtVerify(refreshToken, this.secret, {
issuer: this.options.issuer,
audience: this.options.audience,
});
// verify the signature of the token
await compactVerify(accessToken, this.secret);
const accessData = decodeJwt(accessToken);
if (refreshData.payload.jti !== accessData.jti) {
try {
const refreshData = await jwtVerify(refreshToken, this.secret, {
issuer: this.options.issuer,
audience: this.options.audience,
});
// verify the signature of the token
await compactVerify(accessToken, this.secret);
const accessData = decodeJwt(accessToken);
if (refreshData.payload.jti !== accessData.jti) {
throw new AuthError('Invalid refresh token', 400);
}
const session = this.readSessionFromPayload(accessData);
return this.updateSession(session, { sendRefreshToken: true });
}
catch (err) {
if (err instanceof Error &&
(err.message.includes('JWTExpired') || err.name === 'JWTExpired')) {
throw new AuthError('Refresh token expired', 401);
}
throw new AuthError('Invalid refresh token', 400);
}
const session = this.readSessionFromPayload(accessData);
return this.updateSession(session, { sendRefreshToken: true });
};

@@ -87,2 +96,3 @@ this.updateSession = async (session, { sendRefreshToken, } = { sendRefreshToken: false }) => {

const jwt = await accessTokenBuilder.sign(this.secret);
const parsed = decodeJwt(jwt);
const authCookie = serialize(this.options.cookieName, jwt, {

@@ -92,2 +102,13 @@ httpOnly: true,

path: '/',
secure: this.options.mode === 'production',
// sync access token expiration to refresh token - an expired token
// will still be presented to the server, but the server will reject it
// as expired. the api can then tell the client the token is expired
// and the refresh should be used. once the access token cookie is expired
// and removed, it will instead trigger a fully logged out state.
expires: sendRefreshToken
? this.getRefreshTokenExpirationTime()
: parsed.exp
? new Date(parsed.exp * 1000)
: undefined,
});

@@ -102,2 +123,3 @@ const headers = {

searchParams.set(this.refreshParam, refreshToken);
searchParams.set('refreshTokenExpires', this.getRefreshTokenExpirationTime().toISOString());
}

@@ -110,2 +132,4 @@ return {

this.clearSession = () => {
const searchParams = new URLSearchParams();
searchParams.set(this.refreshParam, 'clear');
return {

@@ -115,2 +139,3 @@ headers: {

},
searchParams,
};

@@ -143,3 +168,3 @@ };

.setIssuedAt()
.setExpirationTime('7d');
.setExpirationTime(this.getRefreshTokenExpirationTime());
if (this.options.issuer) {

@@ -153,2 +178,7 @@ refreshTokenBuilder.setIssuer(this.options.issuer);

};
this.getRefreshTokenExpirationTime = () => {
var _a;
const msFromNow = ((_a = this.options.refreshTokenDurationMinutes) !== null && _a !== void 0 ? _a : 60 * 24 * 14) * 60 * 1000;
return new Date(Date.now() + msFromNow);
};
this.getShortName = (key) => {

@@ -155,0 +185,0 @@ return this.options.shortNames[key];

@@ -86,3 +86,3 @@ import { it, describe, vi, beforeAll, expect } from 'vitest';

// verify that the refresh token is rejected
expect(sessions.refreshSession(badToken, refreshToken)).rejects.toThrowError('signature verification failed');
expect(sessions.refreshSession(badToken, refreshToken)).rejects.toThrowError('Invalid refresh token');
// even a token signed with the right signature whose JTI doesn't

@@ -89,0 +89,0 @@ // match is rejected

@@ -43,3 +43,3 @@ import { AuthDB } from './db.js';

handleSessionRequest: (req: Request) => Promise<Response>;
handleRefreshSessionRequest: (req: Request) => Promise<Response>;
handleRefreshSessionRequest: (req: Request) => Promise<Response | undefined>;
};

@@ -18,2 +18,3 @@ export interface Session {

refreshParam?: string;
refreshTokenDurationMinutes?: number;
shortNames: ShortNames;

@@ -56,5 +57,7 @@ mode?: 'production' | 'development';

};
searchParams: URLSearchParams;
};
private getAccessTokenBuilder;
private getRefreshTokenBuilder;
private getRefreshTokenExpirationTime;
private getShortName;

@@ -61,0 +64,0 @@ private getLongName;

{
"name": "@a-type/auth",
"version": "0.4.9",
"version": "0.4.11",
"description": "My personal auth request handlers",

@@ -5,0 +5,0 @@ "module": "dist/esm/index.js",

@@ -456,20 +456,37 @@ import { AuthDB } from './db.js';

const { headers, searchParams } = await sessions.refreshSession(
accessToken,
refreshToken,
);
try {
const { headers, searchParams } = await sessions.refreshSession(
accessToken,
refreshToken,
);
return new Response(
JSON.stringify({
ok: true,
refreshToken: searchParams.get('refreshToken'),
}),
{
status: 200,
headers: {
...headers,
'content-type': 'application/json',
return new Response(
JSON.stringify({
ok: true,
refreshToken: searchParams.get('refreshToken'),
}),
{
status: 200,
headers: {
...headers,
'content-type': 'application/json',
},
},
},
);
);
} catch (err) {
if (err instanceof AuthError && err.statusCode === 401) {
return new Response(
JSON.stringify({
ok: false,
}),
{
status: 401,
headers: {
...sessions.clearSession().headers,
'content-type': 'application/json',
},
},
);
}
}
}

@@ -476,0 +493,0 @@

@@ -117,3 +117,3 @@ import { it, describe, vi, beforeAll, expect } from 'vitest';

sessions.refreshSession(badToken, refreshToken),
).rejects.toThrowError('signature verification failed');
).rejects.toThrowError('Invalid refresh token');

@@ -120,0 +120,0 @@ // even a token signed with the right signature whose JTI doesn't

@@ -34,2 +34,3 @@ import { parse, serialize } from 'cookie';

refreshParam?: string;
refreshTokenDurationMinutes?: number;
shortNames: ShortNames;

@@ -117,19 +118,29 @@ mode?: 'production' | 'development';

refreshSession = async (accessToken: string, refreshToken: string) => {
const refreshData = await jwtVerify(refreshToken, this.secret, {
issuer: this.options.issuer,
audience: this.options.audience,
});
try {
const refreshData = await jwtVerify(refreshToken, this.secret, {
issuer: this.options.issuer,
audience: this.options.audience,
});
// verify the signature of the token
await compactVerify(accessToken, this.secret);
// verify the signature of the token
await compactVerify(accessToken, this.secret);
const accessData = decodeJwt(accessToken);
const accessData = decodeJwt(accessToken);
if (refreshData.payload.jti !== accessData.jti) {
if (refreshData.payload.jti !== accessData.jti) {
throw new AuthError('Invalid refresh token', 400);
}
const session = this.readSessionFromPayload(accessData);
return this.updateSession(session, { sendRefreshToken: true });
} catch (err) {
if (
err instanceof Error &&
(err.message.includes('JWTExpired') || err.name === 'JWTExpired')
) {
throw new AuthError('Refresh token expired', 401);
}
throw new AuthError('Invalid refresh token', 400);
}
const session = this.readSessionFromPayload(accessData);
return this.updateSession(session, { sendRefreshToken: true });
};

@@ -148,2 +159,3 @@

const jwt = await accessTokenBuilder.sign(this.secret);
const parsed = decodeJwt(jwt);

@@ -154,2 +166,13 @@ const authCookie = serialize(this.options.cookieName, jwt, {

path: '/',
secure: this.options.mode === 'production',
// sync access token expiration to refresh token - an expired token
// will still be presented to the server, but the server will reject it
// as expired. the api can then tell the client the token is expired
// and the refresh should be used. once the access token cookie is expired
// and removed, it will instead trigger a fully logged out state.
expires: sendRefreshToken
? this.getRefreshTokenExpirationTime()
: parsed.exp
? new Date(parsed.exp * 1000)
: undefined,
});

@@ -165,2 +188,6 @@ const headers: Record<string, string> = {

searchParams.set(this.refreshParam, refreshToken);
searchParams.set(
'refreshTokenExpires',
this.getRefreshTokenExpirationTime().toISOString(),
);
}

@@ -175,2 +202,4 @@

clearSession = () => {
const searchParams = new URLSearchParams();
searchParams.set(this.refreshParam, 'clear');
return {

@@ -180,2 +209,3 @@ headers: {

},
searchParams,
};

@@ -214,3 +244,3 @@ };

.setIssuedAt()
.setExpirationTime('7d');
.setExpirationTime(this.getRefreshTokenExpirationTime());

@@ -227,2 +257,8 @@ if (this.options.issuer) {

private getRefreshTokenExpirationTime = () => {
const msFromNow =
(this.options.refreshTokenDurationMinutes ?? 60 * 24 * 14) * 60 * 1000;
return new Date(Date.now() + msFromNow);
};
private getShortName = (key: string) => {

@@ -229,0 +265,0 @@ return (this.options.shortNames as any)[key];

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc