diff --git a/apps/api-test-app/src/main.js b/apps/api-test-app/src/main.js index 249fdb70..bbfb41c0 100644 --- a/apps/api-test-app/src/main.js +++ b/apps/api-test-app/src/main.js @@ -181,8 +181,8 @@ function ensureDirectoryExistence(filePath) { } function getSessionCookieFromCookieJar() { - const cookieUrl = isHjarntorget - ? 'https://admentum.goteborg.se' + const cookieUrl = isAdmentum + ? 'https://admentum.se' : 'https://etjanst.stockholm.se' const cookies = cookieJar.getCookiesSync(cookieUrl) const sessionCookieKey = isAdmentum ? 'JSESSIONID' : 'SMSESSION' @@ -193,6 +193,7 @@ const record = async (info, data) => { const name = info.error ? `${info.name}_error` : info.name const filename = `${recordFolder}/${name}.json` ensureDirectoryExistence(filename) + console.log('recording session', filename) const content = { url: info.url, headers: info.headers, diff --git a/libs/api-admentum/lib/apiAdmentum.test.ts b/libs/api-admentum/lib/apiAdmentum.test.ts deleted file mode 100644 index 2f6a16f0..00000000 --- a/libs/api-admentum/lib/apiAdmentum.test.ts +++ /dev/null @@ -1,288 +0,0 @@ -import { wrapToughCookie } from '@skolplattformen/api' -import { CookieJar } from 'tough-cookie' -import { ApiHjarntorget } from './apiAdmentum' - -const setupSuccessfullLoginInitiation = (fetcherMock: jest.Mock) => { - // 'begin-login' - fetcherMock.mockReturnValueOnce( - Promise.resolve({ - url: 'some url with url encoded at the end?return=hello', - }) - ) - - // 'init-shibboleth-login' - fetcherMock.mockReturnValueOnce( - Promise.resolve({ - url: 'some url with url encoded at the end?Target=hello', - }) - ) - - // 'init-bankId' - fetcherMock.mockReturnValueOnce( - Promise.resolve({ - text: jest.fn().mockReturnValue( - Promise.resolve(` - - - - - - `) - ), - }) - ) - - // 'pick-mvghost' - fetcherMock.mockReturnValueOnce( - Promise.resolve({ - url: 'some url to a mvghost', - }) - ) - - // 'start-bankId' - fetcherMock.mockReturnValueOnce( - Promise.resolve({ - url: 'some base url to a mvghost to use when polling status', - }) - ) -} - -const setupSuccessfullBankIdLogin = (fetcherMock: jest.Mock) => { - // 'poll-bankid-status' - fetcherMock.mockReturnValueOnce( - Promise.resolve({ - json: jest.fn().mockReturnValue( - Promise.resolve({ - infotext: '', - location: 'an url to go to confirm the login', - }) - ), - }) - ) - - // 'confirm-signature-redirect' - fetcherMock.mockReturnValueOnce( - Promise.resolve({ - text: jest.fn().mockReturnValue( - Promise.resolve(` - - - - - - `) - ), - }) - ) - - // 'authgbg-saml-login' - fetcherMock.mockReturnValueOnce( - Promise.resolve({ - text: jest.fn().mockReturnValue( - Promise.resolve(` - - - - - - `) - ), - }) - ) - - // 'admentum-saml-login' - fetcherMock.mockReturnValueOnce(Promise.resolve({ status: 200 })) -} - -describe('api', () => { - let fetcherMock: jest.Mock - let api: ApiHjarntorget - - beforeEach(() => { - const fetcher = jest.fn() - fetcherMock = fetcher as jest.Mock - - const cookieManager = wrapToughCookie(new CookieJar()) - cookieManager.clearAll() - api = new ApiHjarntorget(jest.fn(), cookieManager) - api.replaceFetcher(fetcher) - }) - it('works', () => { - expect(1 + 1).toBe(2) - }) - // describe('#login', () => { - // it('goes through single sing-on steps', async (done) => { - // setupSuccessfullLoginInitiation(fetcherMock) - // setupSuccessfullBankIdLogin(fetcherMock) - // const personalNumber = 'my personal number' - - // const loginComplete = new Promise((resolve, reject) => { - // api.on('login', () => done()) - // }); - // await api.login(personalNumber) - // }) - // it('checker emits PENDING', async (done) => { - // // 'poll-bankid-status' - // fetcherMock.mockReturnValueOnce(Promise.resolve({ - // json: jest.fn().mockReturnValue(Promise.resolve({ - // infotext: "some prompt to do signing in app", - // location: "" - // })) - // })) - - // const status = checkStatus(fetcherMock, "some url") - // status.on('PENDING', () => { - // status.cancel() - // done() - // }) - // }) - // it('checker emits ERROR', async (done) => { - // // 'poll-bankid-status' - // fetcherMock.mockReturnValueOnce(Promise.resolve({ - // json: jest.fn().mockReturnValue(Promise.resolve({ - // infotext: "some prompt to do signing in app", - // location: "url with error in the name" - // })) - // })) - - // const status = checkStatus(fetcherMock, "some url") - // status.on('ERROR', () => { - // status.cancel() - // done() - // }) - // }) - // it('checker emits ERROR when an exception occurs', async (done) => { - // // 'poll-bankid-status' - // fetcherMock.mockReturnValueOnce(Promise.resolve({ - // json: jest.fn().mockReturnValue(Promise.resolve({ - // infotext: undefined, - // location: undefined - // })) - // })) - - // const status = checkStatus(fetcherMock, "some url") - // status.on('ERROR', () => { - // status.cancel() - // done() - // }) - // }) - // it('remembers used personal number', async (done) => { - // setupSuccessfullLoginInitiation(fetcherMock) - // setupSuccessfullBankIdLogin(fetcherMock) - // const personalNumber = 'my personal number' - // await api.login(personalNumber) - // api.on('login', () => { - // expect(api.getPersonalNumber()).toEqual(personalNumber) - // done() - // }) - // }) - // it('forgets used personal number if sign in is unsuccessful', async (done) => { - // setupSuccessfullLoginInitiation(fetcherMock) - // // 'poll-bankid-status' - // fetcherMock.mockReturnValueOnce(Promise.resolve({ - // json: jest.fn().mockReturnValue(Promise.resolve({ - // infotext: "", - // location: "an url to go to confirm the login" - // })) - // })) - // // 'confirm-signature-redirect' - // fetcherMock.mockReturnValueOnce(Promise.resolve({ - // text: Promise.resolve("some error occured") - // })) - - // const personalNumber = 'my personal number' - // const status = await api.login(personalNumber) - - // status.on('ERROR', () => { - // expect(api.getPersonalNumber()).toEqual(undefined) - // done() - // }) - // }) - - // // TODO: Possibly rewrite the mocking so we mock the responses more properly, - // // that way it would be possible to implement a throwIfNotOk wrapper for the - // // fetch calls. - // // it('throws error on external api error', async () => { - // // const personalNumber = 'my personal number' - // // try { - // // await api.login(personalNumber) - // // } catch (error: any) { - // // expect(error.message).toEqual(expect.stringContaining('Server Error')) - // // } - // // }) - // }) - // describe('#logout', () => { - // // it('clears session', async () => { - // // await api.logout() - // // const session = await api.getSession('') - // // expect(session).toEqual({ - // // headers: { - // // cookie: '', - // // }, - // // }) - // // }) - // it('emits logout event', async () => { - // const listener = jest.fn() - // api.on('logout', listener) - // await api.logout() - // expect(listener).toHaveBeenCalled() - // }) - // it('sets .isLoggedIn', async () => { - // api.isLoggedIn = true - // await api.logout() - // expect(api.isLoggedIn).toBe(false) - // }) - // it('forgets personalNumber', async () => { - // // eslint-disable-next-line @typescript-eslint/no-explicit-any - // (api as any).personalNumber = 'my personal number' - // api.isLoggedIn = true - - // await api.logout() - - // expect(api.getPersonalNumber()).toEqual(undefined) - // }) - // }) - /* - describe('fake', () => { - it('sets fake mode for the correct pnr:s', async () => { - let status - - status = await api.login('121212121212') - expect(status.token).toEqual('fake') - - status = await api.login('201212121212') - expect(status.token).toEqual('fake') - - status = await api.login('1212121212') - expect(status.token).toEqual('fake') - }) - it('delivers fake data', async (done) => { - api.on('login', async () => { - const user = await api.getUser() - expect(user).toEqual({ - firstName: 'Namn', - lastName: 'Namnsson', - isAuthenticated: true, - personalNumber: "195001182046", - }) - - const children = await api.getChildren() - expect(children).toHaveLength(2) - - const calendar1 = await api.getCalendar(children[0]) - expect(calendar1).toHaveLength(20) - const calendar2 = await api.getCalendar(children[1]) - expect(calendar2).toHaveLength(18) - - const skola24Children = await api.getSkola24Children() - expect(skola24Children).toHaveLength(1) - - const timetable = await api.getTimetable(skola24Children[0], 2021, 15, 'sv') - expect(timetable).toHaveLength(32) - - done() - }) - await api.login('121212121212') - }) - })*/ -}) diff --git a/libs/api-admentum/lib/apiAdmentum.ts b/libs/api-admentum/lib/apiAdmentum.ts index daa753f2..b26f7a1b 100644 --- a/libs/api-admentum/lib/apiAdmentum.ts +++ b/libs/api-admentum/lib/apiAdmentum.ts @@ -292,16 +292,15 @@ export class ApiAdmentum extends EventEmitter implements Api { return (res as any).url } ) - await this.fetch('get-cookies', url) - // https://login.grandid.com/?sessionid=234324 // => 234324 const sessionId = url.split('=').pop() + console.log('sessionId', sessionId) if (!sessionId) throw new Error('No session provided') console.log('url', bankIdInitUrl(sessionId)) - this.fetch('bankid-init', bankIdInitUrl(sessionId), { + await this.fetch('bankid-init', bankIdInitUrl(sessionId), { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', diff --git a/libs/api-admentum/lib/loginStatus.ts b/libs/api-admentum/lib/loginStatus.ts index fa882cd2..440aa347 100644 --- a/libs/api-admentum/lib/loginStatus.ts +++ b/libs/api-admentum/lib/loginStatus.ts @@ -23,16 +23,16 @@ export class GrandidChecker extends EventEmitter implements LoginStatusChecker { async check(): Promise { try { console.log('polling bankid signature', this.basePollingUrl) - const result = await this.fetcher( - 'bankid-checker', - bankIdCheckUrl(this.basePollingUrl) - ).then((res) => { - console.log('checker response', res) - return res.text() + const result = await this.fetcher('bankid-checker', this.basePollingUrl, { + headers: { + 'x-requested-with': 'XMLHttpRequest', + }, + }).then((res) => { + return res.json() }) console.log('bankid result', result) - const ok = result.includes('OK') - const isError = result.includes('Unauthorized') + const ok = result.response?.status === 'complete' + const isError = result.response?.status === 'error' // https://mNN-mg-local.idp.funktionstjanster.se/mg-local/auth/ccp11/grp/pollstatus if (ok) { this.emit('OK')