diff --git a/README.md b/README.md index 73ba0e6..0cf9b75 100644 --- a/README.md +++ b/README.md @@ -221,20 +221,20 @@ See the [`example/`](./examples/) folder for more examples. ## Reference This Fastify plugin decorates the fastify instance with the [`simple-oauth2`](https://github.com/lelylan/simple-oauth2) -instance inside a **namespace** specified by the property `name`. +instance inside a **namespace** specified by the property `name` both with and without an `oauth2` prefix. E.g. For `name: 'customOauth2'`, the `simple-oauth2` instance will become accessible like this: -`fastify.customOauth2.oauth2` +`fastify.oauth2CustomOauth2.oauth2` and `fastify.customOauth2.oauth2` In this manner we are able to register multiple OAuth providers and each OAuth providers `simple-oauth2` instance will live in it's own **namespace**. E.g. -- `fastify.facebook.oauth2` -- `fastify.github.oauth2` -- `fastify.spotify.oauth2` -- `fastify.vkontakte.oauth2` +- `fastify.oauth2Facebook.oauth2` +- `fastify.oauth2Github.oauth2` +- `fastify.oauth2Spotify.oauth2` +- `fastify.oauth2Vkontakte.oauth2` Assuming we have registered multiple OAuth providers like this: @@ -263,7 +263,7 @@ fastify.googleOAuth2.getNewAccessTokenUsingRefreshToken(currentAccessToken, (err ```js fastify.get('/external', { /* Hooks can be used here */ }, async (req, reply) => { - const authorizationEndpoint = fastify.customOAuth2.generateAuthorizationUri(req, reply); + const authorizationEndpoint = fastify.oauth2CustomOAuth2.generateAuthorizationUri(req, reply); reply.redirect(authorizationEndpoint) }); ``` @@ -282,8 +282,8 @@ fastify.googleOAuth2.revokeAllToken(currentAccessToken, undefined, (err) => { ``` E.g. For `name: 'customOauth2'`, the helpers `getAccessTokenFromAuthorizationCodeFlow` and `getNewAccessTokenUsingRefreshToken` will become accessible like this: -- `fastify.customOauth2.getAccessTokenFromAuthorizationCodeFlow` -- `fastify.customOauth2.getNewAccessTokenUsingRefreshToken` +- `fastify.oauth2CustomOauth2.getAccessTokenFromAuthorizationCodeFlow` +- `fastify.oauth2CustomOauth2.getNewAccessTokenUsingRefreshToken` ## Usage with TypeScript @@ -302,6 +302,8 @@ declare module 'fastify' { } ``` +All auth configurations are made available with an `oauth2` prefix that's typed to `OAuth2Namespace | undefined`, such as eg. `fastify.oauth2CustomOauth2` for `customOauth2`. + ## Provider Quirks The following providers require additional work to be set up correctly. diff --git a/index.js b/index.js index f9ec675..816eb4d 100644 --- a/index.js +++ b/index.js @@ -1,12 +1,12 @@ 'use strict' -const { randomBytes } = require('crypto') +const { randomBytes } = require('node:crypto') const fp = require('fastify-plugin') const { AuthorizationCode } = require('simple-oauth2') const kGenerateCallbackUriParams = Symbol.for('fastify-oauth2.generate-callback-uri-params') -const { promisify, callbackify } = require('util') +const { promisify, callbackify } = require('node:util') const USER_AGENT = 'fastify-oauth2' @@ -206,15 +206,18 @@ function fastifyOauth2 (fastify, options, next) { fastify.get(startRedirectPath, { schema }, startRedirectHandler) } + const decoration = { + oauth2, + getAccessTokenFromAuthorizationCodeFlow, + getNewAccessTokenUsingRefreshToken, + generateAuthorizationUri, + revokeToken, + revokeAllToken + } + try { - fastify.decorate(name, { - oauth2, - getAccessTokenFromAuthorizationCodeFlow, - getNewAccessTokenUsingRefreshToken, - generateAuthorizationUri, - revokeToken, - revokeAllToken - }) + fastify.decorate(name, decoration) + fastify.decorate(`oauth2${name.slice(0, 1).toUpperCase()}${name.slice(1)}`, decoration) } catch (e) { next(e) return diff --git a/package.json b/package.json index ae7dd07..2e549a5 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "snazzy": "^9.0.0", "standard": "^17.1.0", "tap": "^16.3.8", - "tsd": "^0.28.1" + "tsd": "^0.29.0" }, "dependencies": { "@fastify/cookie": "^9.0.4", diff --git a/test/index.test.js b/test/index.test.js index 635c7f9..7eeb2a4 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -3,7 +3,7 @@ const t = require('tap') const nock = require('nock') const createFastify = require('fastify') -const crypto = require('crypto') +const crypto = require('node:crypto') const fastifyOauth2 = require('..') nock.disableNetConnect() @@ -85,6 +85,9 @@ t.test('fastify-oauth2', t => { }) fastify.get('/', function (request, reply) { + if (this.githubOAuth2 !== this.oauth2GithubOAuth2) { + throw new Error('Expected oauth2GithubOAuth2 to match githubOAuth2') + } this.githubOAuth2.getAccessTokenFromAuthorizationCodeFlow(request, (err, result) => { if (err) throw err diff --git a/types/index.d.ts b/types/index.d.ts index 5ed0543..e97ac3e 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -162,3 +162,12 @@ declare namespace fastifyOauth2 { declare function fastifyOauth2(...params: Parameters): ReturnType export = fastifyOauth2 + +type UpperCaseCharacters = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z'; + +declare module 'fastify' { + interface FastifyInstance { + // UpperCaseCharacters ensures that the name has at least one character in it + is a simple camel-case:ification + [key: `oauth2${UpperCaseCharacters}${string}`]: fastifyOauth2.OAuth2Namespace | undefined; + } +} diff --git a/types/index.test-d.ts b/types/index.test-d.ts index 555c43b..5ecd830 100644 --- a/types/index.test-d.ts +++ b/types/index.test-d.ts @@ -121,6 +121,7 @@ expectAssignable(fastifyOauth2.YANDEX_CONFIGURATION); server.get('/testOauth/callback', async (request, reply) => { expectType(server.testOAuthName); + expectType(server.oauth2TestOAuthName); expectType(await server.testOAuthName.getAccessTokenFromAuthorizationCodeFlow(request)); expectType>(server.testOAuthName.getAccessTokenFromAuthorizationCodeFlow(request));