Skip to content

Commit cc917b2

Browse files
climba03003Eomm
andauthored
feat!: update fastify and simple-oauth2 (#172)
* major: upgrade to fastify v4 (#167) * major: upgrade to fastify v4 * chore: fix meta * feat!: simple-oauth2@4 (#170) * feat: simple-oauth2@4 * fix: typescript error Co-authored-by: Manuel Spigolon <[email protected]>
1 parent 77aa8ac commit cc917b2

File tree

10 files changed

+93
-39
lines changed

10 files changed

+93
-39
lines changed

examples/apple.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,4 @@ fastify.get('/login/apple/callback', function (request, reply) {
5858
)
5959
})
6060

61-
fastify.listen(3000)
61+
fastify.listen({ port: 3000 })

examples/facebook.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,4 @@ fastify.get('/login/facebook/callback', function (request, reply) {
4343
})
4444
})
4545

46-
fastify.listen(3000)
46+
fastify.listen({ port: 3000 })

examples/google.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,4 @@ fastify.get('/login/google/callback', function (request, reply) {
4444
})
4545
})
4646

47-
fastify.listen(3000)
47+
fastify.listen({ port: 3000 })

examples/vatsim-dev.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,4 @@ fastify.get('/login/vatsim/callback', function (request, reply) {
5050
)
5151
})
5252

53-
fastify.listen(3000)
53+
fastify.listen({ port: 3000 })

examples/vatsim.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,4 @@ fastify.get('/login/vatsim/callback', function (request, reply) {
5050
)
5151
})
5252

53-
fastify.listen(3000)
53+
fastify.listen({ port: 3000 })

index.d.ts

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,79 @@ export interface FastifyOAuth2Options {
3131
schema?: object;
3232
}
3333

