ReLoia / ArgoScuolaNext-NodeJS

A NodeJS library that allows you to interact with ArgoScuolaNext API.
MIT License
4 stars 0 forks source link

404 not found #1

Closed AntogamerYT closed 1 year ago

AntogamerYT commented 2 years ago

Ciao, so che questa lib non è aggiornata da molto ma quando provo a fare l'accesso la lib da un 404, penso che il link della api sia stato cambiato

PS C:\Users\Antogamer\Desktop\Bot> npx tsc | node ./dist
HTTPError: Response code 404 (Not Found)
    at Request.<anonymous> (C:\Users\Antogamer\Desktop\Bot\node_modules\got\dist\source\as-promise\index.js:118:42)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  code: 'ERR_NON_2XX_3XX_RESPONSE',
  timings: {
    start: 1663696286014,
    socket: 1663696286016,
    lookup: 1663696286030,
    connect: 1663696286053,
    secureConnect: 1663696286079,
    upload: 1663696286079,
    response: 1663696286108,
    end: 1663696286110,
    error: undefined,
    abort: undefined,
    phases: {
      wait: 2,
      dns: 14,
      tcp: 23,
      tls: 26,
      request: 0,
      firstByte: 29,
      download: 2,
      total: 96
    }
  }
}
AntogamerYT commented 2 years ago

Tutte le cose che terminano con REDACTED sono censurate da me

Conducendo delle mie ricerche, ho notato che la nuova app di argo fa 4 richieste principali:

image

/.well-known/openid-configuration penso che sia qualcosa per l'oauth questi sono gli headers che manda e questa è la risposta che l'app riceve:

{
  "issuer": "https://auth.portaleargo.it/",
  "authorization_endpoint": "https://auth.portaleargo.it/oauth2/auth",
  "token_endpoint": "https://auth.portaleargo.it/oauth2/token",
  "jwks_uri": "https://auth.portaleargo.it/.well-known/jwks.json",
  "subject_types_supported": [
    "public"
  ],
  "response_types_supported": [
    "code",
    "code id_token",
    "id_token",
    "token id_token",
    "token",
    "token id_token code"
  ],
  "claims_supported": [
    "sub"
  ],
  "grant_types_supported": [
    "authorization_code",
    "implicit",
    "client_credentials",
    "refresh_token"
  ],
  "response_modes_supported": [
    "query",
    "fragment"
  ],
  "userinfo_endpoint": "https://auth.portaleargo.it/userinfo",
  "scopes_supported": [
    "offline_access",
    "offline",
    "openid"
  ],
  "token_endpoint_auth_methods_supported": [
    "client_secret_post",
    "client_secret_basic",
    "private_key_jwt",
    "none"
  ],
  "userinfo_signing_alg_values_supported": [
    "none",
    "RS256"
  ],
  "id_token_signing_alg_values_supported": [
    "RS256"
  ],
  "request_parameter_supported": true,
  "request_uri_parameter_supported": true,
  "require_request_uri_registration": true,
  "claims_parameter_supported": false,
  "revocation_endpoint": "https://auth.portaleargo.it/oauth2/revoke",
  "backchannel_logout_supported": true,
  "backchannel_logout_session_supported": true,
  "frontchannel_logout_supported": true,
  "frontchannel_logout_session_supported": true,
  "end_session_endpoint": "https://auth.portaleargo.it/oauth2/sessions/logout",
  "request_object_signing_alg_values_supported": [
    "RS256",
    "none"
  ]
}

visto che sono troppo pigro, non farò una spiegazione completa degli altri endpoint visto che puoi anche arrivarci da solo:

https://auth.portaleargo.it/oauth2/token Headers richiesta image Request body image Risposta image Response body

{
  "access_token": "REDACTED",
  "expires_in": 3599,
  "id_token": "IDTOKEN_REDACTED",
  "refresh_token": "REFRESHTOKEN_REDACTED",
  "scope": "openid offline profile user.roles argo",
  "token_type": "bearer"
}

https://www.portaleargo.it/appfamiglia/api/rest/dashboard/what - returna i dati dell'utente

Headers richiesta image Request Body

