“A API de login federado do Google, com base no protocolo OpenID 2.0, permite que os usuários façam login no seu site ou aplicativo da web com suas Contas do Google. Quando o Google autentica uma conta de usuário, ele retorna um ID de usuário para o seu aplicativo, o que permite que você colete e armazene informações do usuário. O Login federado também permite que você obtenha acesso a determinadas informações sobre a conta do usuário, com a aprovação dele.” http://code.google.com/intl/pt-BR/apis/accounts/
Então… Hands ON! Cabe lembrar que da mesma maneira que faremos para o google podemos fazer para qualquer site que seja um provedor OpenID, como Yahoo, Flickr dentre outros.
Segue uma imagem que tenta representar como ficará o fluxo dessa autenticação.
- O usuário entra na tela de login, seleciona o botão para fazer autenticação pelo google.
- É feito um direcionamento para autenticação pela página do google.
- Ao efetuar a autenticação ocorre o redirecionamento de volta para a página da aplicação.
1. SETUP
Baixe a biblioteca openid4java.
No eclipse crie um projeto Dynamic Web Project.
Fiz comentários quase que linha a linha em todo o código para facilitar o entendimento.
2. ResultType.java
Criei um Enum pra indicar se a autenticação teve sucesso, não sucesso ou se foi redirecionada.
package org.rodrigoramalho.openid.autenticacao;
public enum ResultType {
AUTH_SUCCESS, AUTH_FAILURE, REDIRECT_TO_OPENID_PROVIDER_FAILURE
}
2. Consumer.java
Éssa classe que será responsável pela autenticação utilizando o openid.
O método a seguir authRequest é o método responsável pela ação de quando o usuário clicar no botão de autenticação com o google, fazer o request OpenID e direcionar para a página de autenticação do google.
public ResultType authRequest(HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) throws IOException{
try{
// realm é a url da aplicação + porta ex: http://localhost:8080
String realm = getRealm(request);
// Definimos a url a qual o google deverá retornar após autenticar o usuário
String returnToUrl = new StringBuffer(realm).append(request.getContextPath()) + "/Auth";
// "descobre" o OpenID do fornecedor
List discoveries = manager.discover("https://www.google.com/accounts/o8/id");
// Tentativa de se conectar com o provedor OpenID
// e acessar um endpoint service pra se autenticar
DiscoveryInformation discovered = manager.associate(discoveries);
// Obtém a requisição de autorização que será mandada para o provedor OpenID
AuthRequest authReq = manager.authenticate(discovered, returnToUrl);
// Informa quais atributos deverão ser 'requeridos'
FetchRequest fetch = FetchRequest.createFetchRequest();
fetch.addAttribute("email", "http://axschema.org/contact/email", true);
fetch.addAttribute("firstName", "http://axschema.org/namePerson/first", true);
fetch.addAttribute("lastName", "http://axschema.org/namePerson/last", true);
authReq.addExtension(fetch);
authReq.setRealm(realm);
// coloca o objeto discovered na sessão do usuário
request.getSession().setAttribute("discovered", discovered);
request.getSession().setAttribute("checkResponse", true);
// Encaminha para a página de autenticação do google
response.sendRedirect(authReq.getDestinationUrl(true));
}
catch (OpenIDException e){
e.printStackTrace();
}
return ResultType.REDIRECT_TO_OPENID_PROVIDER_FAILURE;
}
Após fazer a autenticação pelo google, deve-se verificar se essa autenticação foi válida, para isso deve-se chamar o método verifyResponse
public ResultType verifyResponse(HttpServletRequest httpReq){
try{
// extrai os parametros que vem do HTTP request do OpenID provider.
ParameterList response = new ParameterList(httpReq.getParameterMap());
// Lembra que a gente colocou esse objeto na sessão?
DiscoveryInformation discovered = (DiscoveryInformation) httpReq.getSession().getAttribute("discovered");
// Extrai os parametros da url
StringBuffer receivingURL = httpReq.getRequestURL();
String queryString = httpReq.getQueryString();
if (queryString != null && queryString.length() > 0){
receivingURL.append("?").append(httpReq.getQueryString());
}
// Valida o response, verificar se o ConsumerManager é o mesmo que efetuou o request
VerificationResult verification = manager.verify(receivingURL.toString(), response, discovered);
// Analisa o resultado da verificação e extrai o identificador de verificação
Identifier verified = verification.getVerifiedId();
if (verified != null){
AuthSuccess authSuccess = (AuthSuccess) verification.getAuthResponse();
if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)){
// Extrai os atributos que fizemos a requisição (no fetchRequest)
FetchResponse fetchResp = (FetchResponse) authSuccess.getExtension(AxMessage.OPENID_NS_AX);
Map userAttributes = fetchResp.getAttributes();
User user = new User();
user.setEmail(userAttributes.get("email").toString());
String nome = userAttributes.get("firstName") + " "+ userAttributes.get("lastName");
user.setName(removeBrackets(nome));
// Coloca o usuário na sessão
httpReq.getSession().setAttribute("user", user);
}
return ResultType.AUTH_SUCCESS; // success
}
}catch (OpenIDException e){
e.printStackTrace();
}
httpReq.getSession().removeAttribute("checkResponse");
return ResultType.AUTH_FAILURE;
}
3. AuthServlet.java
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
if (request.getParameter("logout") != null) {
logoutUser(request, response);
}else{
Consumer consumer = new Consumer();
HttpSession session = request.getSession();
boolean checkResponse = session.getAttribute("checkResponse") != null ? true : false;
if (!checkResponse){
consumer.authRequest(request, response, getServletContext());
}else{
consumer.verifyResponse(request);
RequestDispatcher dispatcher = request.getRequestDispatcher("login.jsp");
dispatcher.forward(request, response);
}
}
} catch (ConsumerException e) {
e.printStackTrace();
}
}
4. login.jsp
<body>
<%@page import="org.rodrigoramalho.openid.beans.User"%>
<% User user = (User) request.getSession().getAttribute("user"); %>
<% if ( user == null){ %>
Sign in
<hr/>
<div><div id="login_por_terceiros">
<a href="Auth">
<div id="login_google"></div>
</a>
</div></div>
<% } else {%>
<p> Bem vindo <%= user.getName() %></p>
<p><a href="Auth?logout">Logout</a></p>
<%} %>
</body>
