diff --git a/src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md b/src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md index e615c695c..4cfa65b73 100644 --- a/src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md +++ b/src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md @@ -1,100 +1,100 @@ -# Az - Tokens & Public Applications +# Az - Token & Applicazioni Pubbliche {{#include ../../../banners/hacktricks-training.md}} -## Basic Information +## Informazioni di base -Entra ID è la piattaforma di gestione dell'identità e degli accessi (IAM) basata sul cloud di Microsoft, che funge da sistema fondamentale di autenticazione e autorizzazione per servizi come Microsoft 365 e Azure Resource Manager. Azure AD implementa il framework di autorizzazione OAuth 2.0 e il protocollo di autenticazione OpenID Connect (OIDC) per gestire l'accesso alle risorse. +Entra ID è la piattaforma di identity and access management (IAM) cloud di Microsoft, che funge da sistema fondamentale di autenticazione e autorizzazione per servizi come Microsoft 365 e Azure Resource Manager. Azure AD implementa il framework di autorizzazione OAuth 2.0 e il protocollo di autenticazione OpenID Connect (OIDC) per gestire l'accesso alle risorse. ### OAuth -**Partecipanti Chiave in OAuth 2.0:** +**Partecipanti chiave in OAuth 2.0:** -1. **Server delle Risorse (RS):** Protegge le risorse possedute dal proprietario delle risorse. -2. **Proprietario delle Risorse (RO):** Tipicamente un utente finale che possiede le risorse protette. -3. **Applicazione Client (CA):** Un'applicazione che cerca di accedere alle risorse per conto del proprietario delle risorse. -4. **Server di Autorizzazione (AS):** Emissione di token di accesso alle applicazioni client dopo averle autenticate e autorizzate. +1. **Resource Server (RS):** Protegge le risorse possedute dal resource owner. +2. **Resource Owner (RO):** Tipicamente un utente finale che possiede le risorse protette. +3. **Client Application (CA):** Un'applicazione che richiede accesso alle risorse per conto del resource owner. +4. **Authorization Server (AS):** Emette access token alle client application dopo averle autenticate e autorizzate. -**Scopes e Consenso:** +**Scopes e consenso:** -- **Scopes:** Permessi granulari definiti sul server delle risorse che specificano i livelli di accesso. -- **Consenso:** Il processo mediante il quale un proprietario delle risorse concede a un'applicazione client il permesso di accedere alle risorse con specifici scopes. +- **Scopes:** Permessi granulari definiti sul resource server che specificano i livelli di accesso. +- **Consent:** Il processo tramite il quale un resource owner concede a una client application il permesso di accedere a risorse con specifici scopes. **Integrazione con Microsoft 365:** -- Microsoft 365 utilizza Azure AD per IAM ed è composto da più applicazioni OAuth "di prima parte". +- Microsoft 365 utilizza Azure AD per IAM ed è composto da molteplici applicazioni OAuth "first-party". - Queste applicazioni sono profondamente integrate e spesso hanno relazioni di servizio interdipendenti. -- Per semplificare l'esperienza dell'utente e mantenere la funzionalità, Microsoft concede "consenso implicito" o "pre-consenso" a queste applicazioni di prima parte. -- **Consenso Implicito:** Alcune applicazioni sono automaticamente **concesse accesso a specifici scopes senza approvazione esplicita dell'utente o dell'amministratore**. -- Questi scopes pre-consentiti sono tipicamente nascosti sia agli utenti che agli amministratori, rendendoli meno visibili nelle interfacce di gestione standard. +- Per semplificare l'esperienza utente e mantenere la funzionalità, Microsoft concede "implied consent" o "pre-consent" a queste applicazioni first-party. +- **Consenso implicito:** Alcune applicazioni sono automaticamente **concesse l'accesso a specifici scopes senza approvazione esplicita dell'utente o dell'amministratore**. +- Questi scopes pre-consentiti sono tipicamente nascosti sia agli utenti sia agli amministratori, rendendoli meno visibili nelle interfacce di gestione standard. -**Tipi di Applicazioni Client:** +**Tipi di Client Application:** -1. **Client Riservati:** -- Possiedono le proprie credenziali (ad es., password o certificati). -- Possono **autenticarsi in modo sicuro** al server di autorizzazione. -2. **Client Pubblici:** +1. **Confidential Clients:** +- Possiedono credenziali proprie (es. password o certificati). +- Possono **autenticarsi in modo sicuro** verso l'authorization server. +2. **Public Clients:** - Non hanno credenziali uniche. -- Non possono autenticarsi in modo sicuro al server di autorizzazione. -- **Implicazione di Sicurezza:** Un attaccante può impersonare un'applicazione client pubblica quando richiede token, poiché non esiste un meccanismo per il server di autorizzazione per verificare la legittimità dell'applicazione. +- Non possono autenticarsi in modo sicuro verso l'authorization server. +- **Implicazione di sicurezza:** Un attaccante può impersonare una public client application durante la richiesta di token, dato che non esiste un meccanismo per l'authorization server per verificare la legittimità dell'applicazione. -## Authentication Tokens +## Token di autenticazione -Ci sono **tre tipi di token** utilizzati in OIDC: +Esistono **tre tipi di token** usati in OIDC: -- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** Il client presenta questo token al server delle risorse per **accedere alle risorse**. Può essere utilizzato solo per una specifica combinazione di utente, client e risorsa e **non può essere revocato** fino alla scadenza - che è di 1 ora per impostazione predefinita. -- **ID Tokens**: Il client riceve questo **token dal server di autorizzazione**. Contiene informazioni di base sull'utente. È **legato a una specifica combinazione di utente e client**. -- **Refresh Tokens**: Forniti al client con il token di accesso. Utilizzati per **ottenere nuovi token di accesso e ID**. È legato a una specifica combinazione di utente e client e può essere revocato. La scadenza predefinita è di **90 giorni** per i refresh token inattivi e **nessuna scadenza per i token attivi** (da un refresh token è possibile ottenere nuovi refresh token). -- Un refresh token dovrebbe essere legato a un **`aud`**, a degli **scopes**, e a un **tenant** e dovrebbe poter generare solo token di accesso per quel aud, scopes (e non di più) e tenant. Tuttavia, questo non è il caso con i **token delle applicazioni FOCI**. -- Un refresh token è crittografato e solo Microsoft può decrittografarlo. +- [**Access Tokens**](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens)**:** Il client presenta questo token al resource server per **accedere alle risorse**. Può essere usato solo per una specifica combinazione di utente, client e risorsa e **non può essere revocato** fino alla scadenza — che di default è 1 ora. +- **ID Tokens**: Il client riceve questo **token dall'authorization server**. Contiene informazioni di base sull'utente. È **vincolato a una specifica combinazione di utente e client**. +- **Refresh Tokens**: Fornito al client insieme all'access token. Usato per **ottenere nuovi access e ID token**. È vincolato a una specifica combinazione di utente e client e può essere revocato. La scadenza predefinita è **90 giorni** per i refresh token inattivi e **nessuna scadenza per i token attivi** (da un refresh token è possibile ottenere nuovi refresh token). +- Un refresh token dovrebbe essere legato a un **`aud`**, ad alcuni **scopes**, e a un **tenant** e dovrebbe poter generare solo access token per quell'aud, quei scopes (e non di più) e quel tenant. Tuttavia, questo non è il caso con i token di **FOCI applications**. +- Un refresh token è crittografato e solo Microsoft può decrittarlo. - Ottenere un nuovo refresh token non revoca il refresh token precedente. > [!WARNING] -> Le informazioni per **l'accesso condizionale** sono **memorizzate** all'interno del **JWT**. Quindi, se richiedi il **token da un indirizzo IP consentito**, quell'**IP** sarà **memorizzato** nel token e poi puoi utilizzare quel token da un **IP non consentito per accedere alle risorse**. +> Le informazioni per l'**accesso condizionale** sono **memorizzate** all'interno del **JWT**. Quindi, se richiedi il **token da un indirizzo IP consentito**, quell'**IP** sarà **memorizzato** nel token e poi potrai usare quel token da un **IP non consentito per accedere alle risorse**. ### Access Tokens "aud" -Il campo indicato nel campo "aud" è il **server delle risorse** (l'applicazione) utilizzato per eseguire il login. +Il valore indicato nel campo "aud" è il **resource server** (l'applicazione) utilizzato per effettuare il login. -Il comando `az account get-access-token --resource-type [...]` supporta i seguenti tipi e ciascuno di essi aggiungerà un "aud" specifico nel token di accesso risultante: +Il comando `az account get-access-token --resource-type [...]` supporta i seguenti tipi e ciascuno di essi aggiungerà un "aud" specifico nell'access token risultante: > [!CAUTION] -> Nota che i seguenti sono solo le API supportate da `az account get-access-token` ma ce ne sono di più. +> Nota che quanto segue sono solo le API supportate da `az account get-access-token`, ma ce ne sono altre.
-aud examples +Esempi di aud -- **aad-graph (Azure Active Directory Graph API)**: Utilizzato per accedere all'API Azure AD Graph legacy (deprecata), che consente alle applicazioni di leggere e scrivere dati di directory in Azure Active Directory (Azure AD). +- **aad-graph (Azure Active Directory Graph API)**: Usato per accedere alla legacy Azure AD Graph API (deprecata), che permette alle applicazioni di leggere e scrivere dati della directory in Azure Active Directory (Azure AD). - `https://graph.windows.net/` -* **arm (Azure Resource Manager)**: Utilizzato per gestire le risorse Azure tramite l'API Azure Resource Manager. Questo include operazioni come la creazione, l'aggiornamento e la cancellazione di risorse come macchine virtuali, account di archiviazione e altro. +* **arm (Azure Resource Manager)**: Usato per gestire risorse Azure tramite l'Azure Resource Manager API. Include operazioni come creare, aggiornare e eliminare risorse come macchine virtuali, account di storage e altro. - `https://management.core.windows.net/ or https://management.azure.com/` -- **batch (Azure Batch Services)**: Utilizzato per accedere ad Azure Batch, un servizio che consente applicazioni di calcolo parallelo e ad alte prestazioni su larga scala in modo efficiente nel cloud. +- **batch (Azure Batch Services)**: Usato per accedere ad Azure Batch, un servizio che abilita applicazioni di calcolo parallelo e ad alte prestazioni su larga scala nel cloud. - `https://batch.core.windows.net/` -* **data-lake (Azure Data Lake Storage)**: Utilizzato per interagire con Azure Data Lake Storage Gen1, che è un servizio di archiviazione e analisi dei dati scalabile. +* **data-lake (Azure Data Lake Storage)**: Usato per interagire con Azure Data Lake Storage Gen1, un servizio scalabile di storage e analytics. - `https://datalake.azure.net/` -- **media (Azure Media Services)**: Utilizzato per accedere ad Azure Media Services, che forniscono servizi di elaborazione e distribuzione multimediale basati sul cloud per contenuti video e audio. +- **media (Azure Media Services)**: Usato per accedere ad Azure Media Services, che fornisce servizi cloud per l'elaborazione e la distribuzione di media video e audio. - `https://rest.media.azure.net` -* **ms-graph (Microsoft Graph API)**: Utilizzato per accedere all'API Microsoft Graph, l'endpoint unificato per i dati dei servizi Microsoft 365. Consente di accedere a dati e informazioni da servizi come Azure AD, Office 365, Enterprise Mobility e servizi di sicurezza. +* **ms-graph (Microsoft Graph API)**: Usato per accedere alla Microsoft Graph API, l'endpoint unificato per i dati dei servizi Microsoft 365. Permette di accedere a dati e insight da servizi come Azure AD, Office 365, Enterprise Mobility e servizi di Security. - `https://graph.microsoft.com` -- **oss-rdbms (Azure Open Source Relational Databases)**: Utilizzato per accedere ai servizi di database Azure per motori di database relazionali open-source come MySQL, PostgreSQL e MariaDB. +- **oss-rdbms (Azure Open Source Relational Databases)**: Usato per accedere ai servizi Database di Azure per motori relazionali open-source come MySQL, PostgreSQL e MariaDB. - `https://ossrdbms-aad.database.windows.net`
### Access Tokens Scopes "scp" -Lo scope di un token di accesso è memorizzato all'interno della chiave scp all'interno del JWT del token di accesso. Questi scopes definiscono a cosa ha accesso il token di accesso. +Lo scope di un access token è memorizzato nella chiave scp dentro l'access token JWT. Questi scopes definiscono a cosa ha accesso l'access token. -Se un JWT è autorizzato a contattare un'API specifica ma **non ha lo scope** per eseguire l'azione richiesta, **non sarà in grado di eseguire l'azione** con quel JWT. +Se un JWT è autorizzato a contattare una specifica API ma **non ha lo scope** per eseguire l'azione richiesta, **non potrà eseguire l'azione** con quel JWT. -### Get refresh & access token example +### Esempio: ottenere refresh & access token ```python # Code example from https://github.com/secureworks/family-of-client-ids-research import msal @@ -106,7 +106,7 @@ from typing import Any, Dict, List # LOGIN VIA CODE FLOW AUTHENTICATION azure_cli_client = msal.PublicClientApplication( -"04b07795-8ddb-461a-bbee-02f9e1bf7b46" # ID for Azure CLI client +"00b41c95-dab0-4487-9791-b9d2c32c80f2" # ID for Office 365 Management ) device_flow = azure_cli_client.initiate_device_flow( scopes=["https://graph.microsoft.com/.default"] @@ -144,31 +144,31 @@ scopes=["https://graph.microsoft.com/.default"], ) pprint(new_azure_cli_bearer_tokens_for_graph_api) ``` -### Altri campi del token di accesso +### Altri campi dell'access token -- **appid**: ID dell'applicazione utilizzato per generare il token -- **appidacr**: Il riferimento alla classe di contesto di autenticazione dell'applicazione indica come il client è stato autenticato; per un client pubblico il valore è 0, e se viene utilizzato un segreto del client il valore è 1 -- **acr**: Il claim del riferimento alla classe di contesto di autenticazione è "0" quando l'autenticazione dell'utente finale non ha soddisfatto i requisiti di ISO/IEC 29115. -- **amr**: Il metodo di autenticazione indica come il token è stato autenticato. Un valore di “pwd” indica che è stata utilizzata una password. -- **groups**: Indica i gruppi di cui il principale è membro. -- **iss**: L'emittente identifica il servizio di token di sicurezza (STS) che ha generato il token. e.g. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (l'uuid è l'ID del tenant) -- **oid**: L'ID dell'oggetto del principale -- **tid**: ID del tenant -- **iat, nbf, exp**: Emesso il (quando è stato emesso), Non prima (non può essere utilizzato prima di questo tempo, di solito lo stesso valore di iat), Tempo di scadenza. +- **appid**: Application ID usato per generare il token +- **appidacr**: The Application Authentication Context Class Reference indica come il client è stato autenticato; per un public client il valore è 0, e se viene usato un client secret il valore è 1 +- **acr**: The Authentication Context Class Reference claim è "0" quando l'autenticazione dell'utente finale non ha soddisfatto i requisiti di ISO/IEC 29115. +- **amr**: The Authentication method indica come il token è stato autenticato. Un valore “pwd” indica che è stata usata una password. +- **groups**: Indica i gruppi di cui il principal è membro. +- **iss**: L'issuer identifica lo security token service (STS) che ha generato il token. e.g. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (l'uuid è il tenant ID) +- **oid**: L'object ID del principal +- **tid**: Tenant ID +- **iat, nbf, exp**: Issued at (quando è stato emesso), Not before (non può essere usato prima di questo momento, solitamente stesso valore di iat), Expiration time. -## Escalation dei privilegi dei token FOCI +## FOCI Tokens Privilege Escalation -In precedenza è stato menzionato che i token di aggiornamento dovrebbero essere legati agli **ambiti** con cui sono stati generati, all'**applicazione** e al **tenant** a cui sono stati generati. Se uno di questi confini viene infranto, è possibile aumentare i privilegi poiché sarà possibile generare token di accesso per altre risorse e tenant a cui l'utente ha accesso e con più ambiti di quanto fosse originariamente previsto. +In precedenza è stato menzionato che i refresh tokens dovrebbero essere vincolati agli **scopes** con cui sono stati generati, all'**application** e al **tenant** per cui sono stati generati. Se uno di questi confini viene violato, è possibile effettuare privilege escalation in quanto sarà possibile generare access tokens per altre risorse e tenant a cui l'utente ha accesso e con più scopes rispetto a quanto previsto originariamente. -Inoltre, **questo è possibile con tutti i token di aggiornamento** nella [Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/) (account Microsoft Entra, account personali Microsoft e account social come Facebook e Google) perché come menzionano i [**docs**](https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens): "I token di aggiornamento sono legati a una combinazione di utente e client, ma **non sono legati a una risorsa o tenant**. Un client può utilizzare un token di aggiornamento per acquisire token di accesso **attraverso qualsiasi combinazione di risorsa e tenant** per cui ha il permesso di farlo. I token di aggiornamento sono crittografati e solo la Microsoft identity platform può leggerli." +Moreover, **this is possible with all refresh tokens** in the [Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/) (Microsoft Entra accounts, Microsoft personal accounts, and social accounts like Facebook and Google) because as the [**docs**](https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens) mention: "Refresh tokens are bound to a combination of user and client, but **aren't tied to a resource or tenant**. A client can use a refresh token to acquire access tokens **across any combination of resource and tenant** where it has permission to do so. Refresh tokens are encrypted and only the Microsoft identity platform can read them." -Inoltre, nota che le applicazioni FOCI sono applicazioni pubbliche, quindi **non è necessario alcun segreto** per autenticarsi al server. +Inoltre, nota che le applicazioni FOCI sono public applications, quindi **non è necessario alcun secret** per autenticarsi al server. -Poi i client FOCI noti riportati nella [**ricerca originale**](https://github.com/secureworks/family-of-client-ids-research/tree/main) possono essere [**trovati qui**](https://github.com/secureworks/family-of-client-ids-research/blob/main/known-foci-clients.csv). +I client FOCI noti riportati nella [**original research**](https://github.com/secureworks/family-of-client-ids-research/tree/main) possono essere [**found here**](https://github.com/secureworks/family-of-client-ids-research/blob/main/known-foci-clients.csv). -### Ottenere un ambito diverso +### Ottenere uno scope diverso -Proseguendo con il codice di esempio precedente, in questo codice viene richiesto un nuovo token per un ambito diverso: +Continuando con l'esempio di codice precedente, in questo codice viene richiesto un nuovo token per uno scope diverso: ```python # Code from https://github.com/secureworks/family-of-client-ids-research azure_cli_bearer_tokens_for_outlook_api = ( @@ -185,7 +185,7 @@ scopes=[ ) pprint(azure_cli_bearer_tokens_for_outlook_api) ``` -### Ottieni client e scope diversi +### Ottenere client e scopes diversi ```python # Code from https://github.com/secureworks/family-of-client-ids-research microsoft_office_client = msal.PublicClientApplication("d3590ed6-52b3-4102-aeff-aad2292ab01c") @@ -201,25 +201,26 @@ scopes=["https://graph.microsoft.com/.default"], # How is this possible? pprint(microsoft_office_bearer_tokens_for_graph_api) ``` -## Dove trovare i token +## Dove trovare tokens -Dal punto di vista di un attaccante, è molto interessante sapere dove è possibile trovare i token di accesso e di aggiornamento quando, ad esempio, il PC di una vittima è compromesso: +Dal punto di vista di un attaccante è molto utile sapere dove è possibile trovare access and refresh tokens quando, per esempio, il PC di una vittima viene compromesso: -- Dentro **`/.Azure`** -- **`azureProfile.json`** contiene informazioni sugli utenti connessi in passato -- **`clouds.config contiene`** informazioni sulle sottoscrizioni -- **`service_principal_entries.json`** contiene le credenziali delle applicazioni (tenant id, client e segreto). Solo in Linux e macOS -- **`msal_token_cache.json`** contiene token di accesso e token di aggiornamento. Solo in Linux e macOS -- **`service_principal_entries.bin`** e **`msal_token_cache.bin`** sono utilizzati in Windows e sono crittografati con DPAPI -- **`msal_http_cache.bin`** è una cache delle richieste HTTP -- Caricalo: `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)` -- **`AzureRmContext.json`** contiene informazioni sui login precedenti utilizzando Az PowerShell (ma nessuna credenziale) -- Dentro **`C:\Users\\AppData\Local\Microsoft\IdentityCache\*`** ci sono diversi file `.bin` con **token di accesso**, token ID e informazioni sugli account crittografati con il DPAPI degli utenti. -- È possibile trovare ulteriori **token di accesso** nei file `.tbres` dentro **`C:\Users\\AppData\Local\Microsoft\TokenBroken\Cache\`** che contengono un base64 crittografato con DPAPI con token di accesso. -- In Linux e macOS puoi ottenere **token di accesso, token di aggiornamento e token ID** da Az PowerShell (se utilizzato) eseguendo `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"` -- In Windows questo genera solo token ID. -- È possibile vedere se Az PowerShell è stato utilizzato in Linux e macOS controllando se esiste `$HOME/.local/share/.IdentityService/` (anche se i file contenuti sono vuoti e inutili) -- Se l'utente è **connesso a Azure con il browser**, secondo questo [**post**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web) è possibile avviare il flusso di autenticazione con un **reindirizzamento a localhost**, far autorizzare automaticamente il login dal browser e ricevere il token di aggiornamento. Nota che ci sono solo poche applicazioni FOCI che consentono il reindirizzamento a localhost (come az cli o il modulo PowerShell), quindi queste applicazioni devono essere autorizzate. +- Inside **`/.Azure`** +- **`azureProfile.json`** contiene informazioni sugli utenti che hanno effettuato il login in passato +- **`clouds.config contains`** info about subscriptions +- **`service_principal_entries.json`** contiene le credenziali delle applicazioni (tenant id, clients e secret). Solo in Linux & macOS +- **`msal_token_cache.json`** contiene access tokens e refresh tokens. Solo in Linux & macOS +- **`service_principal_entries.bin`** and msal_token_cache.bin sono usati in Windows e sono criptati con DPAPI +- **`msal_http_cache.bin`** è una cache di richieste HTTP +- Load it: `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)` +- **`AzureRmContext.json`** contiene informazioni su login precedenti effettuati con Az PowerShell (ma senza credenziali) +- Inside **`C:\Users\\AppData\Local\Microsoft\IdentityCache\*`** ci sono diversi file `.bin` con **access tokens**, ID tokens e informazioni sull'account criptate con il DPAPI dell'utente. +- È possibile trovare altri **access tokens** nei file `.tbres` dentro **`C:\Users\\AppData\Local\Microsoft\TokenBroken\Cache\`**, che contengono un base64 criptato con DPAPI con access tokens. +- In Linux e macOS puoi ottenere **access tokens, refresh tokens and id tokens** da Az PowerShell (se usato) eseguendo `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"` +- In Windows questo genera solo id tokens. +- È possibile verificare se Az PowerShell è stato usato in Linux e macOS controllando se esiste `$HOME/.local/share/.IdentityService/` (anche se i file contenuti sono vuoti e inutili) +- Se l'utente è **logged inside Azure with the browser**, secondo questo [**post**](https://www.infosecnoodle.com/p/obtaining-microsoft-entra-refresh?r=357m16&utm_campaign=post&utm_medium=web) è possibile avviare il flusso di autenticazione con un **redirect to localhost**, far sì che il browser autorizzi automaticamente il login e ricevere il refresh token. Nota che ci sono poche applicazioni FOCI che permettono il redirect a localhost (come az cli o il powershell module), quindi queste applicazioni devono essere consentite. +- Un'altra opzione spiegata nel blog è usare lo strumento [**BOF-entra-authcode-flow**](https://github.com/sudonoodle/BOF-entra-authcode-flow) che può usare qualsiasi applicazione perché **otterrà l'OAuth code per poi ottenere un refresh token dal titolo della pagina di auth finale** usando il redirect URI `https://login.microsoftonline.com/common/oauth2/nativeclient`. ## Riferimenti