Skip to content

Commit

Permalink
fix: ensure streamed responses are handled (#288)
Browse files Browse the repository at this point in the history
  • Loading branch information
ojeytonwilliams authored Feb 9, 2025
1 parent 4d19f84 commit c4ed0f0
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 2 deletions.
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ function fastifyOauth2 (fastify, options, next) {

function onUserinfoResponse (res) {
let rawData = ''
res.on('data', (chunk) => { rawData = chunk })
res.on('data', (chunk) => { rawData += chunk })
res.on('end', () => {
try {
cb(null, JSON.parse(rawData)) // should always be JSON since we don't do jwt auth response
Expand Down
60 changes: 59 additions & 1 deletion test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const t = require('tap')
const nock = require('nock')
const createFastify = require('fastify')
const crypto = require('node:crypto')
const { Readable } = require('node:stream')
const fastifyOauth2 = require('..')

nock.disableNetConnect()
Expand Down Expand Up @@ -132,12 +133,31 @@ function makeRequests (t, fastify, userAgentHeaderMatcher, pkce, discoveryHost,
.query({ a: 1 })
.reply(200, { sub: 'github.subjectid' })
}
} else if (discoveryHostOptions.userinfoBadData) {
userinfoScope = nock(gitHost)
.matchHeader('Authorization', 'Bearer my-access-token-refreshed')
.matchHeader('User-Agent', userAgentHeaderMatcher || 'fastify-oauth2')
.get('/me')
.reply(200, 'not a json')
} else if (discoveryHostOptions.userinfoChunks) {
function createStream () {
const stream = new Readable()
stream.push('{"sub":"gith')
stream.push('ub.subjectid"}')
stream.push(null)
return stream
}
userinfoScope = nock(gitHost)
.matchHeader('Authorization', 'Bearer my-access-token-refreshed')
.matchHeader('User-Agent', userAgentHeaderMatcher || 'fastify-oauth2')
.get('/me')
.reply(200, createStream())
} else {
userinfoScope = nock(gitHost)
.matchHeader('Authorization', 'Bearer my-access-token-refreshed')
.matchHeader('User-Agent', userAgentHeaderMatcher || 'fastify-oauth2')
.get('/me')
.reply(200, discoveryHostOptions.userinfoBadData ? 'not a json' : { sub: 'github.subjectid' })
.reply(200, { sub: 'github.subjectid' })
}
}
}
Expand Down Expand Up @@ -780,6 +800,44 @@ t.test('fastify-oauth2', t => {
makeRequests(t, fastify, undefined, 'S256', 'https://github.com', false, { userinfoEndpoint: 'https://github.com/me' })
})

t.test('discovery with userinfo -> handles responses with multiple "data" events', t => {
const fastify = createFastify({ logger: { level: 'silent' } })

fastify.register(fastifyOauth2, {
name: 'githubOAuth2',
credentials: {
client: {
id: 'my-client-id',
secret: 'my-secret'
}
},
startRedirectPath: '/login/github',
callbackUri: 'http://localhost:3000/callback',
scope: ['notifications'],
discovery: {
issuer: 'https://github.com'
}
})

fastify.get('/', async function (request, reply) {
const result = await this.githubOAuth2.getAccessTokenFromAuthorizationCodeFlow(request, reply)
const refreshResult = await this.githubOAuth2.getNewAccessTokenUsingRefreshToken(result.token)
await new Promise((resolve) => {
this.githubOAuth2.userinfo(refreshResult.token, {}, (err, userinfo) => {
t.error(err)
t.equal(userinfo.sub, 'github.subjectid', 'should match an id')
resolve()
})
})

return { ...refreshResult.token, expires_at: undefined }
})

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

makeRequests(t, fastify, undefined, 'S256', 'https://github.com', false, { userinfoEndpoint: 'https://github.com/me', userinfoChunks: true })
})

t.test('discovery with userinfo -> fails gracefully when at format is bad', t => {
const fastify = createFastify({ logger: { level: 'silent' } })

Expand Down

0 comments on commit c4ed0f0

Please sign in to comment.