Autenticacao em APIs com SSL

38
Autenticação em APIs Marcelo Milhomem

Transcript of Autenticacao em APIs com SSL

Autenticação em APIsMarcelo Milhomem

Agenda

Agenda

• HTTP REST API

• Autenticação

• SSL / Autoridade Certificadora / Certificados

• Aplicação em Mobile

Autenticação x Autorização

401 vs 403• 401 Unauthorised - Não autenticado

Eu preciso saber quem você é

• 403 Forbidden - Não autorizado

Eu sei quem você é mas, você não tem direito

Autenticação hoje

HTTP Basic(Usuário e Senha)

• Cleartext

• Precisa de SSL

• Fácil de "crackear"

• Usuário preguiçoso (mesma senha / senha fraca)

• Mesma senha em vários sistemas

OAuth(Autenticação + Autorização)

Token / JWT 1 { 2 "sub": "1234567890", 3 "name": "John Doe", 4 "admin": true 5 }

1 HMACSHA256( 2 base64UrlEncode(header) + "." + 3 base64UrlEncode(payload), 4 secret)

1 eyJhbGciOiJIUzI1NiIsInR 2 5cCI6IkpXVCJ9. 3 eyJzdWIiOiIxMjM0NTY3ODk 4 wIiwibmFtZSI6IkpvaG4gRG 5 9lIiwiYWRtaW4iOnRydWV9. 6 TJVA95OrM7E2cBab30RMHrH 7 DcEfxjoYZgeFONFh7HgQ

Todos usam SSL

Por que o SSL?

Certificados

• Par de chaves assimétricas (Pública e Privada)

• Oferece a mesma coisa que o SSL

• Autentica o cliente através da assinatura digital

• Requer um `round trip` extra

Autoridade Certificadora (CA)• Self signed (todo CA é)

• CA intermediário (cadeias de CA) - boa prática para evitar perda total em caso de comprometimento da chave privada

• Você é a autoridade :0 dona da verdade

• Utilizar CA intermediários como ACL

Show Case

Ingredientes

Keystore

Certificado do Cliente Certificado do Servidor

Keystore

CA

Gerar certificado do cliente

Gerar certificado - PHPGerando par de chaves do cliente

1 /** 2 * Chave privada 3 */ 4 $clientPrivateKey = new \Crypt_RSA(); 5 $clientPrivateKey->setPassword($password); 6 $generatedKeyPair = $clientPrivateKey->createKey(); 7 $clientPrivateKey->loadKey($generatedKeyPair['privatekey']); 8 /** 9 * Chave pública 10 */ 11 $clientPublicKey = new \Crypt_RSA(); 12 $clientPublicKey->loadKey($generatedKeyPair['publickey']); 13 $clientPublicKey->setPublicKey();

Gerar certificado - PHPPar de chaves do CA

1 /** 2 * Chave privada do CA necessária para assinar 3 */ 4 $privateKeyIntermediateCA = new \Crypt_RSA(); 5 $privateKeyIntermediateCA->setPassword('Intermediate CA password'); 6 $privateKeyIntermediateCA->loadKey(file_get_contents($privateCAKeyPath)); 7 /** 8 * Certificado do CA 9 */ 10 $certificateIntermediateCA = new \File_X509(); 11 $certificateIntermediateCA->setPrivateKey($privateKeyIntermediateCA); 12 $certificateIntermediateCA->loadX509(file_get_contents($certificateCAKeyPath));

Certificado do Cliente - PHPAssinando o certificado

1 /** 2 * CSR - Requisição de certificado 3 */ 4 $certificateSigningRequest = new \File_X509(); 5 $certificateSigningRequest->setDN($certificateIntermediateCA->getDN()); 6 $certificateSigningRequest->setPublicKey((object)$clientPublicKey); 7 $certificateX509 = new \File_X509(); 8 $certificateX509->setEndDate('+1 month'); 9 /** 10 * Assinatura do CA 11 */ 12 $clientCertificate = 13 $certificateX509->sign($certificateIntermediateCA, $certificateSigningRequest); 14 /** 15 * Resultado chave privada + certificado do cliente 16 */ 17 echo $clientPrivateKey->getPrivateKey(); 18 echo PHP_EOL; 19 echo $certificateX509->saveX509($clientCertificate);

Certificado do Cliente - Android

1 /** 2 * Certificado do cliente + chave privada empacotados em um arquivo PFX 3 */ 4 KeyStore keyStore = KeyStore.getInstance("PKCS12"); 5 FileInputStream clientCertificateContent = 6 new FileInputStream("/path/to/publicAndPrivateKey.p12"); 7 keyStore.load(clientCertificateContent, "private key password".toCharArray()); 8 KeyManagerFactory keyManagerFactory = 9 KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 10 keyManagerFactory.init(keyStore, "private key password".toCharArray());

Embarcar CA

