Skip to content

Commit

Permalink
Add OIDC error handling and implement token method in SDK
Browse files Browse the repository at this point in the history
  • Loading branch information
orius123 committed Nov 14, 2024
1 parent d37ab69 commit 74f6ab3
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 4 deletions.
14 changes: 11 additions & 3 deletions packages/sdks/web-js-sdk/src/sdk/oidc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
SigninResponse,
WebStorageStateStore,
} from 'oidc-client-ts';
import { AfterRequestHook, CoreSdk } from '../types';
import { CoreSdk } from '../types';

interface OidcConfig {
clientId: string;
Expand All @@ -18,6 +18,14 @@ const getOidcClient = (
projectID: string,
oidcConfig?: OidcConfig,
) => {
// oidc-client-ts is a peer dependency of @descope/web-js-sdk
// so if it's not installed, we should throw an error
if (!OidcClient) {
throw new Error(
'oidc-client-ts is not installed. Please install it by running `npm install oidc-client-ts`',
);
}

const statePrefix = window.location.pathname.replace(/\//g, '_');
const stateUserKey = `${statePrefix}_user`;

Expand Down Expand Up @@ -56,7 +64,7 @@ const createOidc = (sdk: CoreSdk, projectID: string) => {
return { ok: true, data: { url } };
};

const finish = async (
const token = async (
oidcConfig?: OidcConfig,
): Promise<SdkResponse<JWTResponse>> => {
const { client, stateUserKey } = getOidcClient(sdk, projectID, oidcConfig);
Expand Down Expand Up @@ -85,7 +93,7 @@ const createOidc = (sdk: CoreSdk, projectID: string) => {

return {
authorize,
finish,
token,
logout,
};
};
Expand Down
1 change: 0 additions & 1 deletion packages/sdks/web-js-sdk/test/fedcm.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import createSdk from '../src/index';
import webauthn from '../src/sdk/webauthn';

const coreJs = {
oauth: {
Expand Down
106 changes: 106 additions & 0 deletions packages/sdks/web-js-sdk/test/oidc.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { OidcClient } from 'oidc-client-ts';
import createOidc from '../src/sdk/oidc';
import { CoreSdk } from '../src/types';

jest.mock('oidc-client-ts', () => {
return {
OidcClient: jest.fn().mockImplementation(() => ({
createSigninRequest: jest.fn(),
processSigninResponse: jest.fn(),
createSignoutRequest: jest.fn(),
})),
WebStorageStateStore: jest.fn(),
};
});

describe('OIDC', () => {
let sdk: CoreSdk;

beforeAll(() => {
sdk = {
httpClient: {
buildUrl: jest.fn().mockReturnValue('http://example.com'),
},
refresh: jest.fn(),
} as unknown as CoreSdk;
});

beforeEach(() => {
jest.clearAllMocks();
const unload = () =>
setTimeout(() => window.dispatchEvent(new Event('unload')), 200);

const location = Object.defineProperties(
{},
{
...Object.getOwnPropertyDescriptors(window.location),
assign: {
enumerable: true,
value: jest.fn(unload),
},
replace: {
enumerable: true,
value: jest.fn(unload),
},
},
);
Object.defineProperty(window, 'location', {
enumerable: true,
get: () => location,
});
});

describe('authorize', () => {
it('should call createSigninRequest with correct params', async () => {
const mockCreateSigninRequest = jest
.fn()
.mockResolvedValue({ url: 'mockUrl' });
(OidcClient as jest.Mock).mockImplementation(() => ({
createSigninRequest: mockCreateSigninRequest,
}));

const oidc = createOidc(sdk, 'projectID');
const response = await oidc.authorize();

expect(mockCreateSigninRequest).toHaveBeenCalledWith({});
expect(response).toEqual({ ok: true, data: { url: 'mockUrl' } });
});
});

describe('token', () => {
it('should call processSigninResponse and sdk.refresh with correct params', async () => {
const mockProcessSigninResponse = jest
.fn()
.mockResolvedValue({ refresh_token: 'mockRefreshToken' });
(OidcClient as jest.Mock).mockImplementation(() => ({
processSigninResponse: mockProcessSigninResponse,
}));

const oidc = createOidc(sdk, 'projectID');
const response = await oidc.token();

expect(mockProcessSigninResponse).toHaveBeenCalledWith(
window.location.href,
);
expect(sdk.refresh).toHaveBeenCalledWith('mockRefreshToken');
});
});

describe('logout', () => {
it('should call createSignoutRequest with correct params', async () => {
const mockCreateSignoutRequest = jest
.fn()
.mockResolvedValue({ url: 'mockLogoutUrl' });
(OidcClient as jest.Mock).mockImplementation(() => ({
createSignoutRequest: mockCreateSignoutRequest,
}));

const oidc = createOidc(sdk, 'projectID');

await oidc.logout();

expect(mockCreateSignoutRequest).toHaveBeenCalled();
expect(window.location.replace).toHaveBeenCalledWith('mockLogoutUrl');
});
});
});

0 comments on commit 74f6ab3

Please sign in to comment.