feat: 🎸 Remove all obsolete login obstacles (#146)

This commit is contained in:
Andreas Eriksson 2021-09-12 14:52:33 +02:00 committed by GitHub
parent 7f93285554
commit befb073a32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 8 additions and 149 deletions

View File

@ -49,7 +49,7 @@ async function run() {
console.log('user')
const user = await api.getUser()
console.log(user)
/*
console.log('children')
const children = await api.getChildren()
console.log(children)
@ -115,7 +115,7 @@ async function Login(api) {
console.log('Login with old cookie succeeded')
} catch (error) {
console.log('Could not login with old session cookie. Reverting to BankId')
console.error(error)
// console.error(error)
}
if (useBankId) {

View File

@ -3,7 +3,6 @@ import { EventEmitter } from 'events'
import { decode } from 'he'
import * as html from 'node-html-parser'
import { Language } from '@skolplattformen/curriculum/dist/translations'
import * as base64 from 'base-64'
import { URLSearchParams } from './URLSearchParams'
import { checkStatus, LoginStatusChecker } from './loginStatus'
import {
@ -60,8 +59,6 @@ export class Api extends EventEmitter {
public isFake: boolean = false
public childControllerUrl?: string
private authorizedSystems: SSOSystems = {}
constructor(
@ -136,7 +133,6 @@ export class Api extends EventEmitter {
status.on('OK', async () => {
await this.retrieveSessionCookie()
await this.retrieveXsrfToken()
// await this.retrieveApiKey()
this.isLoggedIn = true
this.emit('login')
@ -166,7 +162,6 @@ export class Api extends EventEmitter {
}
await this.retrieveXsrfToken()
await this.retrieveApiKey()
this.isLoggedIn = true
this.emit('login')
@ -187,110 +182,10 @@ export class Api extends EventEmitter {
doc
.querySelector('input[name="__RequestVerificationToken"]')
?.getAttribute('value') || ''
const scriptTags = doc.querySelectorAll('script')
const childControllerScriptTag = scriptTags.find((elem) => {
const srcAttr = elem.getAttribute('src')
return srcAttr?.startsWith('/vardnadshavare/bundles/childcontroller')
})
this.childControllerUrl =
routes.baseEtjanst + childControllerScriptTag?.getAttribute('src')
this.addHeader('x-xsrf-token', xsrfToken)
}
private async retrieveApiKey(): Promise<void> {
const url = routes.childcontrollerScript
const session = this.getRequestInit()
const response = await this.fetch('startBundle', url, session)
const text = await response.text()
const apiKeyRegex = /"API-Key": "([\w\d]+)"/gm
const apiKeyMatches = apiKeyRegex.exec(text)
const apiKey =
apiKeyMatches && apiKeyMatches.length > 1 ? apiKeyMatches[1] : ''
this.addHeader('API-Key', apiKey)
}
private async retrieveCdnUrl(): Promise<string> {
const url = routes.cdn
const session = this.getRequestInit()
const response = await this.fetch('cdn', url, session)
const cdnUrl = await response.text()
return cdnUrl
}
private async retrieveAuthBody(): Promise<string> {
const url = routes.auth
const session = this.getRequestInit()
const response = await this.fetch('auth', url, session)
const authBody = await response.text()
return authBody
}
private async getTopologyConfig(): Promise<Record<string, any>> {
const response = await this.fetch('topologyConfigUrl', routes.topologyConfigUrl)
const json = await response.json()
return json
}
private async retrieveCreateItemHeaders() {
const response = await this.fetch(
'createItemConfig',
routes.createItemConfig
)
const json = await response.json()
return json
}
private async retrieveAuthToken(
url: string,
authBody: string
): Promise<string> {
const session = this.getRequestInit({
method: 'POST',
headers: {
Accept: 'text/plain',
Origin: 'https://etjanst.stockholm.se',
Referer: 'https://etjanst.stockholm.se/',
Connection: 'keep-alive',
},
body: authBody,
})
delete session.headers['API-Key']
// Temporarily remove cookies
const cookies = await this.cookieManager.getCookies(url)
this.cookieManager.clearAll()
// Perform request
let scriptUrl = this.childControllerUrl
if (!scriptUrl) {
scriptUrl = routes.childcontrollerScript
}
const createItemHeaders = await this.retrieveCreateItemHeaders()
const response = await this.fetch('createItem', url, {
method: 'POST',
...createItemHeaders,
body: authBody,
})
// Restore cookies
cookies.forEach((cookie) => {
this.cookieManager.setCookie(cookie, url)
})
if (!response.ok) {
throw new Error(
`Server Error [${response.status}] [${response.statusText}] [${url}]`
)
}
const authData = await response.json()
return authData.token
}
private async fakeMode(): Promise<LoginStatusChecker> {
this.isFake = true
@ -314,43 +209,13 @@ export class Api extends EventEmitter {
return parse.user(data)
}
private async getTopology (): Promise<string> {
const configTopology = await this.getTopologyConfig()
const currentTime = new Date().getTime() + 600000
let topo = `${configTopology.topologyLongKey}${currentTime}`
const secretNumberString = configTopology.topologyShortKey
const numberOfBase64Iterations = configTopology.topologyBase64Iterations
for (let i = 0; i < numberOfBase64Iterations; i += 1) {
topo = base64.encode(topo)
};
const part1 = topo.substring(0, 1)
const part2 = secretNumberString.charAt(numberOfBase64Iterations)
const part3 = topo.substring(1, topo.length)
const finalTopology = part1 + part2 + part3
return finalTopology
}
public async getChildren(): Promise<EtjanstChild[]> {
if (this.isFake) return fakeResponse(fake.children())
// const cdnUrl = await this.retrieveCdnUrl()
// const authBody = await this.retrieveAuthBody()
// const token = await this.retrieveAuthToken(cdnUrl, authBody)
const url = routes.children
const session = this.getRequestInit({
headers: {
Accept: 'application/json;odata=verbose',
// Auth: token,
topology: await this.getTopology(),
Host: 'etjanst.stockholm.se',
Referer: 'https://etjanst.stockholm.se/vardnadshavare/inloggad2/hem',
},

View File

@ -24,7 +24,7 @@
},
"devDependencies": {
"@react-native-cookies/cookies": "^6.0.7",
"@skolplattformen/curriculum": "^1.3.0",
"@skolplattformen/curriculum": "^1.4.1",
"@types/base-64": "^1.0.0",
"@types/he": "^1.1.1",
"@types/jest": "^26.0.22",
@ -49,7 +49,6 @@
"typescript": "^4.2.4"
},
"dependencies": {
"base-64": "^1.0.0",
"camelcase-keys": "^6.2.2",
"change-case": "^4.1.2",
"events": "^3.3.0",

View File

@ -522,10 +522,10 @@
dependencies:
"@sinonjs/commons" "^1.7.0"
"@skolplattformen/curriculum@^1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@skolplattformen/curriculum/-/curriculum-1.3.0.tgz#841e2ff0095e39e174cffdd0b8a81a17956de7ed"
integrity sha512-nuwZX45gHe5JaiYfygDP1HmbhAJOEXuuWwR04tNAnl/PaDGqJscfzKt8YD2SL+MHqi3LARjSKLa4ms4SxVQFyw==
"@skolplattformen/curriculum@^1.4.1":
version "1.4.1"
resolved "https://registry.yarnpkg.com/@skolplattformen/curriculum/-/curriculum-1.4.1.tgz#f60b82276d61f731bf6c169826a4fb2a82e0a574"
integrity sha512-tKJjB2KsOXhNGvtBTp3DsTVchdQbSU08AwAfK1KbmIGFUQLAz8Su3T6RqYsxXEpCcFKRV6poscBnUZrdgZQy3w==
"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7":
version "7.1.12"
@ -991,11 +991,6 @@ balanced-match@^1.0.0:
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
base-64@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/base-64/-/base-64-1.0.0.tgz#09d0f2084e32a3fd08c2475b973788eee6ae8f4a"
integrity sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==
base@^0.11.1:
version "0.11.2"
resolved "https://registry.npmjs.org/base/-/base-0.11.2.tgz"