현재 NodeJS 환경에서 caver-js를 이용해 민팅 사이트를 만들고있는데 프론트에서 카이카스를 이용해 유저인증을하고 컨트랙트와 통신하는 방법을 알지만 보안상의 이유로 백엔드에서 이러한 것을 처리하고싶은데 백엔드에서 caver-js를 사용할 경우 무조건 유저키가 필요한것으로 나오는데 이에대해 질문이 있습니다.
-
카이카스로 로그인한 정보를 그대로 백엔드로 넘기는 방법은 없나요?
아래 구문은 _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);
});
-
백엔드에서 유저에게 서명을 요구하고 컨트랙트에 트랜잭션을 보내는 것은 좋은 처리방법이 아닌가요?
안녕하세요
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! 으로 고치니까 바로 작동하네요… 이 부분은 문제가 있다고 생각합니다.