OneDrive / SharePoint - Acesso programático (Guia técnico)

Resumo

Documento técnico com instruções passo-a-passo para: registrar uma aplicação no Azure AD, obter tenantId, clientId, clientSecret, configurar permissões apropriadas e métodos comuns para consumir conteúdo do SharePoint / OneDrive (incluindo links compartilhados). Contém exemplos em Python (MSAL + requests), exemplos curl, e diagramas mermaid para ilustrar fluxos de autenticação.

Pré-requisitos

  • Conta com privilégios de Administrador Global ou Administrador de Aplicações no tenant Azure AD onde a aplicação será registrada.
  • Licença Microsoft 365 ativa para o(s) usuários cujo OneDrive/SharePoint serão consumidos (OneDrive for Business / SharePoint Online).
  • Python 3.8+ (recomendado). Pacotes usados nos exemplos: msal, requests, pandas (opcional).

Instalação mínima:

pip install msal requests

Visão geral dos fluxos

1. Registrar a aplicação no Azure AD (passo a passo)

  1. Acesse portal: Microsoft Entra ID (Azure Active Directory) → App registrations → New registration.
  2. Defina nome (por exemplo sharepoint-data-consumer).
  3. Supported account types: escolha conforme necessidade (single-tenant para testes internos).
  4. Redirect URI: não é obrigatório para client credentials; para delegated flows (ex.: auth code) informe https://login.microsoftonline.com/common/oauth2/nativeclient ou outra URI adequada.

Após criar a aplicação, anote:

  • Application (client) ID → CLIENT_ID
  • Directory (tenant) ID → TENANT_ID

2. Configurar credenciais (client secret)

  1. App registrations → sua app → Certificates & secrets → New client secret.
  2. Anote o client_secret gerado (ex.: CLIENT_SECRET).
  3. Recomenda-se usar Azure Key Vault para armazenar segredos em produção.

3. Configurar permissões Microsoft Graph

Decida o tipo de acesso: App-only (daemon/pipeline automático) ou Delegated (com usuário interativo).

Recomendações de permissões para pipelines automáticos (App-only)

  • Microsoft Graph (Application permissions):

    • Files.Read.All (ler arquivos em toda a organização)
    • Files.ReadWrite.All (se precisar escrever)
    • Sites.Read.All / Sites.ReadWrite.All (para bibliotecas SharePoint)
    • User.Read.All (opcional — listar usuários)

Após adicionar as permissões, clicar em Grant admin consent para o tenant.

Permissões para cenários delegados (se houver login humano)

  • Microsoft Graph (Delegated permissions):

    • Files.Read / Files.ReadWrite
    • Sites.Read.All (se necessário)

4. Obter token (exemplos)

4.1 App-only (Client Credentials) — Python (MSAL)

import msal

TENANT_ID = "<TENANT_ID>"
CLIENT_ID = "<CLIENT_ID>"
CLIENT_SECRET = "<CLIENT_SECRET>"

authority = f"https://login.microsoftonline.com/{TENANT_ID}"
SCOPE = ["https://graph.microsoft.com/.default"]

app = msal.ConfidentialClientApplication(
    client_id=CLIENT_ID,
    authority=authority,
    client_credential=CLIENT_SECRET,
)

token_resp = app.acquire_token_for_client(scopes=SCOPE)
if "access_token" not in token_resp:
    raise SystemExit(token_resp)

access_token = token_resp["access_token"]
headers = {"Authorization": f"Bearer {access_token}"}

Observações:

  • /.default usa as permissões de aplicação concedidas no portal.
  • Tokens de app-only representam a aplicação, não um usuário.

4.2 Delegated (Device Code) — quando o usuário puder interagir

import msal

CLIENT_ID = "<CLIENT_ID>"
AUTHORITY = "https://login.microsoftonline.com/common"  # ou tenants específicos
SCOPES = ["Files.Read.All", "offline_access", "User.Read"]

