지난 강좌
스팀커넥트2 강좌 :: 개발환경 설정, 스팀 아이디로 로그인하기 버튼 만들기
지난시간에 만든 로그인 버튼을 누르면 steemconnect.com 으로 가서 퍼미션을 확인합니다.
무슨무슨 퍼미션을 허용할 지는 sc2.Initialize 에서 scope 배열에 설정합니다.
['login', 'offline', 'vote', 'comment', 'comment_delete', 'comment_options', 'custom_json', 'claim_reward_balance']
각 scope 의 의미는 링크 참조.
https://github.com/steemit/steemconnect/wiki/OAuth-2#scopes
스팀커넥트에서 로그인 디테일을 입력하고 나면 아래와같은 형식의 URL 로 돌아옵니다.
http://localhost:8080/?access_token=eyJhbGciOiJIUzI1NiIs1nR5cCI6IkpXVCJ9.eyJyb2xlIjoiYXBaIiwicHJveHkiOiJzYzJ0dxqiLCJ1c2VyIjoibW9ybmloZyIsInNjb3BiijpbxnGgdGUiLCJjb21txW50Il0sImlhdCI6MTUxNzk2MDU1NiwiBXhwIjoxNTE4NTY1MzU2fQ.1GJx2WHNL3DJ4f6RB3vS3i3t-3BZ3HrKcZJoM_hi0aI&expires_in=604800&username=morning
URL 파라미터에 있는 3가지
access_token
입력한 스팀 아이디와 비밀번호로 로그인에 성공했다는 증표 토큰입니다. 이것이 있어야 보팅, 포스팅 등의 API call 이 성공할 수 있습니다.
expires_in
access_token이 만료되기 까지의 초단위 숫자 입니다.
username
로그인 된 스팀 아이디 입니다.
이제 웹페이지가 로드 될 때, 보통의 로딩인지 OAuth 에서 redirect 되는 로딩인지 구분해서 처리해야 합니다.
URL 파라미터에 access_token 이 있는지를 가지고 구분합니다.
우선 함수하나 정의해놓고
function getParameter(paramName) {
var searchString = window.location.search.substring(1);
var params = searchString.split('&');
var i, val;
for (i = 0; i < params.length; i++) {
val = params[i].split('=');
if (val[0] == paramName) {
return val[1];
}
}
return null;
}
파라미터에 access_token 이 있을 경우 로컬 스토리지에 저장하고 다시 access_token 파라미터 없이 리프레쉬 합니다.
if (getParameter('access_token') !== null) {
// access_token 파라미터가 있는 경우
localStorage.setItem('access_token', getParameter('access_token'));
localStorage.setItem('expires_in', getParameter('expires_in'));
localStorage.setItem('auth_timestamp', Math.round(Date.now()/1000));
localStorage.setItem('username', getParameter('username'));
// 브라우저 리프레쉬를 하므로 이 다음 라인은 실행되지 않음
window.location.href = '//' + location.host + location.pathname;
}
// access_token 파라미터가 없는 경우
var callbackURL = location.protocol + '//' + location.host + location.pathname;
var accessToken = localStorage.getItem('access_token');
var expiresIn = localStorage.getItem('expires_in');
var authTimestamp = localStorage.getItem('auth_timestamp');
var logoutButton = document.querySelector('.logout');
var loginButton = document.querySelector('.login');
var api;
if (accessToken !== null) {
// 이전에 저장된 액세스토큰이 있는 경우
api = sc2.Initialize({
app: 'sc2tut',
callbackURL: callbackURL,
accessToken: accessToken,
scope: ['vote', 'comment']
});
// 로그아웃 버튼 보이기
logoutButton.style.display = 'block';
loginButton.style.display = 'none';
// 로그아웃 클릭 처리
} else {
// 이전에 로그인 한 적이 없어서 저장된 액세스토큰이 없는 경우
api = sc2.Initialize({
app: 'sc2tut',
callbackURL: callbackURL,
scope: ['vote', 'comment']
});
// 로그인 버튼 보이기
logoutButton.style.display = 'none';
loginButton.style.display = 'block';
// 로그인 링크 설정
var link = api.getLoginURL();
console.log('SteemConnect2 getLoginURL:', link);
loginButton.setAttribute('href', link);
}
여기까지 하면 로그인 리다이렉트 후에 로그인 버튼이 안보이고 로그아웃 버튼이 보이게 되며
브라우저 리프레쉬를 해도 로그아웃 버튼이 보이게 됩니다.
로그아웃
이어서 로그아웃 클릭 처리 부분을 알아봅니다.
// 로그아웃 클릭 처리
loginButton.addEventListener('click', function(e) {
e.preventDefault();
api.revokeToken(function (err, res) {
console.log(err, res);
localStorage.removeItem('access_token');
localStorage.removeItem('expires_in');
localStorage.removeItem('username');
localStorage.removeItem('auth_timestamp');
logoutButton.style.display = 'none';
loginButton.style.display = 'block';
var link = api.getLoginURL();
loginButton.setAttribute('href', link);
});
});
revokeToken() 은 주어진 액세스토큰을 못쓰게 해달라고 스팀커넥트 서버에 요청하는 함수입니다.
콜백함수 결과는 {success: true}
입니다.
expires_in : 액세스토큰 유통기한
다음으로 expires_in
을 어떻게 활용해야 하는지 알아봅니다.
expires_in
은 액세스토큰의 유통기한입니다. 기한이 지나고 나면 액세스토큰이 더이상 통하지 않게 되어서 보팅이나 포스팅을 하려고 했을 때 실패하게 됩니다.
매번 시간을 계산해서 유통기한이 지났으면 로그아웃 된 것으로 처리를 해줘야 합니다.
로직은 OAuth 성공시의 타임스탬프를 로컬스토리지에 저장해두고
액세스토큰 유효성 체크할 때 아래와 같이 합니다.
var currentTimestamp = Math.round(Date.now()/1000);
if (currentTimestamp - authTimestamp >= expiresIn) {
// 액세스토큰 유효기한이 지나서 로그인 풀림
} else {
// 액세스토큰 유효해서 로그인 된 상태
}
여기까지 해서 전체 HTML/JavaScript 소스코드 첨부합니다.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
<h1>SteemConnect2 Tutorial</h1>
<a href="#" class="login">Login with Steem</a>
<a href="#" class="logout">Logout</a>
<script src="sc2.min.js"></script>
<script>
function getParameter(paramName) {
var searchString = window.location.search.substring(1);
var params = searchString.split('&');
var i, val;
for (i = 0; i < params.length; i++) {
val = params[i].split('=');
if (val[0] == paramName) {
return val[1];
}
}
return null;
}
if (getParameter('access_token') !== null) {
localStorage.setItem('access_token', getParameter('access_token'));
localStorage.setItem('expires_in', getParameter('expires_in'));
localStorage.setItem('auth_timestamp', Math.round(Date.now()/1000));
localStorage.setItem('username', getParameter('username'));
window.location.href = '//' + location.host + location.pathname;
}
var callbackURL = location.protocol + '//' + location.host + location.pathname;
var accessToken = localStorage.getItem('access_token');
var expiresIn = localStorage.getItem('expires_in');
var authTimestamp = localStorage.getItem('auth_timestamp');
var api;
var logoutButton = document.querySelector('.logout');
var loginButton = document.querySelector('.login');
var currentTimestamp = Math.round(Date.now()/1000);
if (currentTimestamp - authTimestamp >= expiresIn) {
// 액세스토큰 유효기한 만료
localStorage.removeItem('access_token');
localStorage.removeItem('expires_in');
localStorage.removeItem('username');
localStorage.removeItem('auth_timestamp');
api = sc2.Initialize({
app: 'sc2tut',
callbackURL: callbackURL,
scope: ['vote', 'comment']
});
// 로그인 버튼 보이기
logoutButton.style.display = 'none';
loginButton.style.display = 'block';
// 로그인 링크 설정
var link = api.getLoginURL();
loginButton.setAttribute('href', link);
} else {
// 액세스토큰 유효
if (accessToken !== null) {
// 이전에 저장된 액세스토큰이 있는 경우
api = sc2.Initialize({
app: 'sc2tut',
callbackURL: callbackURL,
accessToken: accessToken,
scope: ['vote', 'comment']
});
// 로그아웃 버튼 보이기
logoutButton.style.display = 'block';
loginButton.style.display = 'none';
// 로그아웃 클릭 처리
logoutButton.addEventListener('click', function(e) {
e.preventDefault();
api.revokeToken(function (err, res) {
console.log(err, res);
localStorage.removeItem('access_token');
localStorage.removeItem('expires_in');
localStorage.removeItem('username');
localStorage.removeItem('auth_timestamp');
logoutButton.style.display = 'none';
loginButton.style.display = 'block';
var link = api.getLoginURL();
loginButton.setAttribute('href', link);
});
});
} else {
// 이전에 로그인 한 적이 없어서 저장된 액세스토큰이 없는 경우
api = sc2.Initialize({
app: 'sc2tut',
callbackURL: callbackURL,
scope: ['vote', 'comment']
});
// 로그인 버튼 보이기
logoutButton.style.display = 'none';
loginButton.style.display = 'block';
// 로그인 링크 설정
var link = api.getLoginURL();
console.log('SteemConnect2 getLoginURL:', link);
loginButton.setAttribute('href', link);
}
}
if (accessToken) {
var username = localStorage.getItem('username');
console.log('Hi, ', username);
}
</script>
</body>
</html>
다음시간에는 스팀커넥트로 보팅 하는 방법을 알아봅니다.
Nice post
이해하고 싶은데 못하는 심정...
지금 steemit을위한 아주 좋은 게시물
훌륭한 글에는 보팅이죠!! 좋은글 감사합니다
잘보고 공부 하겠습니다. 감사합니다.
ㅠ으아 문송합니다ㅠㅠ
좋은 글 감사합니다ㅠㅠ
좋은 글 감사합니다 ~ 잘 참고 하겠습니다 !!
ㅜ0ㅜ 워.. 너무 고생하셔서 설명해 주셨는데
머리에 막 지진이 나고 있어요 ㅠㅠㅠㅠㅠ
다 이해했어....;;;;;;ㅠ 라고 하고싶다..
아 멋지다. 코딩하는 사람...;
코딩하시는 분들 넘 신기해요. 마법의 언어를 본 것 같습니다.
필요하고 중요한 글인것 같은데... 이해가 하...ㅠㅠ
스팀잇하시는분들의 수준이 정말 높은것 같아요...
OAuth 래퍼 하나 만들어야겠군요 ㅎㅎ
좋은 가이드 감사합니다 :)
열심히 공부하는법밖엔 없네요.
좋은글 감사합니다.