{
  "dataultimoaggiornamento": "2022-09-20 20:50:41.758101",
  "opzioni": "{\"ORARIO_SCOLASTICO\":true,\"PAGELLINO_ONLINE\":true,\"VALUTAZIONI_PERIODICHE\":true,\"VALUTAZIONI_GIORNALIERE\":true,\"COMPITI_ASSEGNATI\":true,\"IGNORA_OPZIONE_VOTI_DOCENTI\":false,\"DOCENTI_CLASSE\":true,\"RENDI_VISIBILE_CURRICULUM\":true,\"RICHIESTA_CERTIFICATI\":false,\"MODIFICA_RECAPITI\":true,\"CONSIGLIO_DI_ISTITUTO\":true,\"NOTE_DISCIPLINARI\":true,\"GIUDIZI\":false,\"GIUSTIFICAZIONI_ASSENZE\":true,\"TABELLONE_PERIODI_INTERMEDI\":false,\"PAGELLE_ONLINE\":true,\"ASSENZE_PER_DATA\":true,\"ARGOMENTI_LEZIONE\":false,\"NASCONDI_DIDUP_FAMIGLIA\":true,\"ALILITA_BSMART_FAMIGLIA\":false,\"VOTI_GIUDIZI\":true,\"ABILITA_AUTOCERTIFICAZIONE_FAM\":false,\"TABELLONE_SCRUTINIO_FINALE\":false,\"PIN_VOTI\":false,\"DISABILITA_ACCESSO_FAMIGLIA\":true,\"TASSE_SCOLASTICHE\":true,\"PROMEMORIA_CLASSE\":true,\"PRENOTAZIONE_ALUNNI\":true,\"CONSIGLIO_DI_CLASSE\":true}",
  "lista-x-auth-token": "[\"REDACTED\"]",
  "lista-x-auth-token-account": "[\"REDACTED\",\"REDACTED\",\"REDACTED\"]"
}

Risposta image Response body Questo non lo caricherò perchè dovrei censurare praticamente tutto, quindi per scoprire che cosa returna ti consiglio di usare http toolkit con un telefono rootato oppure anche bluestacks/Windows Subsystem for Android dovrebbe andare utilizzando Telerik Fiddler Classic

https://www.portaleargo.it/appfamiglia/api/rest/dashboard/aggiornadata Headers richiesta image Request body:

{
  "dataultimoaggiornamento": "2022-09-20 23:21:05.621460"
}

Risposta image Body risposta image

Spero che questi dati ti siano utili per fixare la lib, fammi sapere se ci riuscirai

AntogamerYT commented 2 years ago

ah e magari prova a decompilare l'apk di argo famiglia, che forse potresti trovare anche altre richieste

paoloantinori commented 2 years ago

@AntogamerYT non manca la prima parte della conversazione? quella che porta all'ottenimento del refresh_token?

AntogamerYT commented 2 years ago

@paoloantinori yep, alla fine ho capito tutti gli endpoint e appena posso faccio una repo dove documento il tutto, però puoi incominciare ad ottentere un refresh token utilizzando http toolkit debuggando le richieste che l'app fa nell'endpoint oauth2/token , così ti prendi il refresh_token e ci fai quello che vuoi

paoloantinori commented 2 years ago

Ciao, grazie. Era giusto il mio piano per le prossime mosse. Speravo di evitarlo e di trovare un'implementazione dell auth già fatta in quanto ora come ora non ho un Android rootato comodo e Genymotion non riesce a lanciare Didup.

Se qualcuno fosse più avanti di me e cercasse un betatester, contate su di me 👍

AntogamerYT commented 2 years ago

per l'auth senza trovare il refresh token manualmente ci devo ancora lavorare, perchè quando si fa il login argo crea una login challenge da cui manda la richiesta con codice scuola, user e pass, il problema è che non capisco come generare la login challenge, per questo si usa il refresh token, che poi genera un access token che viene salvato in un object (questo è il metodo che ho utilizzato per ora, magari c'è un metodo migliore per farlo) sul disco

paoloantinori commented 2 years ago

per ora ho giocato solo a replicare in curl l'auth del sito. E, se stiamo parlando della stessa cosa, la challange li', la estraggo da una prima chiamata a https://www.portaleargo.it/argoweb/famiglia/index1.jsp. Se non ricordo male e' un parametro hidden del form.

Ma scusami, quindi tu mi dici che il refreshe token e' statico? Non viene restituito da una prima (o seconda) chiamata dei flussi standard di Oauth?

AntogamerYT commented 2 years ago

@paoloantinori il refresh token viene dato dall'enpoint oauth2/token e, come ogni sistema basato su oauth2, il refresh token non scade mai e serve per generare altri access token/nuovo refresh token

comunque, per ora questa è la mia implementazione del login:

