OAuth - Fabio Velloso

Propaganda
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
Download