diff --git a/conf/oauth2/default.json b/conf/oauth2/default.json index 709fd34..5e63e64 100644 --- a/conf/oauth2/default.json +++ b/conf/oauth2/default.json @@ -1,19 +1,86 @@ { "web": { - "issuers": ["accounts.bitdeals.com"], - "scopes": ["api","openid","profile","email"], - "client_id": "web-bitdeals.com", - "client_secret": "", + "issuers": ["accounts.bitdeals.org"], + "scopes": ["bitdeals"], + "client_id": "web-bitdeals.org", + "client_secret": "4aJEJi3dsSypeUSRCah4gIIs", "algorithm": "HS256", "auth_uri": "/oauth2/authorize", "token_uri": "/oauth2/token", "redirect_uris": [ - "http://localhost:8080/oauth2/code", - "http://localhost:8080/oauth2/callback", - "https://bitdeals.com/oauth2/code", - "https://bitdeals.com/oauth2/callback", - "https://oauthdebugger.com/debug", - "https://auth.advancedrestclient.com/oauth-popup.html" + "http://localhost:4977/oauth2/code", + "http://localhost:4977/dashboard/", + "http://localhost:4999/oauth2/code", + "http://localhost:4999/dashboard/", + "http://65.21.101.151/oauth2/code", + "http://65.21.101.151/dashboard", + "https://oauthdebugger.com/debug" + ], + "javascript_origins": [ + "http://localhost:4977", + "http://localhost:4999", + "http://65.21.101.151" + ] + }, + "service": { + "issuers": ["accounts.bitdeals.org"], + "scopes": ["bitdeals"], + "client_id": "service-bitdeals.org", + "client_secret": "TjcILDtLa06YABJnepcVM32O", + "algorithm": "HS256", + "auth_uri": "/oauth2/authorize", + "token_uri": "/oauth2/token", + "redirect_uris": [ + "http://localhost:4977/dashboard", + "http://65.21.101.151/dashboard", + "https://oauthdebugger.com/debug" + ], + "javascript_origins": [ + "http://localhost:4977", + "http://65.21.101.151" + ] + }, + "module": { + "issuers": ["accounts.bitdeals.org"], + "scopes": ["bitdeals"], + "client_id": "dm-bitdeals.org", + "client_secret": "TypQHP4TK44khO3cvOyuHYg3", + "algorithm": "HS256", + "auth_uri": "/oauth2/authorize", + "token_uri": "/oauth2/token", + "redirect_uris": [ + "http://localhost:4977/oauth2/code", + "http://localhost:4999/dashboard/", + "https://oauthdebugger.com/debug" + ], + "javascript_origins": [ + "http://localhost:4999" + ] + }, + "android": { + "issuers": ["accounts.bitdeals.org"], + "scopes": ["bitdeals"], + "client_id": "android-bitdeals.org", + "client_secret": "HaBAde09xWKb29NizXZfIMpl", + "algorithm": "HS256", + "auth_uri": "/oauth2/authorize", + "token_uri": "/oauth2/token", + "redirect_uris": [ + "http://127.0.0.1/oauth2/code", + "http://127.0.0.1/oauth2/callback" + ] + }, + "ios": { + "issuers": ["accounts.bitdeals.org"], + "scopes": ["bitdeals"], + "client_id": "ios-bitdeals.org", + "client_secret": "kWqJivDfaR7vbzkZz07zi7DO", + "algorithm": "HS256", + "auth_uri": "/oauth2/authorize", + "token_uri": "/oauth2/token", + "redirect_uris": [ + "http://127.0.0.1/oauth2/code", + "http://127.0.0.1/oauth2/callback" ] } } diff --git a/conf/oauth2/service.json b/conf/oauth2/service.json new file mode 100644 index 0000000..5e517bc --- /dev/null +++ b/conf/oauth2/service.json @@ -0,0 +1,10 @@ +{ + "type": "service_account", + "issuers": ["accounts.bitdeals.org"], + "scopes": ["bitdeals"], + "client_id": "dm-bitdeals.org", + "client_secret": "TypQHP4TK44khO3cvOyuHYg3", + "algorithm": "HS256", + "auth_uri": "/oauth2/authorize", + "token_uri": "/oauth2/token" +} diff --git a/src/core b/src/core index a748414..b3aab68 160000 --- a/src/core +++ b/src/core @@ -1 +1 @@ -Subproject commit a748414372940c16bd015eb9a74a0fb05cf3123a +Subproject commit b3aab68ceb755c3d0d53e910552df106d1ad19ba diff --git a/src/modules/Workers/WebService/WebService.cpp b/src/modules/Workers/WebService/WebService.cpp index 0d418e4..c357e55 100644 --- a/src/modules/Workers/WebService/WebService.cpp +++ b/src/modules/Workers/WebService/WebService.cpp @@ -582,7 +582,6 @@ namespace Apostol { const auto& caModuleAddress = Config()->IniFile().ReadString("module", "address", ""); - const auto& caAuthorization = pServerRequest->Headers["authorization"]; const auto& caOrigin = pServerRequest->Headers["origin"]; const auto& caUserAddress = pServerRequest->Params["address"]; @@ -787,8 +786,7 @@ namespace Apostol { CHTTPRequest::Prepare(pProxyRequest, Method.c_str(), URI.c_str()); - if (!caAuthorization.IsEmpty()) - pProxyRequest->AddHeader("Authorization", caAuthorization); + pProxyRequest->AddHeader("Authorization", "Bearer " + m_Tokens[SYSTEM_PROVIDER_NAME]["access_token"]); if (!caModuleAddress.IsEmpty()) pProxyRequest->AddHeader("Module-Address", caModuleAddress); @@ -875,7 +873,6 @@ namespace Apostol { if (checkFee == -1) throw ExceptionFrm("Invalid module fee value: %s", caModuleFee.c_str()); - const auto& caAuthorization = pServerRequest->Headers["authorization"]; const auto& caOrigin = pServerRequest->Headers["origin"]; const auto& caUserAddress = pServerRequest->Params["address"]; @@ -1244,8 +1241,7 @@ namespace Apostol { CHTTPRequest::Prepare(pProxyRequest, Method.c_str(), URI.c_str()); - if (!caAuthorization.IsEmpty()) - pProxyRequest->AddHeader("Authorization", caAuthorization); + pProxyRequest->AddHeader("Authorization", "Bearer " + m_Tokens[SYSTEM_PROVIDER_NAME]["access_token"]); if (!caModuleAddress.IsEmpty()) pProxyRequest->AddHeader("Module-Address", caModuleAddress); @@ -1628,7 +1624,7 @@ namespace Apostol { PGP.StatusTime = Now(); PGP.Status = CKeyContext::ksFetching; - CHTTPRequest::Prepare(ARequest, "GET", CString().Format("/api/v1/key/public?account=%s", PGP.Name.c_str()).c_str()); + CHTTPRequest::Prepare(ARequest, "GET", CString().Format("/api/v1/key/public?account=%s&type=pgp", PGP.Name.c_str()).c_str()); ARequest->AddHeader("Authorization", "Bearer " + m_Tokens[SYSTEM_PROVIDER_NAME]["access_token"]); }; @@ -1702,15 +1698,16 @@ namespace Apostol { const auto& caServerContext = CurrentServer().Value(); - Log()->Debug(0, "Trying to fetch a BTC KEY%d from: %s", m_KeyIndex + 1, caServerContext.URI.c_str()); + Log()->Debug(0, "Trying to fetch a BTC key \"%s\" from: %s", BTC.Name.c_str(), caServerContext.URI.c_str()); auto OnRequest = [this, &BTC](CHTTPClient *Sender, CHTTPRequest *ARequest) { const auto& caServerContext = CurrentServer().Value(); BTC.StatusTime = Now(); BTC.Status = CKeyContext::ksFetching; - CString URI("/api/v1/key?type=BTC-PUBLIC&name=KEY"); - URI << m_KeyIndex + 1; - CHTTPRequest::Prepare(ARequest, "GET", URI.c_str()); + + CHTTPRequest::Prepare(ARequest, "GET", CString().Format("/api/v1/key/public?account=%s&type=btc", BTC.Name.c_str()).c_str()); + + ARequest->AddHeader("Authorization", "Bearer " + m_Tokens[SYSTEM_PROVIDER_NAME]["access_token"]); }; auto OnExecute = [this, &BTC](CTCPConnection *AConnection) { @@ -1771,6 +1768,7 @@ namespace Apostol { void CWebService::Reload() { m_Providers.Clear(); + m_Tokens.Clear(); const auto &oauth2 = Config()->IniFile().ReadString(CONFIG_SECTION_NAME, "oauth2", "oauth2/service.json"); const auto &provider = CString(SYSTEM_PROVIDER_NAME); @@ -1802,15 +1800,13 @@ namespace Apostol { if (m_Servers.Count() == 0) { #ifdef _DEBUG - int Index = m_Servers.AddPair("BM-2cXtL92m3CavBKx8qsV2LbZtAU3eQxW2rB", CServerContext("http://localhost:4988")); + int Index = m_Servers.AddPair(BPS_BM_DEBUG_ADDRESS, CServerContext(BPS_SERVER_URL)); m_Servers[Index].Value().PGP.Name = m_Servers[Index].Name(); #else m_Servers.Add(m_DefaultServer); #endif } -// const auto& caServer = CurrentServer().Value(); - if (m_Status == psRunning) { if (now >= m_RandomDate) { FetchKeys(); diff --git a/src/modules/Workers/WebService/WebService.hpp b/src/modules/Workers/WebService/WebService.hpp index a4da078..f545ecb 100644 --- a/src/modules/Workers/WebService/WebService.hpp +++ b/src/modules/Workers/WebService/WebService.hpp @@ -26,8 +26,9 @@ Author: //---------------------------------------------------------------------------------------------------------------------- #define BPS_DEFAULT_SYNC_PERIOD 30 #define BPS_SERVER_PORT 4988 -#define BPS_SERVER_URL "http://65.21.101.151:4988" +#define BPS_SERVER_URL "http://localhost:4988" #define BPS_BM_SERVER_ADDRESS "BM-2cX8y9u9yEi3fdqQfndx9F6NdR5Hv79add" +#define BPS_BM_DEBUG_ADDRESS "BM-2cXtL92m3CavBKx8qsV2LbZtAU3eQxW2rB" //---------------------------------------------------------------------------------------------------------------------- extern "C++" { @@ -51,7 +52,7 @@ namespace Apostol { CDateTime StatusTime; CKeyContext(): Status(ksUnknown), StatusTime(Now()) { - Name = "DEFAULT"; + Name = BPS_BM_SERVER_ADDRESS; } CKeyContext(const CString& Name, const CString& Key): CKeyContext() { diff --git a/www/dashboard/index.html b/www/dashboard/index.html index 850f62a..037917a 100644 --- a/www/dashboard/index.html +++ b/www/dashboard/index.html @@ -1,5 +1,5 @@ - +
@@ -44,7 +44,6 @@ Other @@ -621,159 +620,6 @@ `; - let token; - - function parseJWT(token) { - try { - // Get Token Header - const base64HeaderUrl = token.split('.')[0]; - const base64Header = base64HeaderUrl.replace('-', '+').replace('_', '/'); - const headerData = JSON.parse(window.atob(base64Header)); - - // Get Token payload and date's - const base64Url = token.split('.')[1]; - const base64 = base64Url.replace('-', '+').replace('_', '/'); - const dataJWT = JSON.parse(window.atob(base64)); - - dataJWT.header = headerData; - - // TODO: add expiration at check ... - - return dataJWT; - } catch (err) { - return false; - } - } - - class Token { - - constructor(clientId, accessName, refreshName) { - this.clientId = clientId; - this.accessName = accessName; - this.refreshName = refreshName; - } - - save(accessToken, refreshToken) { - let success = false; - - if (!empty(accessToken)) { - localStorage.setItem(this.accessName, accessToken); - success = true; - } - - if (!empty(refreshToken)) { - localStorage.setItem(this.refreshName, refreshToken); - success = true; - } - - return success; - } - - getAccess() { - return localStorage.getItem(this.accessName); - } - - getRefresh() { - return localStorage.getItem(this.refreshName); - } - - clear() { - localStorage.removeItem(this.accessName); - localStorage.removeItem(this.refreshName); - } - - parse(hash) { - if (empty(hash)) - return false; - - const search = hash.substr(1); - - let params = new URLSearchParams(search); - - let access_token = params.get("access_token"); - let refresh_token = decodeURIComponent(params.get("refresh_token")); - - return this.save(access_token, refresh_token); - } - - async new() { - const body = { - client_id: this.clientId, - grant_type: 'client_credentials', - } - - return await this.fetchToken(body); - } - - async refresh() { - const refreshToken = this.getRefresh(); - - if (empty(refreshToken)) - return false; - - const body = { - client_id: this.clientId, - grant_type: 'refresh_token', - refresh_token: refreshToken - } - - return await this.fetchToken(body); - } - - async fetchToken(body) { - const server = $("input[id='serverURL']").val(); - - const response = await fetch(`${server}/oauth2/token`, { - method: 'POST', - headers: {'Content-Type': 'application/json'}, - body: JSON.stringify(body), - mode: "cors", - cache: "no-store", - credentials: 'omit' - }); - - if (!response.ok) { - this.clear(); - throw new Error(`Fetch token failed: ${response.statusText}`); - } - - const json = await response.json(); - return this.save(json['access_token'], json['refresh_token']); - } - - expired(accessToken) { - if (!empty(accessToken)) { - const jwtDecoded = parseJWT(accessToken); - if (jwtDecoded) { - let now = new Date(); - let exp = new Date(jwtDecoded.exp * 1000); - return now >= exp; - } - } - return false; - } - - async update() { - const accessToken = this.getAccess(); - if (empty(accessToken)) - return await this.new(); - if (this.expired(accessToken)) { - return await this.refresh(); - } - return true; - } - - async validate() { - const accessToken = this.getAccess(); - if (empty(accessToken)) - return false; - if (this.expired(accessToken)) { - return await this.refresh(); - } - return true; - } - } - async function CheckResponse(json, status) { let error; let message; @@ -789,9 +635,6 @@ } if (status === 400) { - if (typeof error === 'string') { - token.clear(); - } return undefined; } else if (status === 401) { //location = '/welcome/'; @@ -841,35 +684,6 @@ document.location.replace(location); } - /** - * @return {json} - */ - async function TokenFetch(path, method = "GET", body = null, initHeaders = {}) { - - if (await token.validate()) { - let headers = new Headers(initHeaders); - headers.append('Authorization', `Bearer ${token.getAccess()}`) - return AsyncFetch(path, method, body, headers); - } - - Welcome(); - } - - function Welcome() { - localStorage.removeItem('Session'); - localStorage.removeItem('Secret'); - - token.clear(); - - window.location.replace("/welcome/"); - } - - function SignOut() { - const api = $("input[id='apiURL']").val(); - TokenFetch(api + '/sign/out'); - Welcome(); - } - function empty(e) { switch (e) { case "": @@ -1108,7 +922,7 @@ const request = $("#action-help"); request.html(spinner); - TokenFetch(api + '/help' + settings) + AsyncFetch(api + '/help' + settings) .then(json => request.html(JsonToPayload(json))) .catch(reason => request.html(reason.message)); } @@ -1130,7 +944,7 @@ const request = $("#action-status"); request.html(spinner); - TokenFetch(api + '/account/status' + settings) + AsyncFetch(api + '/account/status' + settings) .then(json => request.html(JsonToPayload(json))) .catch(reason => request.html(reason.message)); } @@ -1177,7 +991,7 @@ const request = $("#action-new"); request.html(spinner); - TokenFetch(api + '/account/new' + settings, 'POST', formData, {'Content-Type': 'multipart/form-data'}) + AsyncFetch(api + '/account/new' + settings, 'POST', formData, {'Content-Type': 'multipart/form-data'}) .then(json => request.html(JsonToPayload(json))) .catch(reason => request.html(reason.message)); } @@ -1211,7 +1025,7 @@ const request = $("#action-add"); request.html(spinner); - TokenFetch(api + '/account/add' + settings, 'POST', formData, {'Content-Type': 'multipart/form-data'}) + AsyncFetch(api + '/account/add' + settings, 'POST', formData, {'Content-Type': 'multipart/form-data'}) .then(json => request.html(JsonToPayload(json))) .catch(reason => request.html(reason.message)); } @@ -1256,7 +1070,7 @@ const request = $("#action-update"); request.html(spinner); - TokenFetch(api + '/account/update' + settings, 'POST', formData, {'Content-Type': 'multipart/form-data'}) + AsyncFetch(api + '/account/update' + settings, 'POST', formData, {'Content-Type': 'multipart/form-data'}) .then(json => request.html(JsonToPayload(json))) .catch(reason => request.html(reason.message)); } @@ -1287,7 +1101,7 @@ const request = $("#action-delete"); request.html(spinner); - TokenFetch(api + '/account/delete' + settings, 'POST', formData, {'Content-Type': 'multipart/form-data'}) + AsyncFetch(api + '/account/delete' + settings, 'POST', formData, {'Content-Type': 'multipart/form-data'}) .then(json => request.html(JsonToPayload(json))) .catch(reason => request.html(reason.message)); } @@ -1473,7 +1287,7 @@ let execute = $("button[id='btnDealForm']"); execute.prop('disabled', true); - TokenFetch(api + '/deal/' + formOrder.val() + settings, 'POST', formData, {'Content-Type': 'multipart/form-data'}) + AsyncFetch(api + '/deal/' + formOrder.val() + settings, 'POST', formData, {'Content-Type': 'multipart/form-data'}) .then(function(json) { let html; let payload; @@ -1522,7 +1336,7 @@ let execute = $("button[id='btnDealJSON']"); execute.prop('disabled', true); - TokenFetch(api + '/deal' + settings, 'POST', dealJSON.val(), {'Content-Type': 'application/json'}) + AsyncFetch(api + '/deal' + settings, 'POST', dealJSON.val(), {'Content-Type': 'application/json'}) .then(function(json) { let html; let payload; @@ -1571,7 +1385,7 @@ let execute = $("button[id='btnDealYAML']"); execute.prop('disabled', true); - TokenFetch(api + '/deal' + settings, 'POST', dealYAML.val(), {'Content-Type': 'text/plain'}) + AsyncFetch(api + '/deal' + settings, 'POST', dealYAML.val(), {'Content-Type': 'text/plain'}) .then(function(json) { let html; let payload; @@ -1613,7 +1427,7 @@ let execute = $("button[id='btnCheckSignature']"); execute.prop('disabled', true); - TokenFetch(api + '/signature', 'POST', JSON.stringify(json), {'Content-Type': 'application/json'}) + AsyncFetch(api + '/signature', 'POST', JSON.stringify(json), {'Content-Type': 'application/json'}) .then(function(json) { let html; @@ -1654,7 +1468,7 @@ let execute = $("button[id='btnAccountGet']"); execute.prop('disabled', true); - TokenFetch(`${server}${api}/account/get${params}`) + AsyncFetch(`${server}${api}/account/get${params}`) .then(function(json) { let html; @@ -1694,7 +1508,7 @@ let execute = $("button[id='btnAccountList']"); execute.prop('disabled', true); - TokenFetch(`${server}${api}/account/list${params}`) + AsyncFetch(`${server}${api}/account/list${params}`) .then(function(json) { let html; @@ -1733,7 +1547,7 @@ const request = $("#action-deal-status"); request.html(spinner); - TokenFetch(`${api}/deal/status${settings}`) + AsyncFetch(`${api}/deal/status${settings}`) .then(json => request.html(PayloadToHTML(JsonToPayload(json)))) .catch(reason => request.html(reason.message)); } @@ -1751,7 +1565,7 @@ const request = $("#action-deal-feedback"); request.html(spinner); - TokenFetch(`${api}/deal/feedback${settings}`) + AsyncFetch(`${api}/deal/feedback${settings}`) .then(json => request.html(PayloadToHTML(JsonToPayload(json)))) .catch(reason => request.html(reason.message)); } @@ -1769,7 +1583,7 @@ const request = $("#action-deal-cancel"); request.html(spinner); - TokenFetch(`${api}/deal/cancel${settings}`) + AsyncFetch(`${api}/deal/cancel${settings}`) .then(json => request.html(PayloadToHTML(JsonToPayload(json)))) .catch(reason => request.html(reason.message)); } @@ -1789,7 +1603,7 @@ let execute = $("button[id='btnDealGet']"); execute.prop('disabled', true); - TokenFetch(`${server}${api}/deal/get${params}`) + AsyncFetch(`${server}${api}/deal/get${params}`) .then(function(json) { let html; @@ -1829,7 +1643,7 @@ let execute = $("button[id='btnDealList']"); execute.prop('disabled', true); - TokenFetch(`${server}${api}/deal/list?${params}`) + AsyncFetch(`${server}${api}/deal/list?${params}`) .then(function(json) { let html; @@ -1875,12 +1689,6 @@ })(); $(document).ready(function() { - token = new Token($("meta[name='web-client_id']").attr("content"), 'accessToken', 'refreshToken'); - - if (token.parse(document.location.hash)) { - window.location.hash = '#'; - } - actionHelp(); actionDeal(); }); diff --git a/www/welcome/index.html b/www/welcome/index.html index dca1898..9266132 100644 --- a/www/welcome/index.html +++ b/www/welcome/index.html @@ -104,6 +104,9 @@ SendForm(params, oauth2Endpoint); } + $(document).ready(function() { + document.location.replace('/dashboard'); + }); \ No newline at end of file