34-
export interface OAuth2Token {
34+
export interface Token {
3535
token_type: 'bearer';
3636
access_token: string;
3737
refresh_token?: string;
3838
expires_in: number;
39+
expires_at: Date;
40+
}
41+
42+
export interface OAuth2Token {
43+
/**
44+
* Immutable object containing the token object provided while constructing a new access token instance.
45+
* This property will usually have the schema as specified by RFC6750,
46+
* but the exact properties may vary between authorization servers.
47+
*/
48+
token: Token;
49+
50+
/**
51+
* Determines if the current access token is definitely expired or not
52+
* @param expirationWindowSeconds Window of time before the actual expiration to refresh the token. Defaults to 0.
53+
*/
54+
expired(expirationWindowSeconds?: number): boolean;
55+
56+
/** Refresh the access token */
57+
refresh(params?: {}): Promise<OAuth2Token>;
58+
59+
/** Revoke access or refresh token */
60+
revoke(tokenType: 'access_token' | 'refresh_token'): Promise<void>;
61+
62+
/** Revoke both the existing access and refresh tokens */
63+
revokeAll(): Promise<void>;
3964
}
4065

4166
export interface ProviderConfiguration {
42-
authorizeHost: string;
43-
authorizePath: string;
67+
/** String used to set the host to request the tokens to. Required. */
4468
tokenHost: string;
45-
tokenPath: string;
69+
/** String path to request an access token. Default to /oauth/token. */
70+
tokenPath?: string | undefined;
71+
/** String path to revoke an access token. Default to /oauth/revoke. */
72+
revokePath?: string | undefined;
73+
/** String used to set the host to request an "authorization code". Default to the value set on auth.tokenHost. */
74+
authorizeHost?: string | undefined;
75+
/** String path to request an authorization code. Default to /oauth/authorize. */
76+
authorizePath?: string | undefined;
4677
}
4778

4879
export interface Credentials {
4980
client: {
50-
id: string;
51-
secret: string;
81+
/** Service registered client id. Required. */
82+
id: string;
83+
/** Service registered client secret. Required. */
84+
secret: string;
85+
/** Parameter name used to send the client secret. Default to client_secret. */
86+
secretParamName?: string | undefined;
87+
/** Parameter name used to send the client id. Default to client_id. */
88+
idParamName?: string | undefined;
5289
};
5390
auth: ProviderConfiguration;
91+
/**
92+
* Used to set global options to the internal http library (wreck).
93+
* All options except baseUrl are allowed
94+
* Defaults to header.Accept = "application/json"
95+
*/
96+
http?: {} | undefined;
97+
options?: {
98+
/** Format of data sent in the request body. Defaults to form. */
99+
bodyFormat?: "json" | "form" | undefined;
100+
/**
101+
* Indicates the method used to send the client.id/client.secret authorization params at the token request.
102+
* If set to body, the bodyFormat option will be used to format the credentials.
103+
* Defaults to header
104+
*/
105+
authorizationMethod?: "header" | "body" | undefined;
106+
} | undefined;
54107
}
55108

56109
export interface OAuth2Namespace {
@@ -64,12 +117,12 @@ export interface OAuth2Namespace {
64117
): void;
65118

66119
getNewAccessTokenUsingRefreshToken(
67-
refreshToken: string,
120+
refreshToken: Token,
68121
params: Object,
69122
callback: (err: any, token: OAuth2Token) => void,
70123
): void;
71124

72-
getNewAccessTokenUsingRefreshToken(refreshToken: string, params: Object): Promise<OAuth2Token>;
125+
getNewAccessTokenUsingRefreshToken(refreshToken: Token, params: Object): Promise<OAuth2Token>;
73126

74127
generateAuthorizationUri(
75128
request: FastifyRequest,

index.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
const defaultState = require('crypto').randomBytes(10).toString('hex')
44

55
const fp = require('fastify-plugin')
6-
const oauth2Module = require('simple-oauth2')
6+
const { AuthorizationCode } = require('simple-oauth2')
77
const kGenerateCallbackUriParams = Symbol.for('fastify-oauth2.generate-callback-uri-params')
88

99
const promisify = require('util').promisify
@@ -77,7 +77,7 @@ const oauthPlugin = fp(function (fastify, options, next) {
7777
state
7878
})
7979

80-
const authorizationUri = oauth2.authorizationCode.authorizeURL(urlOptions)
80+
const authorizationUri = oauth2.authorizeURL(urlOptions)
8181
return authorizationUri
8282
}
8383

@@ -88,7 +88,7 @@ const oauthPlugin = fp(function (fastify, options, next) {
8888
}
8989

9090
const cbk = function (o, code, callback) {
91-
return callbackify(o.oauth2.authorizationCode.getToken.bind(o.oauth2.authorizationCode, {
91+
return callbackify(o.oauth2.getToken.bind(o.oauth2, {
9292
code,
9393
redirect_uri: callbackUri
9494
}))(callback)
@@ -116,7 +116,7 @@ const oauthPlugin = fp(function (fastify, options, next) {
116116
}
117117

118118
function getNewAccessTokenUsingRefreshTokenCallbacked (refreshToken, params, callback) {
119-
const accessToken = fastify[name].oauth2.accessToken.create({ refresh_token: refreshToken })
119+
const accessToken = fastify[name].oauth2.createToken(refreshToken)
120120
callbackify(accessToken.refresh.bind(accessToken, params))(callback)
121121
}
122122
const getNewAccessTokenUsingRefreshTokenPromisified = promisify(getNewAccessTokenUsingRefreshTokenCallbacked)
@@ -127,7 +127,7 @@ const oauthPlugin = fp(function (fastify, options, next) {
127127
}
128128
getNewAccessTokenUsingRefreshTokenCallbacked(refreshToken, params, callback)
129129
}
130-
const oauth2 = oauth2Module.create(credentials)
130+
const oauth2 = new AuthorizationCode(credentials)
131131

132132
if (startRedirectPath) {
133133
fastify.get(startRedirectPath, { schema }, startRedirectHandler)
@@ -147,7 +147,7 @@ const oauthPlugin = fp(function (fastify, options, next) {
147147

148148
next()
149149
}, {
150-
fastify: '>=3.x',
150+
fastify: '4.x',
151151
name: '@fastify/oauth2'
152152
})
153153

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"scripts": {
88
"coverage": "npm run unit -- --cov --coverage-report=html",
99
"lint": "standard | snazzy",
10+
"lint:fix": "standard --fix",
1011
"test": "npm run unit && npm run test:typescript",
1112
"test:typescript": "tsd",
1213
"unit": "tap -J \"test/*.test.js\""
@@ -28,7 +29,7 @@
2829
"devDependencies": {
2930
"@fastify/pre-commit": "^2.0.2",
3031
"@types/node": "^18.0.0",
31-
"fastify": "^3.25.3",
32+
"fastify": "^4.3.0",
3233
"nock": "^13.2.1",
3334
"simple-get": "^4.0.0",
3435
"snazzy": "^9.0.0",
@@ -38,7 +39,7 @@
3839
},
3940
"dependencies": {
4041
"fastify-plugin": "^4.0.0",
41-
"simple-oauth2": "^3.4.0"
42+
"simple-oauth2": "^4.3.0"
4243
},
4344
"tsd": {
4445
"directory": "test/types"

test/plugin.test.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const oauthPlugin = require('..')
99
nock.disableNetConnect()
1010

1111
function makeRequests (t, fastify) {
12-
fastify.listen(0, function (err) {
12+
fastify.listen({ port: 0 }, function (err) {
1313
t.error(err)
1414

1515
fastify.inject({
@@ -92,7 +92,7 @@ t.test('fastify-oauth2', t => {
9292
if (err) throw err
9393

9494
// attempts to refresh the token
95-
this.githubOAuth2.getNewAccessTokenUsingRefreshToken(result.refresh_token, undefined, (err, result) => {
95+
this.githubOAuth2.getNewAccessTokenUsingRefreshToken(result.token, undefined, (err, result) => {
9696
if (err) throw err
9797

9898
const newToken = result
@@ -133,7 +133,7 @@ t.test('fastify-oauth2', t => {
133133
return this.githubOAuth2.getAccessTokenFromAuthorizationCodeFlow(request)
134134
.then(result => {
135135
// attempts to refresh the token
136-
return this.githubOAuth2.getNewAccessTokenUsingRefreshToken(result.refresh_token)
136+
return this.githubOAuth2.getNewAccessTokenUsingRefreshToken(result.token)
137137
})
138138
.then(token => {
139139
return {
@@ -280,7 +280,7 @@ t.test('options.callbackUriParams', t => {
280280

281281
t.teardown(fastify.close.bind(fastify))
282282

283-
fastify.listen(0, function (err) {
283+
fastify.listen({ port: 0 }, function (err) {
284284
t.error(err)
285285

286286
fastify.inject({
@@ -322,7 +322,7 @@ t.test('options.generateStateFunction with request', t => {
322322

323323
t.teardown(fastify.close.bind(fastify))
324324

325-
fastify.listen(0, function (err) {
325+
fastify.listen({ port: 0 }, function (err) {
326326
t.error(err)
327327

328328
fastify.inject({
@@ -513,7 +513,7 @@ t.test('options.schema should be a object', t => {
513513
})
514514

515515
t.test('options.schema', t => {
516-
const fastify = createFastify({ logger: { level: 'silent' } })
516+
const fastify = createFastify({ logger: { level: 'silent' }, exposeHeadRoutes: false })
517517

518518
fastify.addHook('onRoute', function (routeOptions) {
519519
t.strictSame(routeOptions.schema, { tags: ['oauth2', 'oauth'] })
@@ -588,7 +588,7 @@ t.test('preset configuration generate-callback-uri-params', t => {
588588

589589
t.teardown(fastify.close.bind(fastify))
590590

591-
fastify.listen(0, function (err) {
591+
fastify.listen({ port: 0 }, function (err) {
592592
t.error(err)
593593

594594
fastify.inject({
@@ -624,7 +624,7 @@ t.test('preset configuration generate-callback-uri-params', t => {
624624

625625
t.teardown(fastify.close.bind(fastify))
626626

627-
fastify.listen(0, function (err) {
627+
fastify.listen({ port: 0 }, function (err) {
628628
t.error(err)
629629

630630
fastify.inject({
@@ -660,7 +660,7 @@ t.test('preset configuration generate-callback-uri-params', t => {
660660

661661
t.teardown(fastify.close.bind(fastify))
662662

663-
fastify.listen(0, function (err) {
663+
fastify.listen({ port: 0 }, function (err) {
664664
t.error(err)
665665

666666
fastify.inject({

test/types/index.test-d.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import fastifyOauth2, { Credentials, OAuth2Namespace, OAuth2Token, ProviderConfi
88
const auth = fastifyOauth2.GOOGLE_CONFIGURATION;
99
const scope = ['r_emailaddress', 'r_basicprofile'];
1010
const tags = ['oauth2', 'oauth'];
11-
const credentials = {
11+
const credentials: Credentials = {
1212
client: {
1313
id: 'test_id',
1414
secret: 'test_secret',
@@ -77,35 +77,35 @@ server.get('/testOauth/callback', async request => {
7777
expectError<void>(server.testOAuthName.getAccessTokenFromAuthorizationCodeFlow(request)); // error because function call does not pass a callback as second argument.
7878

7979
const token = await server.testOAuthName.getAccessTokenFromAuthorizationCodeFlow(request);
80-
if (token.refresh_token) {
80+
if (token.token.refresh_token) {
8181
expectType<OAuth2Token>(
82-
await server.testOAuthName.getNewAccessTokenUsingRefreshToken(token.refresh_token, {}),
82+
await server.testOAuthName.getNewAccessTokenUsingRefreshToken(token.token, {}),
8383
);
8484
expectType<Promise<OAuth2Token>>(
85-
server.testOAuthName.getNewAccessTokenUsingRefreshToken(token.refresh_token, {}),
85+
server.testOAuthName.getNewAccessTokenUsingRefreshToken(token.token, {}),
8686
);
8787
expectType<void>(
8888
server.testOAuthName.getNewAccessTokenUsingRefreshToken(
89-
token.refresh_token,
89+
token.token,
9090
{},
9191
(err: any, t: OAuth2Token): void => { },
9292
),
9393
);
9494

95-
expectError<void>(await server.testOAuthName.getNewAccessTokenUsingRefreshToken(token.refresh_token, {})); // error because Promise should not return void
95+
expectError<void>(await server.testOAuthName.getNewAccessTokenUsingRefreshToken(token.token, {})); // error because Promise should not return void
9696
expectError<OAuth2Token>(
9797
server.testOAuthName.getNewAccessTokenUsingRefreshToken(
98-
token.refresh_token,
98+
token.token,
9999
{},
100100
(err: any, t: OAuth2Token): void => { },
101101
),
102102
); // error because non-Promise function call should return void and have a callback argument
103-
expectError<void>(server.testOAuthName.getNewAccessTokenUsingRefreshToken(token.refresh_token, {})); // error because function call does not pass a callback as second argument.
103+
expectError<void>(server.testOAuthName.getNewAccessTokenUsingRefreshToken(token.token, {})); // error because function call does not pass a callback as second argument.
104104
}
105105

106106
expectType<string>(server.testOAuthName.generateAuthorizationUri(request));
107107

108108
return {
109-
access_token: token.access_token,
109+
access_token: token.token.access_token,
110110
};
111111
});

0 commit comments

Comments
 (0)