Segurança para serviços REST, Redes Sociais e Web 2.0 Fabio Velloso [email protected] Fabio Velloso Bacharel em Ciência da Computação pela Universidade Federal de São Carlos-UFSCar Fundador do SouJava Desenvolvendo projetos com tecnologia Java desde 96 Professor de SOA e Web Services do curso de PósGraduação "Lato-Sensu" em Desenvolvimento de Software para Web da UFSCar Arquiteto de Sistemas na Telefonica 2 Agenda Introdução REST e WS Segurança Web OAuth, Redes Sociais e REST OpenID OpenPTK 3 Como implementar segurança para serviços REST, HyperMidia e Redes Sociais 4 Web Services Web Services SOAP Protocolo SOAP sobre HTTP WSDL UDDI Protocolos de segurança WS-* REST Paradigma mais novo Simples Recursos Segurança??? 5 Web Services Security (SOAP) WS-Security XML Signature XML Encryption XML Key Management (XKMS) WS-SecureConversation WS-SecurityPolicy WS-Trust WS-Federation WS-Federation Active Requestor Profile WS-Federation Passive Requestor Profile Web Services Security Kerberos Binding Web Single Sign-On Interoperability Profile Web Single Sign-On Metadata Exchange Protocol Security Assertion Markup Language (SAML) XACML 6 RESTful Web Services Paradigma simples para Web Services Acrônimo para Representational State Transfer Não é um padrão É um estilo de Arquitetura de Software “Um conjunto de regras de design que identificam os tipos de componentes e conectores que podem ser usados para compor um sistema ou subsistema” 7 RESTful Web Services Recursos são acessíveis e identificados por URI URI parameters /users/{user-id} http://soujava.org.br/users/323421 Conjunto uniforme de operações padronizadas Query parameters para localizar outros recursos http://soujava.org.br/users?id=02115 JAX-RS - Java API for RESTful Web Services Framework com anotações para RESTful Web Services Anotações que encapsulam métodos e parâmetros HTTP Jersey implementação de referência Suporte a mecanismos de autenticação HTTPBasicAuthFilter, HTTPDigestAuthFilter 8 JAX-RS - @GET, @POST, @DELETE @Path("/library") public class Library { @GET @Path("/books") public String getBooks() {...} @GET @Path("/book/{isbn}") public String getBook(@PathParam("isbn") String id) {..} @DELETE @Path("/book/{id}") public void removeBook(@PathParam("id") String id) {...} } 9 Web como plataforma para sistemas distribuídos Pensar em Recursos “Resource-Oriented” Recurso pode ser qualquer coisa exposta na Web: Video,Imagens, Documentos URI referenciando recursos java.net www.java.net “Hypermedia as the engine of application state” Redes Sociais Segurança já disponível para Web 10 Basic authentication Usuário e senha no Header HTTP, sem criptografia User:password Base 64 GET /areaprivada/index.html HTTP/1.1 Host: localhost Authorization: Basic QwxhZATpbjpvcGVuIHNlc2FeOP== Uso de SSL 11 Basic authentication Java EE Security @RolesAllowed Acesso permitido a usuários com papel adequado Exemplo: @GET @Path("/Secure") @RolesAllowed("admin") @Produces("text/plain") public String getMessage(@Context HttpHeaders headers){ return "Olá JavaOne Brasil"; } 12 Basic authentication web.xml <login-config> <auth-method>BASIC</authmethod> <realm-name>Test</realmname> tomcat-users.xml <user password="fabio" roles="manager,admin" username="fabio"/> <user password="tomcat" roles="manager,admin" username="tomcat"/> </login-config> <security-role> <role-name>admin</rolename> </security-role> <security-role> <role-name>user</role-name> </security-role> 13 Basic authentication Base 64 private String getCredentials(HttpHeaders headers) { String authorization = headers.getRequestHeader("authorization").get(0); authorization = authorization.substring("Basic ".length()); String[] data = new String(Base64.base64Decode(authorization)).split(":"); String username = data[0]; String password = data[1]; } 14 Basic authentication Problemas: Não é criptografia Sem integridade Sem confidencialidade Senhas trafegando pela rede Chave compartilhada Controle de acesso fraco Log e auditoria de acesso dificultada Digest e SSL Mecanismos de delegação 15 OAuth Protocolo aberto para permitir a autorização usando uma API segura, simples e padronizada para aplicativos desktop e web Compartilhar dados (recursos), com vários usuários, sem compartilhar sua identidade RFC 5849 – OAuth v1.0 - Internet Engineering Task Force Possibilita proteção de acesso a recursos Web Facebook, Twitter, Linkedin, SalesForce Token e Secret para acesso a aplicação/recurso Token de requisição e Token de acesso Token pode ser revogado a qualquer momento Autorização para cada request facilita log e auditoria 16 OAuth – Entidades Service Provider Provedor do recurso protegido Consumer A aplicação que requisita acesso a um recurso protegido Resource Owner O proprietário do recurso protegido hospedado no servidor. Controla e aprova acesso 17 18 OAuth Token e CallBack 19 Jersey e OAuth Suporte ao protocolo v1.0a Módulos maven oauth-client-{version}.jar Filtro para anexar OAuth Header nas requisições oauth-server-{version}.jar Geração e tratamento de Tokens oauth-signature-{version}.jar Suporte a assinaturas Oauth HMAC_SHA1, PLAINTEXT, RSA_SHA1 Projetos com NetBeans e Maven Adicionar dependências GroupId: com.sun.jersey.contribs.jersey-oauth ArtifactId: oauth-server Version: ${jersey-version} 20 Jersey e OAuth OAuthSecrets OAuth secrets a serem utilizados na assinatura das requisições OAuthParameters Parâmetros utilizados nas requisições Chave da aplicação/usuário (CONSUMER_KEY) Método de assinatura ("HMAC-SHA1") Versão Client Cliente que acessa serviço/recurso OAuthClientFilter Assina os requests com assinatura OAuth Adiciona um Header com os parametros OAuth 21 OAuth Request Token https://site_destino/oauth/requestToken Exemplo: – https://api.linkedin.com/uas/oauth/requestToken authorization OAuth oauth_nonce="a912e229-2488-4a69-ad31-7f3cc7390cd4", oauth_callback="http%3A%2F%2Flocalhost%2Foauth_callback", oauth_consumer_key="c6z48v4MU1QBCpm6R9XshNfVVWmV3RzgwoZFZ9F", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="TXJwbUzeX%2BvWTZqenVGSxvdmB83D", oauth_timestamp="1291596497" Adiciona um único Header HTTP chamado authorization 22 OAuth Request Token Define OAuthSecret e OAuthParameters com os valores gerados pelo servidor dos recursos OAuthSecrets oAuthSecrets = new OAuthSecrets().consumerSecret(Definitions.CONSUMER_SECRET); OAuthParameters oAuthParams = new OAuthParameters().consumerKey(Definitions.CONSUMER_KEY). signatureMethod("HMAC-SHA1").version("1.0"); Assina o request Assina o request com assinatura OAuth Adiciona o Header “authorization” com os parâmetros OAuth client.addFilter( new OAuthClientFilter(client.getProviders(), oAuthParams, oAuthSecrets)); Form response = client.resource(Definitions.REQUEST_TOKEN_URL).post(Form.class); Executa POST para pedir RequestToken 23 OAuth Authorize URL https://site_destino/oauth/authorize Exemplo: https://www.linkedin.com/uas/oauth/authorize? oauth_token=6451ca51-6a82-410e-a3f3-f7d837d856fc Retorno para callback url definida Conta Aplicação Data de Acesso 24 OAuth Authorize URL POST executado para pedir um RequestToken Form response = client.resource(Definitions.REQUEST_TOKEN_URL).post(Form.class); Definitions.setToken(response.getFirst(OAuthParameters.TOKEN), response.getFirst(OAuthParameters.TOKEN_SECRET), false); Armazena os valores de Retornados (RequestToken e TokenSecret) Response.seeOther(UriBuilder.fromPath(Definitions.AUTHORIZE_URL). queryParam(OAuthParameters.TOKEN, response.getFirst(OAuthParameters.TOKEN)).build()).build(); Redireciona Para página de Autorização do Serviço “oauth_token” RequestToken 25 OAuth Access Token https://site_destino/oauth/accessToken Exemplo: https://api.linkedin.com/uas/oauth/accessToken Authorization: OAuth oauth_nonce="wm2h9DH3Njoe62ezioNQS0qPfD11MH4w4paJuf kk", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1259178208", oauth_consumer_key="ABCDEFGHIJKLMNOPQRSTUVQXYZ", oauth_token="94ab03c4-ae2c-45e4-8732-0e6c4899db63", oauth_verifier="27871", oauth_signature="srWAOowk6Tk4irC9pEMUa7Tx%2BBc%3D", oauth_version="1.0" 26 OAuth Access Token Define OAuthSecret e OAuthParameters com os valores gerados pelo servidor dos recursos OAuthSecrets oAuthSecrets = new OAuthSecrets().consumerSecret(Definitions.CONSUMER_SECRET). tokenSecret(Definitions.getTokenSecret()); OAuthParameters oAuthParams = new OauthParameters().consumerKey(Definitions.CONSUMER_KEY). token(Definitions.getToken()).signatureMethod("HMAC-SHA1").version("1.0").verifier(verifier); RequestToken Setado no passo anterior client.addFilter(new OAuthClientFilter(client.getProviders(), oAuthParams, oAuthSecrets)); Código de verificação associado ao RequestToken Form response = client.resource(Definitions.ACCESS_TOKEN_URL).post(Form.class); Definitions.setToken(response.getFirst(OAuthParameters.TOKEN), response.getFirst(OAuthParameters.TOKEN_SECRET), true); Armazena os valores retornados (AccessToken e TokenSecret) return Response.seeOther(UriBuilder.fromResource(ShowResource.class).build()).build(); Retorna para Classe/método que ira acessar o recurso 27 OAuth - Acessar Recurso Define OAuthSecret e OAuthParameters com os valores gerados pelo servidor dos recursos Client client = Client.create(); OAuthSecrets oAuthSecrets = new OAuthSecrets().consumerSecret(Definitions.CONSUMER_SECRET) .tokenSecret(Definitions.getTokenSecret()); OAuthParameters oAuthParams = new OAuthParameters().consumerKey(Definitions.CONSUMER_KEY) .token(Definitions.getToken()).signatureMethod("HMAC-SHA1").version("1.0"); AccessToken armazenado no passo anterior client.addFilter(new OAuthClientFilter(client.getProviders(), oAuthParams, oAuthSecrets)); ClientResponse response = client.resource(SettingsBack.URL).get(ClientResponse.class); ClienteResponse com dados do recurso acessado Requisição Assina o request com assinatura OAuth Adiciona o Header “authorization” com os parâmetros OAuth Authorization: OAuth oauth_nonce="LpggMEZQYFkdTmrw0OixdZLMc6DdjNWDywsIULxVRwo", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1259182582", oauth_consumer_key="ABCDEFGHIJKLMNOPQRSTUVQXYZ", oauth_token="f862f658-ad89-4fcb-995b7a4c50554ff6", oauth_signature="udXNypHc%2BbaM0FP1xRdXeyKI2%2Fo%3D", oauth_version="1.0" 28 OAuth 29 OAuth Server – Gerar Tokens MultivaluedMap com informações adicionais sobre o consumidor Nome, URI, Descrição... DefaultOAuthProvider defaultOAuth = new DefaultOAuthProvider(); Consumer registerConsumer = defaultOAuth.registerConsumer("owner", attributes); String CONSUMER_KEY = registerConsumer.getKey(); String CONSUMER_SECRET = registerConsumer.getSecret(); Armazenar dados Relacionar CONSUMER_KEY a aplicação 30 OAuth Server – RequestToken @Path("/requestToken") Header com os public class RequestTokenResource { parametros OAuth @POST @Produces(MediaType.APPLICATION_FORM_URLENCODED) public javax.ws.rs.core.Response getHtml(@HeaderParam("authorization") String authorization) { MultivaluedMap<java.lang.String, java.lang.String> attributes; // obter do Header authorization "oauth_consumer_key" // Validar se Consumer_Key existe, validar hash Parâmetros para Indicar nível de acesso por exemplo. Read, ReadWrite Geração do RequestToken OAuthToken requestToken = defaultOAuth.newRequestToken(oauth_consumer_key, callbackUrl, attributes); String ret = OAuthParameters.TOKEN+"="+requestToken.getToken() +"&"+OAuthParameters.TOKEN_SECRET+"="+requestToken.getSecret(); return Response.ok(ret).build(); • Token e TokenSecret no corpo da resposta Autorizar acesso no serviço (Owner logado) 31 OAuth Server – AccessToken @Path("/accessToken") Header com os public class AccessTokenResource { parametros OAuth @POST @Produces(MediaType.APPLICATION_FORM_URLENCODED) public javax.ws.rs.core.Response getHtml(@HeaderParam("authorization") String authorization) { // obter do Header authorization “oauth_token” // Validar se Consumer_Key existe, validar hash Geração do AccessToken Verifier Para Callback URL OAuthToken accessToken = defaultOAuth.newAccessToken(oauth_token, defaultOAuth.authorizeToken(oauth_token, userPrincipal, roles)); Principal identificando o owner e informações adicionais sobre o consumer:URI, nome e descrição string ret = OAuthParameters.TOKEN+"="+accessToken.getToken() +"&"+OAuthParameters.TOKEN_SECRET+"="+accessToken.getSecret(); return Response.ok(ret).build(); Token e TokenSecret no corpo da resposta 32 Protegendo o recurso Validar tokens e assinaturas no recurso Acopla lógica de negócio com autorização Usar @ResourceFilters Define a lista de filtros associadas com o recurso ResourceFilters é um singleton Aplicável a classe ou método Filtros precisam implementar ResourceFilter @DELETE @Path("/book/{id}") @ResourceFilters(value = {OAuthAuthorizationRequiredFilter.class, OAuthAccessTokenRequiredFilter.class, OAuthNonceFilter.class}) public Response recursoProtegido {.....} 33 Filtro para o recurso public class OAuthAccessTokenRequiredFilter implements ResourceFilter { @Override public ContainerRequestFilter getRequestFilter() { return new ContainerRequestFilter() { public ContainerRequest filter(ContainerRequest cr) { HashMap<String, String> oauthValues = OauthHeaderHelper.extractOauthParamsFromAuthorizationHeader ( cr.getHeaderValue(′′Authorization′′)); if(!oauthValues.containsKey(′′oauth_token′′)) { throw new WebApplicationException( Response.status(Status.UNAUTHORIZED) . type(MediaType.TEXT_PLAIN) .entity(′′No oauth_token in request.′′).build()); } } return cr; } };} 34 OAuth 2 DRAFT - Abril 2010 Especificação final prevista para o final do ano OAuth Web Resource Authorization Protocol (WRAP) foi base Incompativel com OAuth 1.0 Torna obsoleta a especificação OAuth 1.0 Suporte parcial no Facebook e Twitter Facebook Graph API e Twitter com suporte parcial Processo simplificado sem RequestToken Sem assinatura OAuth SSL Sem Token Secret 35 OpenID Protocolo que possibilita o armazenamento de IDs ou credenciais (usuário e senha) em um repositório centralizado Compartilha com um ou mais consumidores Provider responsável por autenticar e informar consumidores Suportado por Google, Yahoo!, Flickr, Facebook, Verisign OpenID providers - Google, Yahoo e AOL OpenID Compartilhar uma identidade com diferentes consumidores OAuth Compartilhar dados (recursos), com vários usuários, sem compartilhar sua identidade Podem trabalhar em conjunto 36 OpenPTK Open Source User Provisioning Toolkit Gerenciamento de usuários com interface Web Services (REST e SOAP), Portlets, Taglibs e APIs Suporta vários repositórios de identidade LDAP Banco de Dados Autenticação e autorização na versão 2.0 (em desenvolvimento) Configuração em arquivos XML https://openptk.dev.java.net/ 37 OpenPTK 38 OpenPTK - Autorização 1 - Request Session/Principal:Principal com usuário Operation: CREATE, READ, UPDATE, DELETE, etc. Target ou Resource: URI a ser acessada 2 - Enforcer - ServletFilter que processa o Request 3 - Decider – Avalia o direito de acesso baseado nas políticas e retorna true ou false 4 – Policies – políticas de acesso utilizadas pelo Decider 39 OpenPTK - Configuração <Policy id="System" environment="ENGINE" mode="inbound" effect="allow"> <Properties> <Property name="policy.description" value="System user access"/> </Properties> <Session> <Types> <Type id="SYSTEM"/> </Types> </Session> <Targets> <Target id="contexts" uri="/resources/contexts/*"> <Operations> <Operation id="CREATE"/> <Operation id="READ"/> <Operation id="UPDATE"/> <Operation id="DELETE"/> <Operation id="SEARCH"/> </Operations> </Target> <Target id="engine" uri="/resources/engine/*"> <Operations> <Operation id="READ"/> </Operations> </Target> </Targets> </Policy> Habilita usuários SYSTEM a executar todas operações em contexts Habilita usuários SYSTEM a executar leitura em engine 40 Conclusão Frameworks e API's para recursos Web OAuth para autenticação OpenID para identificação na rede OAuth possibilita compartilhar dados (recursos), com vários usuários, sem compartilhar sua identidade Versão 1.0 disponível em APIs e serviços como FaceBook, Linkedin, Twitter Especifição OAuth 2.0 draft Facebook Graph API e Twitter com suporte parcial OpenPTK para provisionar usuários 41 Obrigado Perguntas??? 42 Palestra www.fabiovelloso.com.br/palestras/javaonebr2010.pdf Código exemplo www.fabiovelloso.com.br/palestras/rest-sec-j1br.zip Email [email protected] • Twitter @fabiovelloso 43 Sessões relacionadas Transforme seu processo em Rest com JAX-RS Horário: 14:00 - 14:45 Sala: Auditório 5 Segurança e insegurança em aplicações Internet Java EE Horário: 15:00 - 15:45 Sala: Auditório 4 Servlet 3.0 – Expansível, Assíncrono e Fácil de Usar Horário: 16:15 - 17:00 Sala: Auditório 1 44 45 OpenID 46