Pular para o conteúdo principal

Guia de Autenticação

A TranscriMed usa fluxo de código de autorização OAuth2 para autenticação segura de parceiros. Este guia cobre tudo que você precisa para implementar autenticação em sua aplicação.

Visão Geral

O fluxo OAuth2 consiste em quatro etapas principais:

  1. Solicitação de Autorização - Redirecionar usuários para a TranscriMed
  2. Consentimento do Usuário - Usuários concedem permissões ao seu app
  3. Código de Autorização - Receber código de autorização via callback
  4. Troca de Token - Trocar código por tokens de acesso

Antes de Começar

Registrar Sua Aplicação

  1. Visite o Portal do Desenvolvedor TranscriMed
  2. Crie uma conta de desenvolvedor
  3. Registre sua aplicação com:
    • Nome da Aplicação: Nome para exibição aos usuários
    • URIs de Redirecionamento: Para onde os usuários retornam após autorização
    • Escopos: Permissões que seu app precisa
    • Tipo de Aplicação: Web, móvel ou server-to-server

Obter Suas Credenciais

Após o registro, você receberá:

  • Client ID: Identificador público para sua aplicação
  • Client Secret: Chave privada (mantenha segura!)
  • URIs de Redirecionamento: URLs de callback registradas
Segurança

Nunca exponha seu client secret em código do lado do cliente ou confirme-o no controle de versão. Armazene-o com segurança em variáveis de ambiente ou configuração segura.

Passo 1: Solicitação de Autorização

Redirecione usuários para o endpoint de autorização para iniciar o fluxo OAuth2.

URL de Autorização

GET https://api.transcrimed.com.br/api/oauth/authorize

Parâmetros Obrigatórios

ParâmetroTipoDescrição
response_typestringDeve ser code
client_idstringID do cliente da sua aplicação
redirect_uristringDeve corresponder à URI registrada
scopestringLista de escopos separados por espaço
statestringValor aleatório para proteção CSRF

Escopos Disponíveis

Solicite apenas os escopos que você precisa. Escopos disponíveis:

EscopoDescrição
medical_records:readLer registros médicos
medical_records:writeCriar e atualizar registros médicos
medical_records:deleteExcluir registros médicos
jobs:readLer status e resultados de tarefas
jobs:writeCriar, cancelar e gerenciar tarefas
worklists:writeEnviar itens de lista de trabalho de sistemas RIS/PACS
worklists:manageAtualizar status de itens da lista de trabalho
worklists:readLer itens de lista de trabalho (uso interno)

Exemplo de Implementação

JavaScript (Frontend)

function initiateOAuth2Flow() {
// Gerar state aleatório para proteção CSRF
const state = generateRandomString(32);

// Armazenar state em session/localStorage para verificação
sessionStorage.setItem('oauth_state', state);

// Construir URL de autorização
const authUrl = new URL('https://api.transcrimed.com.br/api/oauth/authorize');
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('client_id', 'seu_client_id');
authUrl.searchParams.set('redirect_uri', 'https://seuapp.com/oauth/callback');
authUrl.searchParams.set('scope', 'medical_records:read medical_records:write jobs:read');
authUrl.searchParams.set('state', state);

// Redirecionar usuário para página de autorização
window.location.href = authUrl.toString();
}

