Kaikas로그인 정보를 백엔드로 넘기는 방법이 있나요?

현재 NodeJS 환경에서 caver-js를 이용해 민팅 사이트를 만들고있는데 프론트에서 카이카스를 이용해 유저인증을하고 컨트랙트와 통신하는 방법을 알지만 보안상의 이유로 백엔드에서 이러한 것을 처리하고싶은데 백엔드에서 caver-js를 사용할 경우 무조건 유저키가 필요한것으로 나오는데 이에대해 질문이 있습니다.

  1. 카이카스로 로그인한 정보를 그대로 백엔드로 넘기는 방법은 없나요?
    아래 구문은 _address로 유저의 주소를 받았습니다. addWhiteList 부분은 작동하지만 .send() 안쪽 from: _address 부분은 Error: Returned error: unknown account 뜨고 작동하지않습니다
    await contract.methods
    .addWhiteList(_address)
    .send({
    from: _address,
    gas: “200000”,
    })
    .then(function (result) {
    console.log(result);
    })

    .catch(function (error) {

    console.log(error);

    });

  2. 백엔드에서 유저에게 서명을 요구하고 컨트랙트에 트랜잭션을 보내는 것은 좋은 처리방법이 아닌가요?

안녕하세요

Caver를 이용해 클라이언트에서 SignedMessage 를 만들고 서버에서 보내 서버에서 검증하시면 됩니다.

아래 간단한 예제 추가했습니다.


Client

import Caver from 'caver-js';

async function bootstrap() {
  const caver = new Caver((window as any).klaytn);
  const [address] = await (window as any).klaytn.enable();
  const signedMessage = await caver.rpc.klay.sign(address, 'my message');

  const payload = await fetch('http://localhost:3001/verify', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      address,
      signedMessage,
    }),
  });

  console.log(await payload.json());

}

bootstrap();

Server

import Caver from 'caver-js';
import express from 'express';
import cors from 'cors';
import bodyParser from 'body-parser';

const caver = new Caver('https://public-node-api.klaytnapi.com/v1/baobab');

async function validateSignedMessage(message: string, signedMessage: string, address: string) {
  const v = '0x' + signedMessage.substring(2).substring(128, 130);
  const r = '0x' + signedMessage.substring(2).substring(0, 64);
  const s = '0x' + signedMessage.substring(2).substring(64, 128);
  return await caver.validator.validateSignedMessage(
    message,
    [v, r, s],
    address,
    false,
  );
}

const app = express();

app.use(cors());
app.use(bodyParser());

app.post('/verify', async (req, res) => {
  const { address, signedMessage } = req.body;

  const isValid = await validateSignedMessage('my message', signedMessage, address);

  res.json({
    isValid,
  });
});

app.listen(3001, () => {
  console.log('Example app listening on port 3001');
});
2 Likes

위와 같이 작성했는데 결과값으로 계속해서 false가 나옵니다.

안녕하세요

서버, 클라이언트 코드, 의존성 버전도 함께 공유해주시면

자세하게 답변 드리도록 하겠습니다.

2 Likes


다음과 같은 방식으로 프론트에서 signature와 지갑 address를 백엔드로 보내면

const isValid = await caver.validator.validateSignedMessage(
        hash,
        caver.utils.decodeSignature(signature),
        address,
        false,
      );

위와 같은 방식으로 검증을 진행하고 있는데 올바른 값을 보내도 계속 false만 나오네요…

의존성 버전은 ^1.8.1 사용하고 있습니다.

아래와같이 클라이언트에서 바로 validate하여 정상적으로 작동하는것을 확인했습니다.

async function bootstrap() {
  const caver = new Caver((window as any).klaytn);
  const [address] = await (window as any).klaytn.enable();

  const signedMessage = await caver.rpc.klay.sign(address, 'my message');
  const isValid = await caver.validator.validateSignedMessage('my message', caver.utils.decodeSignature(signedMessage), address);

  console.log(isValid);
}

bootstrap();

혹시 sign 하는 메시지에 한국어를 지원하지 않나요? 혹시 몰라서 한국어로 썻던 메시지를 Welcome! 으로 고치니까 바로 작동하네요… 이 부분은 문제가 있다고 생각합니다.