diff --git a/.changeset/light-spoons-listen.md b/.changeset/light-spoons-listen.md new file mode 100644 index 0000000000..ec3a85cb0d --- /dev/null +++ b/.changeset/light-spoons-listen.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Fixed a bug where OAuth state parameters would be serialized as the string `'undefined'`. diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 26bd5b408e..38ad491b19 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -50,6 +50,7 @@ "jose": "^1.27.1", "jwt-decode": "^3.1.0", "knex": "^0.95.1", + "lodash": "^4.17.21", "luxon": "^2.0.2", "minimatch": "^3.0.3", "morgan": "^1.10.0", diff --git a/plugins/auth-backend/src/lib/oauth/helpers.test.ts b/plugins/auth-backend/src/lib/oauth/helpers.test.ts index 00161ff8cf..8af1d2f2ad 100644 --- a/plugins/auth-backend/src/lib/oauth/helpers.test.ts +++ b/plugins/auth-backend/src/lib/oauth/helpers.test.ts @@ -15,9 +15,39 @@ */ import express from 'express'; -import { verifyNonce, encodeState } from './helpers'; +import { verifyNonce, encodeState, readState } from './helpers'; describe('OAuthProvider Utils', () => { + describe('encodeState', () => { + it('should serialized values', () => { + const state = { + nonce: '123', + env: 'development', + origin: 'https://example.com', + }; + + const encoded = encodeState(state); + expect(encoded).toBe( + Buffer.from( + 'nonce=123&env=development&origin=https%3A%2F%2Fexample.com', + ).toString('hex'), + ); + + expect(readState(encoded)).toEqual(state); + }); + + it('should not include undefined values', () => { + const state = { nonce: '123', env: 'development', origin: undefined }; + + const encoded = encodeState(state); + expect(encoded).toBe( + Buffer.from('nonce=123&env=development').toString('hex'), + ); + + expect(readState(encoded)).toEqual(state); + }); + }); + describe('verifyNonce', () => { it('should throw error if cookie nonce missing', () => { const state = { nonce: 'NONCE', env: 'development' }; diff --git a/plugins/auth-backend/src/lib/oauth/helpers.ts b/plugins/auth-backend/src/lib/oauth/helpers.ts index ead9acae27..17e3769d21 100644 --- a/plugins/auth-backend/src/lib/oauth/helpers.ts +++ b/plugins/auth-backend/src/lib/oauth/helpers.ts @@ -16,6 +16,7 @@ import express from 'express'; import { OAuthState } from './types'; +import pickBy from 'lodash/pickBy'; export const readState = (stateString: string): OAuthState => { const state = Object.fromEntries( @@ -34,7 +35,9 @@ export const readState = (stateString: string): OAuthState => { }; export const encodeState = (state: OAuthState): string => { - const stateString = new URLSearchParams(state).toString(); + const stateString = new URLSearchParams( + pickBy(state, value => value !== undefined), + ).toString(); return Buffer.from(stateString, 'utf-8').toString('hex'); };