function generateRandomString(length) {
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let text = '';
for (let i = 0; i < length; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}

Python (Backend)

import secrets
import urllib.parse
from flask import Flask, redirect, session

app = Flask(__name__)

@app.route('/auth/login')
def login():
# Gerar state para proteção CSRF
state = secrets.token_urlsafe(32)
session['oauth_state'] = state

# Construir URL de autorização
auth_url = 'https://api.transcrimed.com.br/api/oauth/authorize'
params = {
'response_type': 'code',
'client_id': 'seu_client_id',
'redirect_uri': 'https://seuapp.com/oauth/callback',
'scope': 'medical_records:read medical_records:write jobs:read',
'state': state
}

full_url = f"{auth_url}?{urllib.parse.urlencode(params)}"
return redirect(full_url)

Passo 2: Lidar com Callback

Após o consentimento do usuário, a TranscriMed redireciona para sua URI registrada com um código de autorização.

Callback de Sucesso

https://seuapp.com/oauth/callback?code=CODIGO_AUTH&state=ESTADO_CSRF

Callback de Erro

https://seuapp.com/oauth/callback?error=access_denied&error_description=Usuário+negou+acesso&state=ESTADO_CSRF

Exemplo de Handler de Callback

JavaScript

function handleOAuthCallback() {
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
const state = urlParams.get('state');
const error = urlParams.get('error');

// Verificar erros
if (error) {
console.error('Erro OAuth:', urlParams.get('error_description'));
return;
}

// Verificar state para prevenir ataques CSRF
const storedState = sessionStorage.getItem('oauth_state');
if (state !== storedState) {
console.error('Parâmetro state inválido');
return;
}

// Trocar código por tokens
exchangeCodeForTokens(code);
}

Python

@app.route('/oauth/callback')
def oauth_callback():
code = request.args.get('code')
state = request.args.get('state')
error = request.args.get('error')

# Verificar erros
if error:
return f"Erro OAuth: {request.args.get('error_description')}"

# Verificar state
if state != session.get('oauth_state'):
return "Parâmetro state inválido"

# Trocar código por tokens
tokens = exchange_code_for_tokens(code)

# Armazenar tokens com segurança
session['access_token'] = tokens['access_token']
session['refresh_token'] = tokens['refresh_token']

return redirect('/dashboard')

Passo 3: Troca de Token

Trocar o código de autorização por tokens de acesso e atualização.

Endpoint de Token

POST https://api.transcrimed.com.br/api/oauth/token

Parâmetros da Solicitação

ParâmetroTipoDescrição
grant_typestringDeve ser authorization_code
codestringCódigo de autorização do callback
redirect_uristringMesma URI usada na autorização
client_idstringID do cliente da sua aplicação
client_secretstringSecret do cliente da sua aplicação

Exemplo de Implementação

JavaScript

async function exchangeCodeForTokens(authCode) {
try {
const response = await fetch('https://api.transcrimed.com.br/api/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code: authCode,
redirect_uri: 'https://seuapp.com/oauth/callback',
client_id: 'seu_client_id',
client_secret: 'seu_client_secret'
})
});

if (!response.ok) {
throw new Error(`Falha na troca de token: ${response.status}`);
}

const tokens = await response.json();

// Armazenar tokens com segurança
localStorage.setItem('access_token', tokens.access_token);
localStorage.setItem('refresh_token', tokens.refresh_token);
localStorage.setItem('expires_at', Date.now() + (tokens.expires_in * 1000));

return tokens;
} catch (error) {
console.error('Erro na troca de token:', error);
throw error;
}
}

Resposta do Token

{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "refresh_token_string_aqui",
"scope": "medical_records:read medical_records:write jobs:read"
}

Passo 4: Usar Tokens de Acesso

Inclua o token de acesso no cabeçalho Authorization para todas as chamadas da API:

Authorization: Bearer seu_token_de_acesso_aqui

Exemplo de Chamada da API

async function listMedicalRecords(accessToken) {
const response = await fetch('https://api.transcrimed.com.br/api/v1/medical-records', {
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
});

if (!response.ok) {
throw new Error(`Chamada da API falhou: ${response.status}`);
}

return response.json();
}

Atualização de Token

Tokens de acesso expiram após 1 hora. Use tokens de atualização para obter novos tokens de acesso sem requerer nova autenticação do usuário.

Solicitação de Token de Atualização

POST https://api.transcrimed.com.br/api/oauth/token

Parâmetros