1 -----BEGIN CERTIFICATE----- 2 MIIDnzCCAwigAwIBAgIJAJZTKp0w82kyMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYD 3 VQQGEwJCUjETMBEGA1UECBQKU8OjbyBQYXVsbzETMBEGA1UEBxQKU8OjbyBQYXVs 4 bzERMA8GA1UEChMIRWFzeVRheGkxETAPBgNVBAsTCEVhc3lUYXhpMQswCQYDVQQD 5 EwJFVDEmMCQGCSqGSIb3DQEJARYXY29udGF0b0BlYXN5dGF4aS5jb20uYnIwHhcN 6 MTYwMTE4MTYwNDQ2WhcNMzYwMTEzMTYwNDQ2WjCBkjELMAkGA1UEBhMCQlIxEzAR 7 BgNVBAgUClPDo28gUGF1bG8xEzARBgNVBAcUClPDo28gUGF1bG8xETAPBgNVBAoT 8 CEVhc3lUYXhpMREwDwYDVQQLEwhFYXN5VGF4aTELMAkGA1UEAxMCRVQxJjAkBgkq 9 hkiG9w0BCQEWF2NvbnRhdG9AZWFzeXRheGkuY29tLmJyMIGfMA0GCSqGSIb3DQEB 10 AQUAA4GNADCBiQKBgQDTny6B8fbG1UXEtMYYFKfODKduzYTovLIUzXKFrX9wHEsC 11 lTOLqtvKsvkLkjXsC3R/HedWoRbFXJbaaw723csPlxrxuBqfkNBJB25ihccwVWbP 12 WpEaDluL2btsBdW2uuDshpXk2z6Gf5xcePnmf24iWpvJs1uBJWkEGRR2TzEi8wID 13 AQABo4H6MIH3MB0GA1UdDgQWBBRMm/EjlWrvxXTtUmotq+kwN52u3zCBxwYDVR0j 14 BIG/MIG8gBRMm/EjlWrvxXTtUmotq+kwN52u36GBmKSBlTCBkjELMAkGA1UEBhMC 15 QlIxEzARBgNVBAgUClPDo28gUGF1bG8xEzARBgNVBAcUClPDo28gUGF1bG8xETAP 16 BgNVBAoTCEVhc3lUYXhpMREwDwYDVQQLEwhFYXN5VGF4aTELMAkGA1UEAxMCRVQx 17 JjAkBgkqhkiG9w0BCQEWF2NvbnRhdG9AZWFzeXRheGkuY29tLmJyggkAllMqnTDz 18 aTIwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAEcW5DO0ODdWd0kZzU 19 6eSg8ckDPImveTiKpFU5a96WxlVmwU8IlwAZ695w6ciIwDjys6BUNUBayTczhJbO 20 83Ykrt+b62+ksqKKFrCcba10R8QSjhYZSy7Yv08m/6+OiP+rUb2Jg4zVdAPhaaVn 21 lb1Nff1EgOdWIdjTKpPzHRjY4g== 22 -----END CERTIFICATE-----

Autoridade Certificadora Aplicativo Mobile

Requisição OkHttp - Android

1 OkHttpClient client = new OkHttpClient(); 2 client.setSslSocketFactory(sslContext.getSocketFactory()); 3 client.newCall(new Request.Builder() 4 .url("https://easytaxi.com.br") 5 .build() 6 ).execute();

Adicionando Cabeçalhos

1 GET /passenger/56edfd08756f458a6f0041ad HTTP/1.1 2 Host: api.easytaxi.com.br 3 User-Agent: curl/7.43.0 4 X-SSL: 1 5 X-SSL-Client-Verify: 0 6 X-SSL-Client-SHA1: "a01b894d12579d88efce97d27107f380b05f5968" 7 X-SSL-Client-CN: "56edfd08756f458a6f0041ad" 8 X-SSL-Issuer: "/C=BR/OU=EasyTaxi/[email protected]” 9 X-SSL-Client-Not-Before: "120101100030Z" 10 X-SSL-Client-Not-After: "160101100030Z" 11 Accept: */*

Use Cases

Validade• Todo certificado tem validade

• Demonstração

• Teste gratuito temporário

• Revalidação de login

Grupos e Cadeias

• Você pode criar vários CAs intermediários

• Criar intermediário e assinar os usuários do grupo com ele

• Revogar um intermediário e todos certificados abaixo dele

• Intermediários também possuem validade

Integridade

• Benefício da autenticação mútua (2WAY)

Assinatura digital

• Não repúdio - Garantia da que o portador assinou

• Assinar documentos digitalmente

• Certificado digital

Offload

Descentralizado

• Servidores conseguem validar o certificado offline

• Precisam apenas compartilhar as chaves do CA

• Ideal para microserviços

Emissão on-demand

• Emissão de certificados dinamicamente

• Let’s Encrypt faz isso para certificado de servidores

• Crie sua PKI para emitir certificados para clientes

Autorização Simples - 403

1 #GET /passenger/56edfd08756f458a6f0041ad HTTP/1.1 2 $uri = current(explode('?', getenv('REQUEST_URI'))); 3 preg_match('#[a-zA-Z0-9\-]+(/)?$#', $uri, $matches); 4 $passengerId = $matches[0]; 5 if ($request->headers->get('X-SSL-Client-CN') != $passengerId) { 6 return new Response('Forbidden', 403); 7 }

Gerar certificado - PHPAssinando o certificado

1 /** 2 * CSR - Requisição de certificado 3 */ 4 $certificateSigningRequest = new \File_X509(); 5 $certificateSigningRequest->setDN($certificateIntermediateCA->getDN()); 6 $certificateSigningRequest->setDNProp('uniqueidentifier', 'my unique ID'); 7 $certificateSigningRequest->setPublicKey((object)$clientPublicKey); 8 $certificateX509 = new \File_X509(); 9 $certificateX509->setEndDate('+1 month'); 10 /** 11 * Assinatura do CA 12 */ 13 $clientCertificate = 14 $certificateX509->sign($certificateIntermediateCA, $certificateSigningRequest);

Por que ninguém ta usando isso?

Perguntas?

Vamos manter contato!

https://legacy.joind.in/17491

https://gist.github.com/milhomem