Conteúdo


Clientes de OAuth 2.0 em programação Java, Parte 2

concessão de credenciais do cliente

Comments

Conteúdos da série:

Esse conteúdo é a parte # de # na série: Clientes de OAuth 2.0 em programação Java, Parte 2

Fique ligado em conteúdos adicionais dessa série.

Esse conteúdo é parte da série:Clientes de OAuth 2.0 em programação Java, Parte 2

Fique ligado em conteúdos adicionais dessa série.

Visão geral

O OAuth é um padrão aberto para autorização que permite aos clientes obter acesso a recursos protegidos do servidor em nome do proprietário do recurso. O proprietário do recurso pode ser um cliente diferente ou o usuário final. O OAuth também ajuda os usuários finais a autorizar o acesso de terceiros aos seus recursos do servidor sem precisar compartilhar credenciais, como nome de usuário e senha. Esta série de artigos cumpre a estrutura de autorização do OAuth 2.0 descrita em RFC6749. A estrutura de autorização completa do OAuth 2.0, conforme descrita em RFC 6749, pode ser encontrada no website Engineering Task Force (consulte ).

A concessão de autorização

A concessão de autorização é uma credencial que representa a autorização do proprietário do recurso que pode ser usada para acessar um recurso protegido. Essa credencial é usada pelo cliente para obter um token de acesso, e esse token de acesso é, em algum momento, enviado junto com a solicitação para acessar um recurso protegido. O OAuth 2.0 define quatro tipos de concessões:

  1. Código de autorização
  2. Implícita
  3. Credenciais de senha do proprietário do recurso
  4. Credenciais do cliente

Esta série de artigos de quatro partes o conduz pela implementação de um cliente OAuth 2.0 em programação Java™ usando cada um dos tipos de concessão mencionados anteriormente. Nesta segunda parte, explico como implementar a concessão de credenciais do cliente. O artigo descreve essa concessão em detalhes e explica o código de amostra do cliente que pode ser usado para fazer interface com qualquer servidor em conformidade com OAuth 2.0 que tenha suporte para essa concessão. Até o fim do artigo, você deve ter um entendimento completo da implementação do cliente e estar pronto para fazer o download do código do cliente de amostra para seu próprio teste.

Concessão de credenciais do cliente

Nesta concessão, um cliente confidencial pode solicitar um token de acesso do servidor de autorização usando apenas suas credenciais de cliente (ou outros meios suportados de autenticação, como par de chave pública/privada). Presume-se que o cliente esteja solicitando acesso a recursos protegidos que estejam sob seu controle (o cliente é o proprietário do recurso).

O fluxo ilustrado em Figura 1 inclui as seguintes etapas:

(A) o cliente OAuth 2.0 autentica com o servidor de autorização usando suas credenciais de cliente e solicita o token de acesso do terminal do token

(B) O servidor de autorização autentica o cliente OAuth 2.0 e valida as credenciais do cliente. Se forem válidas, o servidor de autorização emite um token de acesso.

Figura 1. Fluxo de credenciais do cliente
Image showing the                     flow from the OAuth 2.0 client to the authorization server and back
Image showing the flow from the OAuth 2.0 client to the authorization server and back

Solicitação de token de acesso

A solicitação de token de acesso corresponde à Etapa A, como descrito em Figura 1.

O cliente faz uma solicitação para o terminal do token (servidor de autorização) com os seguintes parâmetros enviados usando o formato application/x-www-form-urlencoded .

  • grant_type: OBRIGATÓRIO. O valor deve ser definido para client_credentials"
  • client_id: OBRIGATÓRIO. ID do cliente.
  • client_secret: OBRIGATÓRIO. Segredo/senha do cliente.
  • scope: OPCIONAL. O escopo da solicitação de acesso

Uma vez que a autenticação do cliente está sendo usada como concessão de autorização, nenhuma autorização adicional será necessária. Por exemplo, o cliente faz a seguinte solicitação HTTP usando segurança de camada de transporte:

Lista 1. Solicitação HTTP do cliente
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=myApp&client_secret=ab32vr

Resposta do token de acesso

A resposta do token de acesso corresponde à etapa B, como descrito em Figura 1. Se a solicitação de token de acesso for válida e autorizada, o servidor de autorização retornará o token de acesso. Uma reposta de sucesso é mostrada na Lista 2.

Lista 2. Resposta do token de acesso
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
  "access_token":"2YotnFZFEjr1zCsicMWpAA",
  "token_type":"example",
  "expires_in":3600,
  "example_parameter":"example_value"
}

Se uma solicitação não for válida ou não for autorizada, o servidor de autorização retornará uma mensagem de erro adequada com código.