app = msal.PublicClientApplication(CLIENT_ID, authority=AUTHORITY)
flow = app.initiate_device_flow(scopes=SCOPES)
print(flow["message"])  # usuário abre o browser e autentica

token = app.acquire_token_by_device_flow(flow)
access_token = token["access_token"]
headers = {"Authorization": f"Bearer {access_token}"}

5. Endpoints úteis Microsoft Graph

  • Listar drives do tenant (app-only): GET /drives
  • Acessar drive de usuário (app-only): GET /users/{userPrincipalName}/drive ou GET /drives/{drive-id}
  • Listar filhos de um driveItem: GET /drives/{drive-id}/items/{item-id}/children ou GET /users/{user}/drive/root/children
  • Baixar conteúdo de arquivo (driveItem): GET /drive/items/{item-id}/content ou usar @microsoft.graph.downloadUrl retornado pela API.
  • Acessar item a partir de link de compartilhamento: GET /shares/{shareId}/driveItem ou GET /shares/{shareId}/driveItem/children

8. Curl minimal (token obtido previamente)

# obter metadados de um driveItem
curl -H "Authorization: Bearer $TOKEN" \
  "https://graph.microsoft.com/v1.0/drives/{drive-id}/items/{item-id}"

# baixar conteúdo
curl -H "Authorization: Bearer $TOKEN" \
  "https://graph.microsoft.com/v1.0/drives/{drive-id}/items/{item-id}/content" -o arquivo.ext

9. Boas práticas de segurança e operacionais

  • Nunca commitar client_secret em repositórios. Use Azure Key Vault ou managed identities.
  • Conceda permissões mínimas necessárias (principle of least privilege).
  • Para pipelines automáticas em Azure, prefira Managed Identity + Key Vault quando possível.
  • Rotacione secrets periodicamente.
  • Registre logs de acesso e monitore usando Azure Monitor/Azure AD sign-in logs.

10. Troubleshooting (erros comuns)

  • "/me request is only valid with delegated authentication flow": não use /me com app-only; substitua por /users/{user} ou drives/{drive-id}.
  • User not found: userPrincipalName não existe no tenant ou o ambiente é MSA (conta pessoal) e não Azure AD.
  • invalidAuthenticationToken ao acessar /shares/{shareId}: o link pode não ser acessível via API (visualização no browser não garante API access). Peça ao proprietário para gerar um link de download “Anyone with the link” com permissão de download.

11. Referências

  • Microsoft Graph: Permissions reference
  • Microsoft Graph: Access shared items (/shares endpoint)
  • Microsoft Graph: DriveItem resource and download (@microsoft.graph.downloadUrl)
  • MSAL Python: acquiring tokens (client credentials, device code)
  • OneDrive / OneDrive API: shares encoding

12. Anexos — exemplos práticos (snippets reutilizáveis)

OneDriveClient (esqueleto)

class OneDriveClient:
    def __init__(self, tenant_id, client_id, client_secret):
        import msal
        self.app = msal.ConfidentialClientApplication(
            client_id=client_id,
            authority=f"https://login.microsoftonline.com/{tenant_id}",
            client_credential=client_secret,
        )
        self.token = None

    def get_token(self):
        if not self.token:
            self.token = self.app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])['access_token']
        return self.token

    def headers(self):
        return {"Authorization": f"Bearer {self.get_token()}"}

    def download_shared_folder(self, shared_link, target_dir="."):
        import os, requests
        share_id = link_to_share_id(shared_link)
        url = f"https://graph.microsoft.com/v1.0/shares/{share_id}/driveItem/children"
        resp = requests.get(url, headers=self.headers()).json()
        for it in resp.get('value', []):
            dl = it.get('@microsoft.graph.downloadUrl')
            if dl:
                r = requests.get(dl)
                path = os.path.join(target_dir, it['name'])
                with open(path, 'wb') as fh:
                    fh.write(r.content)