const axios = (await import('axios')).default
import fs from 'fs'
export async function login() {
    const now = handleDate(Date.now())
    const creds = JSON.parse(fs.readFileSync(process.cwd()+'/creds.json', 'utf-8'))
    var dataoa = qs.stringify({
        'refresh_token': global.refresh || creds.refresh_token,
        'grant_type': 'refresh_token',
        'scope': 'openid offline profile user.roles argo',
        'redirect_uri': 'it.argosoft.didup.famiglia.new://login-callback',
        'client_id': '72fd6dea-d0ab-4bb9-8eaa-3ac24c84886c' 
    });
    var configoa = {
        method: 'post',
        url: 'https://auth.portaleargo.it/oauth2/token',
        headers: { 
            'accept': 'application/json', 
            'accept-encoding': 'gzip', 
            'content-type': 'application/x-www-form-urlencoded', 
            'user-agent': 'Dalvik/2.1.0 (Linux; U; Android 12; SM-N960F Build/SQ3A.220705.004)'
        },
        data : dataoa
    }
    try {
        const resoa = await axios(configoa)
        global.bearer = resoa.data.access_token
        global.refresh = resoa.data.refresh_token
        await fs.writeFileSync(process.cwd() + '/creds.json', JSON.stringify({
            access_token: global.bearer,
            refresh_token: global.refresh,
            token: ""
        }))
    } catch (error) {
        console.log(error)
    }

    var data = '{\r\n  "clientID": "dfnW3d4STtm1_HWiXFw36t:APA91bEiQDMnZS8GAHYYMvv1gZce14bFkCa7D2ve0TEYDZIL-zCE7ZzcuV3O7V87-V50ZN3pGYkOeqZivMOtH0aU0nTyfJmV7pK6VE31mj3qb156Px1ETpgA0fGg2hqHASiVVmYPX_L9",\r\n  "lista-x-auth-token": "[\\"bc26e5cb-2c4c-4ce3-ade2-9a5877fe7d76\\",\\"5b51c43c-7f15-4a60-83b3-941f4e183ae2\\",\\"2e192091-97f6-4329-9e8a-b036b1e538ff\\"]",\r\n  "x-auth-token-corrente": "bc26e5cb-2c4c-4ce3-ade2-9a5877fe7d76",\r\n  "lista-opzioni-notifiche": "{\\"bc26e5cb-2c4c-4ce3-ade2-9a5877fe7d76\\":\\"#BAC#CON#COM#VOT#NOT#APP#ASS#BAL#RIC#PRE#SCR#OPZ#GIU\\",\\"5b51c43c-7f15-4a60-83b3-941f4e183ae2\\":\\"#BAC#CON#COM#VOT#NOT#APP#ASS#BAL#RIC#PRE#SCR#OPZ#GIU\\",\\"2e192091-97f6-4329-9e8a-b036b1e538ff\\":\\"#BAC#CON#COM#VOT#NOT#APP#ASS#BAL#RIC#PRE#SCR#OPZ#GIU\\"}"\r\n}';

    var config = {
        method: 'post',
        url: 'https://www.portaleargo.it/appfamiglia/api/rest/login', // serve per ottenere il token dell'account
        headers: { 
            'accept': 'application/json', 
            'accept-encoding': 'gzip', 
            'argo-client-version': '1.9.1', 
            'Authorization': 'Bearer ' + global.bearer, 
            'content-type': 'application/json; charset=utf-8', 
            'os-type': 'android SQ3A.220705.004', 
            'user-agent': 'Dart/2.14 (dart:io)', 
            'x-cod-min': 'null'
        },
        data : data
    }
    try {
        const loginrest = await axios(config)
        global.token = loginrest.data.data[0].token
        await fs.writeFileSync(process.cwd() + '/creds.json', JSON.stringify({
            access_token: global.bearer,
            refresh_token: global.refresh,
            token: global.token
        }))    
    } catch (error) {
        console.log(error)
    }
    let update_data = `{\r\n    "dataultimoaggiornamento": "${now.postDate} ${now.time}.002524"\r\n}`;

    let update_config = {
        method: 'post',
        url: 'https://www.portaleargo.it/appfamiglia/api/rest/dashboard/aggiornadata',
        headers: { 
            'accept': 'application/json', 
            'accept-encoding': 'gzip', 
            'Authorization': 'Bearer ' + global.bearer, 
            'content-type': 'application/json; charset=utf-8', 
            'os-type': 'android SQ3A.220705.004', 
            'user-agent': 'Dart/2.14 (dart:io)', 
            'x-auth-token': global.token, 
            'x-cod-min': process.env.CODICESCUOLA!
        },
        data : update_data
    };

    await axios(update_config)
}

const handleDate = (dataD: any) => {
    let data= new Date(dataD)
    const locale = data.toLocaleString('en-ZA', { timeZone: 'Europe/Rome' })
    let month = data.getMonth() + 1
    let day = data.getDate()
    let year = data.getFullYear()
    if(day<=9)
    day = '0' + day
    if(month<10)
    month = '0' + month
    const postDate = year + '-' + month + '-' + day
    const time = locale.split(',')[1].split(' ')[1]
    return {postDate, time}
}
paoloantinori commented 2 years ago

