Advertencia: Esta página trata sobre las API anteriores de Google, las API de datos de Google, y solo es relevante para las API que aparecen en el directorio de las API de datos de Google, muchas de las cuales se reemplazaron con API más nuevas. Para obtener información sobre una API nueva específica, consulta la documentación de la API nueva. Para obtener información sobre cómo autorizar solicitudes con una API más reciente, consulta Autenticación y autorización de cuentas de Google.
En este documento, se describe cómo usar las bibliotecas cliente de la API de datos de Google a fin de conectarse a la Autenticación de AuthSub para aplicaciones web de Google.
La interfaz de AuthSub permite que una aplicación basada en la Web acceda a un servicio de Google en nombre de un usuario. Para mantener un alto nivel de seguridad, la interfaz AuthSub permite que la aplicación obtenga un token de autenticación sin necesidad de manejar la información de acceso de la cuenta del usuario.
Las bibliotecas cliente de la API de datos de Google proporcionan métodos para ayudarte a usar AuthSub en tu aplicación web. Específicamente, existen métodos para construir la URL de la solicitud, obtener un token de autenticación de un solo uso, intercambiar el token de un solo uso por un token de sesión y firmar la solicitud.
Nota: La biblioteca cliente de JavaScript tiene su propio tipo de AuthSub, llamado AuthSubJS. Para obtener información sobre cómo utilizar AuthSubJS en tus aplicaciones de JavaScript, consulta Cómo utilizar la autenticación "AuthSub" con la biblioteca cliente de JavaScript.
Público
Este documento está destinado a programadores que desean que sus aplicaciones basadas en la Web accedan a los servicios de Google en nombre de los usuarios mediante las bibliotecas cliente de las API de datos de Google.
En este documento, se supone que estás familiarizado con la interfaz de AuthSub y con el proceso general para incorporar AuthSub a tu aplicación web. Si quieres obtener una descripción completa del protocolo de AuthSub, consulta Autenticación de AuthSub para aplicaciones web.
Usa AuthSub y las API de datos de Google sin las bibliotecas cliente
Si deseas que tu cliente de aplicación web interactúe con un servicio de datos de Google usando AuthSub como sistema de autenticación, todo lo que necesitas saber es en Autenticación de AuthSub para aplicaciones web. Si no lo desea, no es necesario que use las bibliotecas cliente de las API de datos de Google.
A continuación, se describe el modo en que tu aplicación puede autenticar a un usuario con AuthSub:
Tu aplicación construye la URL de AuthSub adecuada y luego envía al usuario a esa URL para que pueda acceder; el sistema de AuthSub envía al usuario de vuelta a la URL en el sitio que especificaste y muestra un token de uso único; tu aplicación cambia de manera opcional ese token por un token de sesión; luego tu aplicación envía el token en el encabezado de autorización con cada solicitud que la aplicación envía al servicio.
Las bibliotecas cliente de las API de datos de Google simplifican este proceso de autorización, ya que manejan varios detalles por ti. En este documento, se explica cómo hacerlo.
Cómo trabajar con AuthSub y las API de datos de Google: ejemplos de biblioteca cliente
En esta sección, se muestra un ejemplo del uso de los métodos de la biblioteca cliente de las API de datos de Google para seguir los pasos descritos en la sección "Trabaja con AuthSub" de la documentación de AuthSub.
En este ejemplo, integramos la interfaz de AuthSub a una aplicación web que interactúa con Calendario de Google (aunque no necesitas saber nada sobre Calendario de Google para seguir el ejemplo). En el ejemplo, se supone que la aplicación web está alojada en example.com
.
Decide qué tipo de token usar (session=0
o session=1
).
Puedes elegir usar tokens de uso único (session=0
) o tokens de sesión (session=1
). En este documento, se usarán tokens de sesión, ya que son más útiles en las aplicaciones que realizan varias solicitudes a la API.
Como se explica en la documentación de AuthSub, si decides usar tokens de sesión en tu aplicación web, deberás administrar el almacenamiento de tokens tú mismo. Este documento no cubre la administración de tokens. Además, ten en cuenta que los tokens solicitados con session=0
no se pueden intercambiar (actualizar) más tarde por un token de sesión de larga duración.
Decida si desea registrar su aplicación web (secure=0
o secure=1
)
AuthSub se puede usar en tres modos diferentes: sin registrar, registrado y registrado con seguridad encantada. En el resto de este documento, se hará referencia a la última opción como AuthSub seguro. Aunque el modo no registrado o registrado es más sencillo de configurar que AuthSub seguro, Google te recomienda usar tokens seguros para su seguridad encantada.
Cómo registrarse
Si eliges Registro para aplicaciones basadas en la Web, tendrás los siguientes beneficios:
- Un nivel de seguridad más alto.
- Ser de confianza de Google (no se muestra ninguna advertencia al usuario en la página de autorización de Google)
AuthSub registrada y segura
Si decides usar AuthSub seguro, deberás crear una clave privada RSA y un par de certificados públicos autofirmados, además de registrar tu aplicación web. Consulta Generar claves y certificados para usarlos con el modo registrado (a continuación) a fin de obtener ejemplos de la creación de certificados X.509.
Determine el alcance de su acceso a los datos
Cada servicio de Google define un valor de scope
que determina (y posiblemente reduce) el acceso de un token a los datos del usuario.
Consulta las Preguntas frecuentes para ver la lista de valores scope
disponibles.
Como decidimos interactuar con la API del Calendario de Google, el scope
debería ser http://www.google.com/calendar/feeds/
.
Nota: Siempre debes establecer el valor de alcance en la URL más amplia posible, a menos que necesites una restricción más precisa.
Por ejemplo, un alcance más limitado, como scope=http://www.google.com/calendar/feeds/default/allcalendars/full
, restringirá el acceso del token solo a todos los calendarios o el feed completo. Si usas scope=http://www.google.com/calendar/feeds/
, se permitirá el acceso a todos los feeds de Calendario: http://www.google.com/calendar/feeds/*.
Tokens de alcance múltiple
Para crear tokens que accedan a varias API de datos de Google, separe cada alcance con un espacio codificado en URL. En el siguiente ejemplo, se crea un token que tendrá acceso a los datos de Contactos de Google y Calendario de Google de un usuario.
scope=http://www.google.com/calendar/feeds/%20http://www.google.com/m8/feeds/
Solicita un token de autenticación de un solo uso
A fin de adquirir un token de AuthSub para un usuario y servicio determinados, tu aplicación debe redireccionar al usuario a la URL AuthSubRequest
, que le solicita que acceda a su Cuenta de Google.
(Para obtener más información sobre la URL AuthSubRequest
, consulta la Autenticación de AuthSub para aplicaciones web completa).
A fin de construir la URL AuthSubRequest
en tu aplicación, usa lo siguiente para cada biblioteca cliente:
Java
import com.google.gdata.client.*; String nextUrl = "http://www.example.com/RetrieveToken.jsp"; String scope = "http://www.google.com/calendar/feeds/"; boolean secure = false; // set secure=true to request secure AuthSub tokens boolean session = true; String authSubUrl = AuthSubUtil.getRequestUrl(nextUrl, scope, secure, session);
Si deseas autenticar a los usuarios de tu dominio de G Suite, haz lo siguiente:
import com.google.gdata.client.*; String hostedDomain = "example.com"; String nextUrl = "http://www.example.com/RetrieveToken.jsp"; String scope = "http://www.google.com/calendar/feeds/"; boolean secure = false; // set secure=true to request AuthSub tokens boolean session = true; String authSubUrl = AuthSubUtil.getRequestUrl(hostedDomain, nextUrl, scope, secure, session);
.NET
using Google.GData.Client; String nextUrl = "http://www.example.com/RetrieveToken.aspx"; String scope = "http://www.google.com/calendar/feeds/"; bool secure = false; // set secure=true to request secure AuthSub tokens bool session = true; String authSubUrl = AuthSubUtil.getRequestUrl(nextUrl, scope, secure, session);
Si deseas autenticar a los usuarios de tu dominio de G Suite, haz lo siguiente:
using Google.GData.Client; String hostedDomain = "example.com"; String nextUrl = "http://www.example.com/RetrieveToken.aspx"; String scope = "http://www.google.com/calendar/feeds/"; bool secure = false; // set secure=true to request secure AuthSub tokens bool session = true; String authSubUrl = AuthSubUtil.getRequestUrl(hostedDomain, nextUrl, scope, secure, session);
PHP
require_once 'Zend/Loader.php'; Zend_Loader::loadClass('Zend_Gdata_AuthSub'); $nextUrl = 'http://www.example.com/RetrieveToken.php'; $scope = 'http://www.google.com/calendar/feeds/'; $secure = 0; // set $secure=1 to request secure AuthSub tokens $session = 1; $authSubUrl = Zend_Gdata_AuthSub::getAuthSubTokenUri($nextUrl, $scope, $secure, $session);
Si deseas autenticar a los usuarios de tu dominio de G Suite, haz lo siguiente:
require_once 'Zend/Loader.php'; Zend_Loader::loadClass('Zend_Gdata_AuthSub'); $hostedDomain = 'example.com'; $nextUrl = 'http://www.example.com/RetrieveToken.php'; $scope = 'http://www.google.com/calendar/feeds/'; $secure = 0; // set $secure=1 to request secure AuthSub tokens $session = 1; $authSubUrl = Zend_Gdata_AuthSub::getAuthSubTokenUri($nextUrl, $scope, $secure, $session) . '&hd=' . $hostedDomain;
Python
import gdata.auth next = 'http://www.example.com/RetrieveToken.pyc' scope = 'http://www.google.com/calendar/feeds/' secure = False # set secure=True to request secure AuthSub tokens session = True auth_sub_url = gdata.auth.GenerateAuthSubRequestUrl(next, scope, secure=secure, session=session)
Si deseas autenticar a los usuarios de tu dominio de G Suite, haz lo siguiente:
import gdata.auth hosted_domain = 'example.com' next = 'http://www.example.com/RetrieveToken.pyc' scope = 'http://www.google.com/calendar/feeds/' secure = False # set secure=True to request secure AuthSub tokens session = True auth_sub_url = gdata.auth.GenerateAuthSubRequestUrl(next, scope, secure=secure, session=session, domain=hosted_domain)
Después de construir la URL "next", la aplicación puede usarla de varias maneras para enviar al usuario al controlador AuthSubRequest
. El enfoque más común es mostrar una página que le indique al usuario que debe seguir un vínculo para autorizar a tu aplicación a acceder a su cuenta de Google y que luego adjunte la URL de la solicitud al vínculo. Por ejemplo, podrías generar la siguiente string en tu aplicación web:
String authorizationUrl = "<p>MyApp needs access to your Google Calendar account to read your Calendar feed. " + "To authorize MyApp to access your account, <a href=\"" + authSubUrl + "\">log in to your account</a>.</p>";
El usuario sigue el vínculo a la página de AuthSub en Google y accede. El sistema AuthSub luego redirecciona al usuario de vuelta a tu aplicación usando la URL "siguiente" que proporcionaste.
Extrae el token de un solo uso
Cuando Google redirecciona a su aplicación, el token se agrega a la URL "next" como parámetro de consulta. En el caso de los ejemplos anteriores, después de que el usuario accede, Google redirecciona a una URL como http://www.example.com/RetrieveToken?token=DQAADKEDE
.
Tu aplicación debe extraer el valor del token de su parámetro de consulta de URL.
Si tu aplicación configura una cookie de autenticación en el navegador del usuario antes de enviarlo al sistema de AuthSub, cuando Google redireccione a la URL "siguiente", la aplicación podrá leer la cookie de autenticación para reconocer qué usuario llegó a esa URL. Puedes usar esa cookie para asociar un ID de usuario en tu aplicación con el token de AuthSub recuperado de Google.
Las bibliotecas cliente proporcionan métodos convenientes para extraer el token de un solo uso:
Java
String singleUseToken = AuthSubUtil.getTokenFromReply(httpServletRequest.getQueryString());
.NET
String singleUseToken = Request.QueryString["token"]; // or String singleUseToken = AuthSubUtil.getTokenFromReply(new Uri(Request.QueryString));
PHP
$singleUseToken = $_GET['token'];
Python
current_url = 'http://' + req.hostname + req.unparsed_uri # Unlike the other calls, extract_auth_sub_token_from_url() will create anAuthSubToken
orSecureAuthSubToken
object. # Use str(single_use_token) to return the token's string value. single_use_token = gdata.auth.extract_auth_sub_token_from_url(current_url)
Si usas AuthSub seguro, asegúrate de establecer tu clave privada RSA para que se cree un SecureAuthSubToken
:
f = open('/path/to/yourRSAPrivateKey.pem') rsa_key = f.read() f.close() current_url = 'http://' + req.hostname + req.unparsed_uri # Unlike the other calls, extract_auth_sub_token_from_url() will create anAuthSubToken
orSecureAuthSubToken
object. # Use str(single_use_token) to return the token's string value. single_use_token = gdata.auth.extract_auth_sub_token_from_url(current_url, rsa_key=rsa_key)
Solicita un token de sesión
El token que recuperas de la URL siempre es un token de un solo uso. El siguiente paso es actualizar ese token para un token de sesión de larga duración mediante la URL AuthSubSessionToken
, como se describe en la documentación completa de Autenticación de AuthSub para aplicaciones web. Si usas AuthSub seguro, deberás configurar tu clave privada RSA antes de hacer el intercambio. A continuación, se incluyen algunos ejemplos que usan cada una de las bibliotecas cliente:
Java
import com.google.gdata.client.*; import com.google.gdata.client.calendar.*; String sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, null); CalendarService calendarService = new CalendarService("google-ExampleApp-v1.0"); calendarService.setAuthSubToken(sessionToken, null); // ready to interact with Calendar feeds
Para usar AuthSub seguro, pasa tu clave privada RSA a exchangeForSessionToken
en lugar de pegar null
:
import com.google.gdata.client.*; import com.google.gdata.client.calendar.*; java.security.PrivateKey privateKey = AuthSubUtil.getPrivateKeyFromKeystore("AuthSubExample.jks", "privKeyPa$$word", "AuthSubExample", "privKeyPa$$word"); String sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, privateKey); CalendarService calendarService = new CalendarService("google-ExampleApp-v1.0"); calendarService.setAuthSubToken(sessionToken, privateKey); // ready to interact with Calendar feeds
.NET
using Google.GData.Client; using Google.GData.Calendar; String sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, null).ToString(); GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "google-ExampleApp-v1.0"); authFactory.Token = (String) sessionToken; CalendarService calendarService = new CalendarService(authFactory.ApplicationName); calendarService.RequestFactory = authFactory; // ready to interact with Calendar feeds
Para usar AuthSub seguro, pasa tu clave privada RSA a exchangeForSessionToken
en lugar de pegar null
:
using Google.GData.Client; using Google.GData.Calendar; protected AsymmetricAlgorithm getRsaKey() { X509Certificate2 cert = new X509Certificate2("C:/MyAspSite/test_cert.pfx", "privKeyPa$$word"); RSACryptoServiceProvider privateKey = cert.PrivateKey as RSACryptoServiceProvider; return privateKey; } AsymmetricAlgorithm rsaKey = getRsaKey(); String sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, rsaKey).ToString(); GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "google-ExampleApp-v1.0"); authFactory.Token = (String) sessionToken; authFactory.PrivateKey = rsaKey; CalendarService calendarService = new CalendarService(authFactory.ApplicationName); calendarService.RequestFactory = authFactory; // ready to interact with Calendar feeds
PHP
require_once 'Zend/Loader.php'; Zend_Loader::loadClass('Zend_Gdata_AuthSub'); Zend_Loader::loadClass('Zend_Gdata_Calendar'); $sessionToken = Zend_Gdata_AuthSub::getAuthSubSessionToken($singleUseToken); // Create a Calendar service object and set the session token for subsequent requests $calendarService = new Zend_Gdata_Calendar(null, 'google-ExampleApp-v1.0'); $calendarService->setAuthSubToken($sessionToken); // ready to interact with Calendar feeds
Para AuthSub seguro, el intercambio requiere que primero configures una Zend_Gdata_HttpClient
y establezcas tu clave privada RSA con setAuthSubPrivateKeyFile()
:
require_once 'Zend/Loader.php'; Zend_Loader::loadClass('Zend_Gdata_AuthSub'); Zend_Loader::loadClass('Zend_Gdata_Calendar'); $client = new Zend_Gdata_HttpClient(); $client->setAuthSubPrivateKeyFile('/path/to/myrsakey.pem', null, true); $sessionToken = Zend_Gdata_AuthSub::getAuthSubSessionToken($singleUseToken, $client); $calendarService = new Zend_Gdata_Calendar($client, 'google-ExampleApp-v1.0'); $calendarService->setAuthSubToken($sessionToken); // ready to interact with Calendar feeds
Python
import gdata.calendar import gdata.calendar.service calendar_service = gdata.calendar.service.CalendarService() calendar_service.UpgradeToSessionToken(single_use_token) # calls gdata.service.SetAuthSubToken() for you # ready to interact with Calendar feeds
Nota: El proceso es el mismo para la autenticación segura de AuthSub, siempre que hayas usado gdata.auth.extract_auth_sub_token_from_url(url, rsa_key=rsa_key)
a fin de extraer el token de uso único.
Nota: Cuando usas AuthSub seguro, tu clave privada no se envía a través de la red. Las bibliotecas cliente envían la firma única generada mediante la firma de la solicitud con tu clave, no la clave en sí.
Usa el token de sesión
Puedes usar el token de sesión para autenticar las solicitudes al servidor; para ello, coloca el token en el encabezado de autorización, como se describe en la documentación de AuthSub.
Después de configurar el token de sesión, puedes usar las llamadas a la biblioteca cliente estándar de las API de datos de Google para interactuar con el servicio, sin tener que pensar en el token. Para obtener más información, consulta la documentación de la biblioteca cliente y la guía para desarrolladores de las API de datos de Google para el servicio y el lenguaje con los que interactúas.
Recupera información sobre un token de sesión
Si quieres probar que el cliente y el servidor acepten los parámetros del token, puedes pasar el token al controlador AuthSubTokenInfo
, que muestra un conjunto de pares nombre-valor que contienen información sobre el token.
Java
Map<String, String> tokenInfo = AuthSubUtil.getTokenInfo(sessionToken, null);
Si usas AuthSub seguro, pasa tu clave privada RSA:
Map<String, String> tokenInfo = AuthSubUtil.getTokenInfo(sessionToken, privateKey);
.NET
Dictionary<String, String> tokenInfo = AuthSubUtil.GetTokenInfo(sessionToken, null);
Si usas AuthSub seguro, pasa tu clave privada RSA:
Dictionary<String, String> tokenInfo = AuthSubUtil.GetTokenInfo(sessionToken, privateKey);
PHP
$tokenInfo = Zend_Gdata_AuthSub::getAuthSubTokenInfo($sessionToken);
Si usas AuthSub seguro, pasa tu Zend_Gdata_HttpClient
para que la solicitud se firme con tu clave privada RSA:
$tokenInfo = Zend_Gdata_AuthSub::getAuthSubTokenInfo($sessionToken, $client);
Python
token_info = calendar_service.AuthSubTokenInfo()
Revocar un token de sesión
Los tokens de sesión de AuthSub no vencen; tu cliente puede almacenar el token de sesión durante el tiempo que sea necesario.
Por lo tanto, cuando el cliente termine de usar el token de sesión, podrá revocarlo con el controlador AuthSubRevokeToken
, como se describe en la documentación de AuthSub.
Por ejemplo, si desea administrar tokens de manera similar a una sesión tradicional, su cliente puede obtener un token al comienzo de la sesión de un usuario y revocarlo al final de la sesión.
Para revocar un token, usa lo siguiente en cada biblioteca cliente:
Java
AuthSubUtil.revokeToken(sessionToken, null);
Si usas AuthSub seguro, pasa tu clave privada RSA:
AuthSubUtil.revokeToken(sessionToken, privateKey);
.NET
AuthSubUtil.revokeToken(sessionToken, null);
Si usas AuthSub seguro, pasa tu clave privada RSA:
AuthSubUtil.revokeToken(sessionToken, privateKey);
PHP
$wasRevoked = Zend_Gdata_AuthSub::AuthSubRevokeToken($sessionToken);
Si usas AuthSub seguro, pasa tu Zend_Gdata_HttpClient
para que la solicitud se firme con tu clave privada RSA:
$wasRevoked = Zend_Gdata_AuthSub::AuthSubRevokeToken($sessionToken, $client);
Python
calendar_service.RevokeAuthSubToken()
Recursos y muestras adicionales
- Ejemplos de AuthSub en el blog de sugerencias de la API de datos de Google
- Ejemplo de AuthSub de la biblioteca cliente de Python
- Ejemplo de AuthSub de la biblioteca cliente de Java
- Artículo: Usa AuthSub con la biblioteca cliente de .NET.
- Artículo: Cómo usar la autenticación "AuthSub" con la biblioteca cliente de JavaScript
Genera una clave privada autofirmada y un certificado público para usar con AuthSub seguro
La clave privada se usa para generar una firma, que debe incluirse en cada solicitud. Google utiliza la clave pública incorporada en el certificado para verificar la firma. La clave pública debe ser una clave RSA de 1,024 bits codificada en un certificado X.509 en formato PEM. El certificado debe enviarse a Google en el momento del registro.
En las siguientes secciones, se proporcionan ejemplos de cómo generar claves y certificados con dos herramientas en particular: la utilidad OpenSSL
y la utilidad keytool
de Java.
Estos ejemplos no son específicos para las API de datos de Google; puedes usar las mismas utilidades para generar claves con cualquier propósito.
En los ejemplos, se supone que su empresa se llama My_Company y se encuentra en Mountain View, California, EE.UU., con el nombre de dominio example.com.
Genera claves con OpenSSL
Para crear un par de claves RSA y el certificado correspondiente, puedes usar el siguiente comando:
# Generate the RSA keys and certificate openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj \ '/C=US/ST=CA/L=Mountain View/CN=www.example.com' -keyout \ myrsakey.pem -out /tmp/myrsacert.pem
Advertencia: Incluir el parámetro -nodes
crea una clave privada sin una contraseña para protegerla.
Sin embargo, deberías considerar omitir este parámetro para mayor seguridad.
El parámetro -sha1
especifica que la clave se usará para generar firmas SHA1.
El parámetro -subj
especifica la identidad de la aplicación que representa el certificado.
El parámetro -keyout
especifica el archivo que contendrá las claves.
Este archivo contiene información sensible y debe protegerse y no compartirse con nadie.
El parámetro -out
especifica el archivo que contendrá el certificado en formato PEM (que se puede enviar a Google durante el registro).
Genera claves para el cliente .NET
El marco de trabajo .NET no comprende las claves ni los certificados almacenados en formato PEM. Por lo tanto, se debe realizar un paso adicional después de crear el archivo .pem:
openssl pkcs12 -export -in test_cert.pem -inkey myrsacert.pem -out myrsacert.pfx -name "Testing Certificate"
Este paso genera un archivo PFX desde tu clave privada y certificado. Este archivo se puede importar a la biblioteca cliente de .NET para firmar de forma digital las solicitudes realizadas a las API de datos de Google.
Genera claves para el cliente de Java
El cliente Java acepta claves privadas en formato PKCS#8. Después de generar una clave o un certificado con las instrucciones anteriores, crea un archivo .pk8 a partir de tu archivo .pem generado:
openssl pkcs8 -in myrsakey.pem -topk8 -nocrypt -out myrsakey.pk8
Como alternativa, puedes usar el almacén de claves de Java y la utilidad de keytool para crear un par de claves RSA y el certificado correspondiente. Usa el siguiente comando:
# Generate the RSA keys and certificate keytool -genkey -v -alias Example -keystore ./Example.jks\ -keyalg RSA -sigalg SHA1withRSA\ -dname "CN=www.example.com, OU=Engineering, O=My_Company, L=Mountain View, ST=CA, C=US"\ -storepass changeme -keypass changeme
Advertencia: "changeme
" no es una contraseña segura, es solo un ejemplo.
El parámetro -dname
especifica la identidad de la aplicación que representa el certificado. El parámetro -storepass
especifica la contraseña para proteger el almacén de claves. El parámetro -keypass
especifica la contraseña para proteger la clave privada.
Para escribir el certificado en un archivo que pueda usarse en la herramienta ManageDomains, use el siguiente comando:
# Output the public certificate to a file keytool -export -rfc -keystore ./Example.jks -storepass changeme \ -alias Example -file mycert.pem