ParâmetroTipoDescrição
grant_typestringDeve ser refresh_token
refresh_tokenstringSeu token de atualização
client_idstringID do cliente da sua aplicação
client_secretstringSecret do cliente da sua aplicação

Exemplo de Implementação

async function refreshAccessToken(refreshToken) {
try {
const response = await fetch('https://api.transcrimed.com.br/api/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: refreshToken,
client_id: 'seu_client_id',
client_secret: 'seu_client_secret'
})
});

if (!response.ok) {
throw new Error('Falha na atualização do token');
}

const tokens = await response.json();

// Atualizar tokens armazenados
localStorage.setItem('access_token', tokens.access_token);
localStorage.setItem('expires_at', Date.now() + (tokens.expires_in * 1000));

// Token de atualização pode ser rotacionado
if (tokens.refresh_token) {
localStorage.setItem('refresh_token', tokens.refresh_token);
}

return tokens.access_token;
} catch (error) {
console.error('Erro na atualização do token:', error);
// Redirecionar para login se a atualização falhar
window.location.href = '/auth/login';
throw error;
}
}

Revogação de Token

Revogue tokens quando usuários fazem logout ou quando não são mais necessários.

Solicitação de Revogação de Token

POST https://api.transcrimed.com.br/api/oauth/revoke

Parâmetros

ParâmetroTipoDescrição
tokenstringToken a ser revogado
token_type_hintstringaccess_token ou refresh_token
client_idstringID do cliente da sua aplicação
client_secretstringSecret do cliente da sua aplicação

Exemplo de Implementação

async function revokeToken(token, tokenType = 'access_token') {
try {
const response = await fetch('https://api.transcrimed.com.br/api/oauth/revoke', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
token: token,
token_type_hint: tokenType,
client_id: 'seu_client_id',
client_secret: 'seu_client_secret'
})
});

if (response.ok) {
console.log('Token revogado com sucesso');
// Limpar localStorage
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
localStorage.removeItem('expires_at');
}
} catch (error) {
console.error('Erro na revogação do token:', error);
}
}

Melhores Práticas de Segurança

Parâmetro State

Sempre use o parâmetro state para prevenir ataques CSRF:

// Gerar state criptograficamente seguro
const state = window.crypto.getRandomValues(new Uint8Array(32))
.reduce((acc, byte) => acc + byte.toString(16).padStart(2, '0'), '');

Segurança do Client Secret

  • Nunca exponha client secrets em código frontend
  • Armazene secrets em variáveis de ambiente
  • Use proxy backend seguro para troca de token
  • Rotacione secrets regularmente

Armazenamento de Token

  • Use cookies seguros e httpOnly para aplicações web
  • Use keychain/keystore seguro para aplicações móveis
  • Implemente criptografia de token para armazenamento local
  • Defina expiração apropriada de token

Testando Autenticação

Usando cURL

# Passo 1: Obter código de autorização (passo manual do navegador)
open "https://api.transcrimed.com.br/api/oauth/authorize?response_type=code&client_id=seu_client_id&redirect_uri=https://seuapp.com/callback&scope=medical_records:read&state=estado_aleatorio"

# Passo 2: Trocar código por tokens
curl -X POST https://api.transcrimed.com.br/api/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&code=codigo_recebido&redirect_uri=https://seuapp.com/callback&client_id=seu_client_id&client_secret=seu_client_secret"

# Passo 3: Usar token de acesso
curl -X GET https://api.transcrimed.com.br/api/v1/medical-records \
-H "Authorization: Bearer seu_token_de_acesso"

Próximos Passos

Uma vez que a autenticação esteja funcionando:

  1. Explorar Referência da API - Aprenda sobre endpoints disponíveis
  2. Experimentar Exemplos - Veja padrões de integração do mundo real
  3. Usar Ferramentas - Simplifique a integração com nossas ferramentas de desenvolvimento
  4. Contatar Suporte - Obtenha ajuda de integração

Precisa de ajuda? Entre em contato com nossos desenvolvedores para assistência de integração.