grazie! mi sa che seguiro' il tuo consiglio e mi tirero' fuori un primo token valido che mi sembra il modo piu' pratico!

ReLoia commented 2 years ago

Ciao, ho appena scoperto questo issue ahah. Ho creato questa librearia per mettermi alla prova nella creazione di un package npm e dopo averla finita non l'ho più modificata. Comunque l'errore è causato da un aggiornamento dell'api da parte dei programmatori di Argo come detto da te. Io al momento non posso sistemarlo perché sono in Erasmus. Se vuoi potresti creare una pull request con le modifiche (ma non credo ne valga la pena perché da quello che ho notato dalle informazioni che mi hai dato, hanno cambiato quasi tutto e c'è da fare una ricerca per i nuovi endpoint) oppure potresti creare una nuova repo (e credo che tu lo stia già facendo). Se creerai una nuova repo archivierò questa e lascerò un link alla tua come "redirect".

Comunque, l'issue è scritto in modo fantastico e le informazioni che hai allegato sono molto utili a capire come sistemare, complimenti : )

AntogamerYT commented 2 years ago

@ReLoia grazie, per ora ho solo creato la repo ma molto presto incomincerò a riempirla con tutto il codice

ReLoia commented 1 year ago

Questo problema è aperto da circa 6 mesi. Ieri ho creato una soluzione temporanea utilizzando Puppeteer, in attesa che @AntogamerYT aggiorni la sua repository con la sua soluzione al problema.

Purtroppo, non ho un telefono con root e non ho la possibilità di cercare una soluzione utilizzando l'applicazione per ottenere le richieste necessarie. Obiettivamente, preferirei qualsiasi altra soluzione, poiché quella attuale è lenta e non molto stabile.

Comunque, con questa soluzione, posso chiudere l'issue. Tuttavia, ribadisco che se @AntogamerYT aggiornerà la sua repository, archivierò questa repository e l'aggiornerò con un link alla soluzione di @AntogamerYT.

AntogamerYT commented 1 year ago

Questo problema è aperto da circa 6 mesi. Ieri ho creato una soluzione temporanea utilizzando Puppeteer, in attesa che @AntogamerYT aggiorni la sua repository con la sua soluzione al problema.

Purtroppo, non ho un telefono con root e non ho la possibilità di cercare una soluzione utilizzando l'applicazione per ottenere le richieste necessarie. Obiettivamente, preferirei qualsiasi altra soluzione, poiché quella attuale è lenta e non molto stabile.

Comunque, con questa soluzione, posso chiudere l'issue. Tuttavia, ribadisco che se @AntogamerYT aggiornerà la sua repository, archivierò questa repository e l'aggiornerò con un link alla soluzione di @AntogamerYT.

Ciao, non ho mai avuto tempo di toccare le api di argo visto che sono abbastanza complicate, comunque l'alternativa con puppeteer sembra buona, ma sto cercando un modo per evitare di usarlo. la cosa che mi ha bloccato è la generazione del client id, penso sia uno uuid, proverò a generarne uno e vedere come reagisce se provo a fare una richiesta utilizzandolo detto questo, spero di aggiornarla al più presto possibile la repo

AntogamerYT commented 1 year ago

ho appena controllato https://www.portaleargo.it/argoweb/famiglia/index1.jsp e sembra avere sia la challenge che il client id image

Chicchi7393 commented 1 year ago

Buonasera, sono un amico di @AntogamerYT

Nel mentre sviluppavo un mio progetto personale (Registro elettronico material 3 per Android) ho scelto di iniziare a capire come funzionasse il login di argo.

Stamattina abbiamo chiamato direttamente argo ma a detta loro "non possono comunicarci questi dati via telefono perchè sono privati"

Questo pomeriggio mi sono messo a lavoro utilizzando dei packet capture di Anto e sono riuscito a far funzionare l'autenticazione.

Appena anto è disponibile ci muoviamo per aggiornare questa repo o altro. Non ho argo quindi non so neanche i suoi piani per come continuare.

paoloantinori commented 1 year ago

Molto interessante, grazie! Io ho notato che and m utilizzando il refresh token ottenuto dall app , manage l'app out of sync, con il risultato di per usare o solo l'app o solo il codice esterno. Purtroppo questa limitazione era un po' troppo scomoda, motivo per cui ho messo in pausa le mie prove.

Ma una soluzione completa che possa replicare l'autenticazione completamente migliorerebbe molto le cose e sarebbe quindi ancora molto interessante, per cui se avete qualcosa da condividere mi tornerebbe molto utile!