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:
- Solicitação de Autorização - Redirecionar usuários para a TranscriMed
- Consentimento do Usuário - Usuários concedem permissões ao seu app
- Código de Autorização - Receber código de autorização via callback
- Troca de Token - Trocar código por tokens de acesso
Antes de Começar
Registrar Sua Aplicação
- Visite o Portal do Desenvolvedor TranscriMed
- Crie uma conta de desenvolvedor
- 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
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âmetro | Tipo | Descrição |
|---|---|---|
response_type | string | Deve ser code |
client_id | string | ID do cliente da sua aplicação |
redirect_uri | string | Deve corresponder à URI registrada |
scope | string | Lista de escopos separados por espaço |
state | string | Valor aleatório para proteção CSRF |
Escopos Disponíveis
Solicite apenas os escopos que você precisa. Escopos disponíveis:
| Escopo | Descrição |
|---|---|
medical_records:read | Ler registros médicos |
medical_records:write | Criar e atualizar registros médicos |
medical_records:delete | Excluir registros médicos |
jobs:read | Ler status e resultados de tarefas |
jobs:write | Criar, cancelar e gerenciar tarefas |
worklists:write | Enviar itens de lista de trabalho de sistemas RIS/PACS |
worklists:manage | Atualizar status de itens da lista de trabalho |
worklists:read | Ler 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âmetro | Tipo | Descrição |
|---|---|---|
grant_type | string | Deve ser authorization_code |
code | string | Código de autorização do callback |
redirect_uri | string | Mesma URI usada na autorização |
client_id | string | ID do cliente da sua aplicação |
client_secret | string | Secret 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âmetro | Tipo | Descrição |
|---|---|---|
grant_type | string | Deve ser refresh_token |
refresh_token | string | Seu token de atualização |
client_id | string | ID do cliente da sua aplicação |
client_secret | string | Secret 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âmetro | Tipo | Descrição |
|---|---|---|
token | string | Token a ser revogado |
token_type_hint | string | access_token ou refresh_token |
client_id | string | ID do cliente da sua aplicação |
client_secret | string | Secret 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:
- Explorar Referência da API - Aprenda sobre endpoints disponíveis
- Experimentar Exemplos - Veja padrões de integração do mundo real
- Usar Ferramentas - Simplifique a integração com nossas ferramentas de desenvolvimento
- Contatar Suporte - Obtenha ajuda de integração
Precisa de ajuda? Entre em contato com nossos desenvolvedores para assistência de integração.