Setup

O cliente OAuth2.0 de amostra está disponível na Download section no arquivo OAuth2.0_client_credentials.zip. O código é organizado como um projeto Java, que pode ser importado para o ambiente Eclipse.

Pré-requisitos

Você precisará do IDE do Eclipse para desenvolvedores de Java EE para configurar o ambiente de desenvolvimento e importar o projeto anexado. Faça o download do Eclipse da página de download do Eclipse.

O projeto depende dos seguintes arquivos JAR:

  1. commons-codec-1.6.jar
  2. commons-logging-1.1.1.jar
  3. httpclient-4.2.5.jar
  4. httpclient-cache-4.2.5.jar
  5. httpcore-4.2.4.jar
  6. httpmime-4.2.5.jar
  7. json-simple-1.1.1.jar

Os arquivos JAR mencionados nos pontos 1 a 6 podem ser encontrados no arquivo JAR HttpComponents. Ele pode ser transferido por download do projeto Apache HTTP Component. O arquivo json-simple-1.1.1.jar pode ser transferido por download da página do projeto Simple JSON. Copie esses arquivos JAR para a pasta lib do projeto Java.

Código do cliente OAuth 2.0

O cliente OAuth 2.0 discutido aqui implementa a concessão de credenciais do cliente. Em partes subsequentes desta série de tutoriais, os tipos de concessão restantes serão discutidos e o código do cliente será atualizado.

Parâmetros de entrada

Os parâmetros de entrada para o cliente precisam ser fornecidos através do arquivo de propriedades Oauth2Client.config que está disponível na pasta de recursos do projeto.

  • scope: este é um parâmetro opcional. Ele representa o escopo da solicitação de acesso. O token de acesso retornado pelo servidor tem acesso a apenas os serviços mencionados no escopo.
  • grant_type: precisa ser definido para client_credentials representando a concessão de credenciais do cliente.
  • client_id: o ID do cliente ou do consumidor fornecido pelo servidor de recursos ao registrar o aplicativo com ele.
  • client_secret: o segredo do cliente ou do consumidor fornecido pelo servidor de recurso ao registrar o aplicativo com ele.
  • access_token: o token de acesso retornado pelo servidor de autorização em resposta a uma solicitação de token de acesso válido e autorizado. As suas credenciais de cliente são trocadas por um token de acesso como parte dessa solicitação.
  • authentication_server_url: representa o terminal do token. Todas as solicitações para concessão e nova geração de tokens de acesso precisam ser enviadas para essa URL.
  • resource_server_url: representa a URL do servidor de recurso que precisa ser contatado para acessar um recurso protegido enviando a ele o token de acesso no cabeçalho de autorização.

O código do cliente é mostrado em Lista 3.

Lista 3. Código-fonte do cliente
//Load the properties file
Properties config = OauthUtils.getClientConfigProps(OauthConstants.CONFIG_FILE_PATH);
		
//Generate the OAuthDetails bean from the config properties file
Oauth2Details oauthDetails = OauthUtils.createOauthDetails(config);
		
//Validate Input
if(!OauthUtils.isValidInput(oauthDetails)){
 System.out.println("Please provide valid config properties to continue.");
 System.exit(0);
}
		
//Determine operation
if(oauthDetails.isAccessTokenRequest()){
  //Generate new Access token
  String accessToken = OauthUtils.getAccessToken(oauthDetails);
   if(OauthUtils.isValid(accessToken)){
      System.out.println("Successfully generated Access token for client_credentials grant_type: "+accessToken);
   }
   else{
    System.out.println("Could not generate Access token for client_credentials grant_type");
   }
}
		
else {
                        //Access protected resource from server using OAuth2.0
 //Response from the resource server must be in Json or Urlencoded or xml
   System.out.println("Resource endpoint url: " + oauthDetails.getResourceServerUrl());
   System.out.println("Attempting to retrieve protected resource");
   OauthUtils.getProtectedResource(oauthDetails);
}

O código do cliente em Lista 3 lê os parâmetros de entrada fornecidos no arquivo Oauth2Client.config. Ele valida os valores para client_id, client_secret e authentication_server_url. Se a URL do servidor de recursos fornecida no arquivo de configuração for válida, o cliente tenta recuperar os recursos protegidos nessa URL. Caso contrário, o cliente apenas faz uma solicitação de token de acesso ao servidor de autorização e recupera o token de acesso. A seção a seguir explica o código responsável por recuperar o recurso protegido e o token de acesso.

Recurso protegido contra acesso

O código em Lista 4 demonstra como acessar um recurso protegido usando o token de acesso.

