Autenticación Stellar
Esta guía está disponible en cuatro lenguajes de programación diferentes: Typescript, Kotlin, Flutter (Dart) y Swift. Puedes cambiar la versión mostrada en cada página mediante los botones de arriba.
Las billeteras se conectan a los anchors utilizando una forma estándar de autenticación a través de la red Stellar definida por el estándar SEP-10.
Esta guía cubrirá todas las formas de usar SEP-10 para autenticarte con un anchor.
Crear una clave de autenticación
Primero, vamos a crear una clave de autenticación. Aunque puedes usar la misma clave para autenticación y enviar fondos, se recomienda dividir las responsabilidades. En tu aplicación, tendrás una o más keypairs de fondos (keypairs para las cuentas que mantienen fondos e inician y reciben transacciones) y una clave de autenticación.
La clave de autenticación solo se utiliza para propósitos de autenticación y no necesita mantener fondos. Ten en cuenta que no necesitas crear una cuenta para este keypair tampoco.
Ve a Stellar Lab y genera un keypair. La clave secreta debe manejarse de manera segura, porque se utilizará para la autenticación.
Autenticación básica
Hagamos una autenticación básica. En este ejemplo, utilizaremos el SDK de billetera para crear un token de autenticación.
Primero, vamos a crear un objeto anchor
para trabajar con el anchor con el que te estás integrando. En este ejemplo, utilizaremos una implementación de anchor de referencia con el dominio principal testanchor.stellar.org
- TypeScript
const anchor = wallet.anchor({ homeDomain: "https://testanchor.stellar.org" });
A continuación, autentica con la authKey
creada anteriormente:
- TypeScript
const authKey = SigningKeypair.fromSecret("my secret key");
const sep10 = await anchor.sep10();
const authToken = await sep10.authenticate({ accountKp: authKey });
Para billeteras no custodiales, querrás usar la clave privada del usuario como authKey
.
Dominio de origen (Opcional)
El dominio de origen es el parámetro opcional para la autenticación SEP-10, cuando un único servidor de autenticación se comparte entre múltiples dominios. Algunos anclajes pueden requerir que proporciones este argumento. El SDK establece automáticamente el parámetro home_domain
en todas las solicitudes SEP-10.
Dominio del cliente (Opcional)
Algunos anclajes pueden requerir que el client_domain
siempre esté presente como parte de la solicitud, incluso para billeteras no custodiales.
El dominio del cliente es utilizado por los anclajes para verificar el origen de la solicitud del usuario (¿qué billetera está usando este usuario?). Esto es particularmente útil para los anclajes para integrarse con billeteras no custodiales.
Admitir client_domain
tiene dos partes, la implementación del cliente de la billetera y la implementación del servidor de la billetera. En esta configuración, tendremos una clave de autenticación adicional. Esta clave se almacenará de forma remota en el servidor. Usando el archivo de información SEP-1, el anclaje podrá consultar esta clave y verificar la firma. Así, el anclaje podrá confirmar que la solicitud proviene de tu billetera, perteneciente al client_domain
de la billetera.
Lado del Cliente
Primero, implementemos el lado del cliente. En este ejemplo nos conectaremos a un signatario remoto que firma transacciones en el punto final https://demo-wallet-server.stellar.org/sign
para el dominio del cliente demo-wallet-server.stellar.org
.
- TypeScript
const signer = new DomainSigner(
"https://demo-wallet-server.stellar.org/sign",
{},
);
const getAuthToken = async () => {
return anchor.sep10().authenticate({
accountKp,
walletSigner: signer,
clientDomain: "demo-wallet-server.stellar.org",
});
};
El punto final de firma de demo-wallet no está protegido para que cualquiera lo use. Tu URL de producción debe estar protegida, de lo contrario, cualquiera podría suplantar al usuario de tu billetera.
Agreguemos autenticación con un token de portador. Simplemente actualiza el transformador de solicitudes:
- TypeScript
const signer = new DomainSigner("https://demo-wallet-server.stellar.org/sign", {
Authorization: `Bearer ${authToken}`,
});
Finalmente, con el enfoque anterior definimos el firmante y el dominio del cliente por cada solicitud. Si deseas definirlo una vez y usarlo para cada llamada de autenticación que tu aplicación esté realizando, puedes hacerlo cambiando la configuración:
- TypeScript
const appCfg = new ApplicationConfiguration(
new DomainSigner("https://my-domain.com/sign", { ...headers }),
undefined,
"my-domain.com",
);
Esto es particularmente útil para integrar con múltiples anchors.
Lado del Servidor
A continuación, implementemos el lado del servidor.
Primero, genera una nueva clave de autenticación que se usará como clave de autenticación del client_domain
.
A continuación, crea un archivo toml SEP-1
colocado bajo <tu dominio>/.well-known/stellar.toml
con el siguiente contenido:
- TOML
ACCOUNTS = [ "Authentication public key (address)" ]
VERSION = "0.1.0"
SIGNING_KEY = "Authentication public key (address)"
NETWORK_PASSPHRASE = "Test SDF Network ; September 2015"
No olvides cambiar la frase secreta de la red para el despliegue en Mainnet.
Finalmente, agreguemos la implementación en el servidor. Esta implementación de ejemplo utiliza el framework express:
- JavaScript
app.post("/sign", (req, res) => {
const envelope_xdr = req.body.transaction;
const network_passphrase = req.body.network_passphrase;
const transaction = new Transaction(envelope_xdr, network_passphrase);
if (Number.parseInt(transaction.sequence, 10) !== 0) {
res.status(400);
res.send("transaction sequence value must be '0'");
return;
}
transaction.sign(Keypair.fromSecret(SERVER_SIGNING_KEY));
res.set("Access-Control-Allow-Origin", "*");
res.status(200);
res.send({
transaction: transaction.toEnvelope().toXDR("base64"),
network_passphrase: network_passphrase,
});
});
Puedes ver ejemplos de ambas implementaciones de billetera y servidor aquí. Como se mencionó antes, esta implementación de servidor de ejemplo no tiene ninguna protección contra solicitudes no autorizadas, así que debes agregar verificaciones de autorización como parte de la solicitud.