auth-{backend,node}: improved error forwarding from passport helpers

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2024-11-26 19:03:49 +01:00
parent 51bf53cd29
commit c907440f8a
4 changed files with 71 additions and 24 deletions
@@ -272,28 +272,63 @@ describe('PassportStrategyHelper', () => {
);
});
it('should reject with an error if refresh failed', async () => {
class MyCustomOAuth2Error {
getOAuthAccessToken(
_refreshToken: string,
_options: any,
callback: Function,
) {
callback(new Error('Unknown error'));
}
}
it('should forward simple errors', async () => {
class MyCustomRefreshTokenSuccess extends passport.Strategy {
_oauth2 = new MyCustomOAuth2Error();
_oauth2 = new (class {
getOAuthAccessToken(_r: string, _o: any, cb: Function) {
cb(new Error('Unknown error'));
}
})();
}
const mockStrategy = new MyCustomRefreshTokenSuccess();
const refreshTokenPromise = executeRefreshTokenStrategy(
mockStrategy,
'REFRESH_TOKEN',
'a',
await expect(
executeRefreshTokenStrategy(
new MyCustomRefreshTokenSuccess(),
'REFRESH_TOKEN',
'a',
),
).rejects.toThrow(
'Failed to refresh access token; caused by Error: Unknown error',
);
await expect(refreshTokenPromise).rejects.toThrow(
'Failed to refresh access token Error: Unknown error',
});
it('should forward string errors', async () => {
class MyCustomRefreshTokenSuccess extends passport.Strategy {
_oauth2 = new (class {
getOAuthAccessToken(_r: string, _o: any, cb: Function) {
cb('some silly string error');
}
})();
}
await expect(
executeRefreshTokenStrategy(
new MyCustomRefreshTokenSuccess(),
'REFRESH_TOKEN',
'a',
),
).rejects.toThrow(
"Failed to refresh access token; caused by unknown error 'some silly string error'",
);
});
it('should forward object errors', async () => {
class MyCustomRefreshTokenSuccess extends passport.Strategy {
_oauth2 = new (class {
getOAuthAccessToken(_r: string, _o: any, cb: Function) {
cb({ name: 'SomeError', message: 'some message' });
}
})();
}
await expect(
executeRefreshTokenStrategy(
new MyCustomRefreshTokenSuccess(),
'REFRESH_TOKEN',
'a',
),
).rejects.toThrow(
'Failed to refresh access token; caused by SomeError: some message',
);
});
@@ -21,6 +21,7 @@ import { InternalOAuthError } from 'passport-oauth2';
import { ProfileInfo } from '@backstage/plugin-auth-node';
import { PassportProfile } from './types';
import { OAuthStartResponse } from '../../providers/types';
import { ForwardedError } from '@backstage/errors';
export type PassportDoneCallback<Res, Private = never> = (
err?: Error,
@@ -66,7 +67,10 @@ export const makeProfileInfo = (
displayName = decoded.name;
}
} catch (e) {
throw new Error(`Failed to parse id token and get profile info, ${e}`);
throw new ForwardedError(
`Failed to parse id token and get profile info`,
e,
);
}
}
@@ -176,7 +180,7 @@ export const executeRefreshTokenStrategy = async (
params: any,
) => {
if (err) {
reject(new Error(`Failed to refresh access token ${err.toString()}`));
reject(new ForwardedError(`Failed to refresh access token`, err));
}
if (!accessToken) {
reject(