Lista 4. Recurso protegido contra acesso
String resourceURL = oauthDetails.getResourceServerUrl();
				
HttpGet get = new HttpGet(resourceURL);
get.addHeader(OAuthConstants.AUTHORIZATION,
 getAuthorizationHeaderForAccessToken(oauthDetails
  .getAccessToken()));
DefaultHttpClient client = new DefaultHttpClient();
HttpResponse response = null;
int code = -1;
	try {
	response = client.execute(get);
	code = response.getStatusLine().getStatusCode();
	if (code == 401) {
	 // Access token is invalid or expired. Regenerate the access
	 // token
	 System.out
	 .println("Access token is invalid or expired. Regenerating access 	  token....");
	 String accessToken = getAccessToken(oauthDetails);
	 if (isValid(accessToken)) {
	  // update the access token
	  // System.out.println("New access token: " + accessToken);
	   oauthDetails.setAccessToken(accessToken);
	   get.removeHeaders(OAuthConstants.AUTHORIZATION);
	   get.addHeader(OAuthConstants.AUTHORIZATION,
	   getAuthorizationHeaderForAccessToken(oauthDetails
	   .getAccessToken()));
	   get.releaseConnection();
	   response = client.execute(get);
	   code = response.getStatusLine().getStatusCode();
		if (code == 401) {
			throw new RuntimeException(
								"Could not access protected resource. Server returned http 			code: " + code);

		}

	  }
		else {
		 throw new RuntimeException(
		 Could not regenerate access token");
	       }

       }

		handleResponse(response);

Observações:

  • Esse método aceita o bean OauthDetails com os valores recuperados do arquivo de configuração.
  • Como o nome sugere, esse método tenta recuperar um recurso protegido do servidor de recursos. Assim, criamos um método HttpGet .
  • Para autenticar com o servidor de recurso, o token de acesso precisa ser enviado como parte do cabeçalho de autorização.

    Por exemplo: Authorization: Bearer accessTokenValue

  • Crie DefaultHttpClient para fazer a solicitação get ao servidor de recurso.
  • Se o código de resposta recebido do servidor de recurso for 401, o token de acesso usado para autenticação provavelmente expirou ou é inválido.
  • A próxima etapa é gerar o token de acesso novamente. (Consulte Lista 5.)
  • Depois de o token de acesso ser gerado novamente com sucesso, atualize o valor do token de acesso no bean OauthDetails . Substitua o cabeçalho de autorização existente no método get pelo novo valor do token de acesso.
  • Agora faça outra solicitação para acessar o recurso protegido.
  • Se o token de acesso for válido e a URL do servidor de recurso estiver correta, você deve poder ver os conteúdos da resposta no console.

Gerar novamente o token de acesso expirado

O código em Lista 5 manipula a regeneração de um token de acesso expirado.

Lista 5. Gerar novamente o token de acesso expirado
 HttpPost post = new HttpPost(
 oauthDetails.getAuthenticationServerUrl());
 String clientId = oauthDetails.getClientId();
 String clientSecret = oauthDetails.getClientSecret();
 String scope = oauthDetails.getScope();

 List<BasicNameValuePair> parametersBody =
 new ArrayList<BasicNameValuePair>();
 parametersBody.add(new BasicNameValuePair(OAuthConstants.GRANT_TYPE,
 oauthDetails.getGrantType()));
 parametersBody.add(new BasicNameValuePair(OAuthConstants.Client_ID,
 clientId));
 parametersBody.add(new BasicNameValuePair(OAuthConstants.Client_Secret,
 clientSecret));

 
 if (isValid(scope)) {
	parametersBody.add(new BasicNameValuePair
      (OAuthConstants.SCOPE,scope));
  }

 DefaultHttpClient client = new DefaultHttpClient();
 HttpResponse response = null;
 String accessToken = null;
   try {
	post.setEntity(new UrlEncodedFormEntity(parametersBody,
       HTTP.UTF_8));
	
	response = client.execute(post);
	int code = response.getStatusLine().getStatusCode();
	if (code == 401) {
	System.out.println("Authorization
       server expects Basic authentication");
	// Add Basic Authorization header
	post.addHeader(
	OAuthConstants.AUTHORIZATION,
	getBasicAuthorizationHeader(oauthDetails.clientId,
	clientSecret));
	System.out.println("Retry with client credentials");
	post.releaseConnection();
	response = client.execute(post);
	code = response.getStatusLine().getStatusCode();
	
	if (code == 401) {
	throw new RuntimeException(
	"Could not retrieve access token for client: "
	clientId);
	   }
        }
      }
	Map<String, String> map = handleResponse(response);
	accessToken = map.get(OAuthConstants.ACCESS_TOKEN);
	} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
	}

	return accessToken;

Observações:

  • Esse método gera uma solicitação HttpPost e atinge a URL do servidor de autenticação.
  • A solicitação Post envia client_id, client_secret e, opcionalmente, scope como parâmetros codificados de URL como parte da carga útil.
  • Conforme a estrutura de autorização OAuth 2.0, o cliente deve definir o cabeçalho de autorização com as credenciais do cliente ou qualquer outra credencial fornecida pelo servidor para autenticação ao fazer a solicitação do token de acesso. Mas isso está sujeito à implementação do servidor de autorização. O código do cliente faz a solicitação inicial sem adicionar o cabeçalho de autenticação básico. Se o servidor retornar uma resposta não autorizada, o cliente depois tenta autenticando com suas credenciais de cliente.
  • OAuth 2.0 determina a resposta do token de acesso a ser enviada no formato JSON. Mas, para fins de flexibilidade, incluí métodos utilitários para manipular uma resposta codificada em XML ou URL do servidor também.

Testando o cliente OAuth 2.0

Esta seção explica como configurar um terminal em conformidade com OAuth 2.0 e testar o cliente com relação a ele.

Testando o cliente com terminais

Esse cliente foi testado com sucesso com terminais IBM em conformidade com Twitter e OAuth 2.0, como o IBM® Websphere® Application Server e o IBM DataPower™.

Instruções para configurar um terminal OAuth 2.0 em um servidor de aplicativo Websphere podem ser encontradas em "Enabling the OAuth service provider in WebSphere ApplicationServer."

Executando o cliente

Agora que você configurou o servidor em conformidade com OAuth 2.0, está pronto para testar seu cliente e recuperar informações protegidas do servidor.

  • Importe o projeto Java anexado neste tutorial para sua área de trabalho Eclipse.
  • Faça o download e copie os arquivos JAR de dependência para a pasta a biblioteca do projeto.
  • Navegue para o arquivo resources/com/ibm/oauth/Oauth2Client.config e preencha os valores para a URL client_id, client_secret e authorization_server URL.
  • Abra o Oauth2Client.java e execute-o em Eclipse.

Saída do token de acesso

Você deve ver a saída na janela do console como mostra a Lista 6

Lista 6. Saída do token de acesso
Resource server URL is null. Will assume request is for generating Access token
Validated Input

********** Response Received **********
  expires_in = 3600
  token_type = bearer
  scope =
  access_token = mc20Tn3Br8raUvCrBEap3VYMbErGXshjiXYFAwEB
Successfully generated Access token for client_credentials grant_type: mc20Tn3Br8raUvCrBEap3VYMbErGXshjiXYFAwEB

Recuperando informações do usuário do servidor

Agora que você possui o token de acesso, é possível fazer uma solicitação para um aplicativo da web hospedado em um WebSphere Application Server que requer autenticação OAuth 2.0.

  • Atualize o arquivo Oauth2Client.confg com o token de acesso e preencha a propriedade da URL do servidor de recurso com a URL do servidor de recurso com relação a qual deseja testar.
  • Execute Oauth2Client.java novamente.

Você deve ver a saída na sua janela do console, como mostra Lista 7.

Lista 7. Recuperando informações do usuário
Resource endpoint url: https://localhost/protectedResource
Attempting to retrieve protected resource

********** Response Received **********
{
 "Author": "Varun Ojha",
 "Authenticatation": "Oauth2.0",
 "Result": "Success"
}

Como mostrado, é possível acessar o aplicativo da web realizando a autenticação usando OAuth 2.0. Depois de o token de acesso fornecido no arquivo de configuração expirar, o cliente gera novamente de modo automático o token de acesso na próxima solicitação e o utiliza para recuperar o recurso protegido disponível na URL do servidor de recurso.

Conclusão

Neste tutorial, você aprendeu os fundamentos das credenciais do cliente OAuth. O tutorial descreveu como um cliente OAuth 2.0 genérico em programação Java pode ser escrito para conectar-se a vários terminais em conformidade com OAuth 2.0 e recuperar recursos protegidos deles. O cliente de amostra foi anexado como um projeto Java para rapidamente permitir aos usuários importar o projeto para a área de trabalho Eclipse e começar a testar. Partes posteriores desta série de tutoriais abordarão os dois tipos restantes de concessão conforme descrito na estrutura de autorização do OAuth 2.0.


Recursos para download


Temas relacionados


Comentários

Acesse ou registre-se para adicionar e acompanhar os comentários.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java
ArticleID=995069
ArticleTitle=Clientes de OAuth 2.0 em programação Java, Parte 2: concessão de credenciais do cliente
publish-date=01162015