์ฑ๊ธ์ฌ์ธ์จ(Single Sign-On, SSO)์ ํ๋์ ๋ก๊ทธ์ธ ์ธ์ฆ ์๋จ์๋ฅผ ์ฌ์ฉํ์ฌ
์ฌ์ดํธ์์ ์ ๊ณตํ๋ ์ฌ๋ฌ ์ดํ๋ฆฌ์ผ์ด์
ํน์ API์ ์ ๊ทผํ ์ ์๋ ์ค์ํ๋ ์ธ์
๋ฐ ์ฌ์ฉ์ ์ธ์ฆ ์๋น์ค์
๋๋ค.
์๋ผํผ์ ๋ง์ด์ฌ์ดํธ ์์ฑ ๊ธฐ๋ฅ์ ์ด์ฉํ์ฌ ์ฑ ์์ด๋๋ฅผ ๋ฐ๊ธ ๋ฐ๊ณ ,
์ฑ ์์ด๋๋ฅผ ์ด์ฉํ์ฌ SSO ํ ํฐ์ ๋ฐ๊ธ๋ฐ์ API๋ฅผ ์ด์ฉํ๋ ๊ฒ์ ๋งํฉ๋๋ค.
์๋๋ SSO ํ ํฐ์ ์ด์ฉํ์ฌ ์๋ผํผ API๋ฅผ ํธ์ถํ๋ ๋ฐฉ๋ฒ ๊ทธ๋ฆฌ๊ณ ๋ก๊ทธ์ธ ์ฒ๋ฆฌ๊น์ง ์ํค๋ ๋ฐฉ๋ฒ์ ๋๋ค.
์์ ์ฝ๋๋ ์๋ผํผ SSO Examples ์ฝ๋๋ฅผ ์ฐธ์กฐํ์์ต๋๋ค.
SSO๋ฅผ ์ด์ฉํ๊ธฐ ์ํด์๋ ์๋ผํผ์ ๋ง์ด์ฌ์ดํธ๊ฐ ํ์ํฉ๋๋ค.
๋ง์ด์ฌ์ดํธ์ ์ฑ ์์ด๋๋ฅผ ์ด์ฉํ์ฌ SSO ํ ํฐ์ ๋ง๋ค ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
'๋ง์ด์ฌ์ดํธ ์์ฑ' ๋ฒํผ์ ํด๋ฆญํ์ฌ ์์ฑํ ์ ์์ต๋๋ค.
๋ง์ด์ฌ์ดํธ ์ด๋ฆ ๊ทธ๋ฆฌ๊ณ ๋ฐ์ ์ด๋ฉ์ผ์ ์์ฑํ์ ํ ๋ํ์ฃผ์๋ฅผ ์ค์ ํ ๋ค ์๋์ชฝ์ '๋ง์ด์ฌ์ดํธ ์์ฑ' ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์์ฑ์ด ์๋ฃ๋ฉ๋๋ค.
๋ก๊ณ ๋ ์ปฌ๋ฌ๋ฅผ ์ํ์๋ ๋๋ก ๋ณ๊ฒฝํ์ค ์ ์์ต๋๋ค.
์์ฑ๋ ๋ง์ด์ฌ์ดํธ ์ค๋ฅธ์ชฝ์ ์๋ '๋ง์ด์ฌ์ดํธ ๊ด๋ฆฌ'๋ฅผ ํด๋ฆญํ๋ฉด ๊ด๋ฆฌ ํ์ด์ง๋ก ๊ฐ ์ ์์ต๋๋ค.
์ด๊ณณ์์ ๋ง์ด์ฌ์ดํธ์ ๊ฐ์
ํ ํ์๋ค์ ๋ณด๊ณ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
'๋ง์ด์ฌ์ดํธ ๊ด๋ฆฌ' ๋ฒํผ์ ํด๋ฆญํ์ฌ ๋ค์ด๊ฐ๋ฉด ๋ณด์ด๋ ์์ชฝ ์ฃผ์์ฐฝ์ 'mysite/' ๋ท ๋ถ๋ถ์ ์ ํ์๋ ๊ฒ์ด ์ฑ ์์ด๋ ์ ๋๋ค.
ํ๋ฉด ์ค๋ฅธ์ชฝ ์๋ ์๋ด์ฐฝ์ ๋ง์ด์ฌ์ดํธ์ ์ฑ์์ด๋์ ํจ๊ป ๊ด๋ฆฌ์์๊ฒ IP ํ์ฉ์ ์์ฒญํฉ๋๋ค.
ํ์ฉ์ด๋ IP์์๋ง SSO ํ ํฐ์ ์ด์ฉํ API ์ฌ์ฉ์ด ๊ฐ๋ฅํฉ๋๋ค.
๋ฐ์ ์ฑ ์์ด๋๋ก SSO ํ ํฐ ๋ฐ๊ธ์ ์์ฒญํฉ๋๋ค.
[Requset]
const moment = require('moment-timezone')
const { HmacSHA256 } = require('crypto-js')
const apiKey = '##API_KEY##'
const apiSecret = '##API_SECRET##'
// API KEY, API SECRET ์ผ๋ก ์ธ์ฆ๊ฐ ๋ง๋ค์ด ํค๋์ ์ค์
const getApiKeyAuthHeader = () => {
const date = moment().tz('Asia/Seoul').format('YYYY-MM-DD HH:mm:ss')
const salt = (Math.random() + 1).toString(36).substring(7) // ๋๋คํ ๋ฌธ์์ด
const hmacData = date + salt
const signature = HmacSHA256(hmacData, apiSecret).toString()
return { Authorization: `HMAC-SHA256 apiKey=${apiKey}, date=${date}, salt=${salt}, signature=${signature}` }
}
/** Step 1. ์ฑ ์์ด๋์ ๊ฐ์
ํ ํ์์ ๋ณด๋ฅผ ์ด์ฉํ์ฌ SSO Token ๋ฐ๊ธ */
const getSSOToken = async () => {
const form = {
appId: '##APP_ID##', // ๋ฐ๊ธ๋ฐ์ ์ฑ ์์ด๋
email: '##EMAIL##', // ํ์๊ฐ์
์ ์ฌ์ฉ๋ ์ด๋ฉ์ผ ์ฃผ์
password: '##PASSWORD##', // ํ์๊ฐ์
์ ์ฌ์ฉ๋ ์ํธ
customerKey: '##MEMBER_CUSTOMER_KEY##' // ๋ง์ด์ฌ์ดํธ์์ ์ฌ์ฉํ ํ์ ๊ตฌ๋ถ ํค
}
const result = await request({
method: 'POST',
uri: `https://api.solapi.com/appstore/v2/sso/connect`,
form,
json: true,
// OAuth2 or API Key๋ก ๋ ์ธ์ฆ ์๋จ ๊ฐ, ์์ธํ ๋ด์ฉ์ https://developers.solapi.dev/references/authentication์ ์ฐธ๊ณ ํด์ฃผ์ธ์
headers: getApiKeyAuthHeader()
})
console.log(result)
}
getSSOToken()
[Response]
{
ssoToken: 'eyJhbGciOiJIUzI1NiIsInR53216IkpXVCJ9.eyJhcHBJZCI6Ik123U5zQUUzYUp5QiIsIm1lbWJlcklkIjoiTUVNemNhZHo0WmVoUGkiLCJhY2NvdW50SWQiOiIyMjExMDgxODA5NzEwMiIsImlhdCI6MTY2Nzg4MzY5N30.rKGE_xa1ONf5vXn14wI23nlNLeNVst0gEJ_b9E9rReI'
}
๋ฐ๊ธ๋ฐ์ SSO ํ ํฐ์ผ๋ก ์๋ผํผ API ์ด์ฉ์ด ๊ฐ๋ฅํฉ๋๋ค.
[Request]
const request = require('request-promise')
const getMemberInfo = async () => {
const result = await request({
method: 'GET',
uri: `https://api.solapi.com/users/v1/member`,
json: true,
// SSO ํ ํฐ ๊ฐ ์ค์
headers: { Authorization: `sso ##SSO TOKEN ##` }
})
console.log(result)
}
getMemberInfo()
[Response]
{
name: 'user',
phoneNumber: null,
extraPhoneNumbers: [],
status: 'ACTIVE',
selectedAccountId: '22110348097102',
betaMicroservices: null,
appId: 'NGeNsAE334yB',
activeDeviceAuth: false,
isTrial: false,
memberId: 'MEMzc34z4ZehPi',
email: 'user@nurigo.net',
devices: [],
loginSessions: [],
dateCreated: '2022-11-08T05:01:37.097Z',
dateUpdated: '2022-11-08T05:01:37.166Z'
}
SSO ํ ํฐ์ ์ฟผ๋ฆฌ๊ฐ์ผ๋ก ์๋ ์ฃผ์๋ก ๋ณด๋ด๋ฉด ๋ก๊ทธ์ธ์ด ์๋ฃ๋์ฑ๋ก ๋ณด๋ด์ฃผ์ ๋ฆฌ๋ค์ด๋ ํธ ์ฃผ์๋ก ์ด๋ํฉ๋๋ค.
์ฒ์์๋ ์ ์์ ์๋ ์ด๋ฏธ์ง ์ฒ๋ผ ๋ณธ์ธ์ธ์ฆ์ ํด์ฃผ์
์ผํฉ๋๋ค.
[๋ฉ์ธํ์ด์ง๋ก ์ด๋]
https://api.solapi.com/appstore/v2/sso/connect-homepage?redirecturi=#{๋ง์ด์ฌ์ดํธ์ฃผ์}/dashboard
[๋ฐ์ ๋ฒํธ๋ก ์ด๋]
https://api.solapi.com/appstore/v2/sso/connect-homepage?redirecturi=#{๋ง์ด์ฌ์ดํธ์ฃผ์}/senderids
[์ถฉ์ ํ์ด์ง๋ก ์ด๋]
https://api.solapi.com/appstore/v2/sso/connect-homepage?redirecturi=#{๋ง์ด์ฌ์ดํธ์ฃผ์}/balance








