algotradelib
0.0.0.9000
C++ header-only library for algorithmic trading
Toggle main menu visibility
Loading...
Searching...
No Matches
auth.hpp
1
#pragma once
2
3
#include "./config.hpp"
4
#include "./network.hpp"
5
6
#include <mutex>
7
8
namespace
algotradelib
{
9
namespace
kis
{
10
11
class
KisAuth
;
12
19
class
KisAuth
{
20
public
:
27
KisAuth
(net::io_context& ioc, ssl::context& ctx,
const
KisConfig
& config)
28
: ioc_(ioc), ctx_(ctx), req_(config) {}
29
31
virtual
~KisAuth
() =
default
;
32
40
std::string
accessToken
() {
41
std::lock_guard<std::mutex> lock(mtx_);
42
if
(!rest_resp_.valid()) {
43
refresh();
44
}
45
return
rest_resp_.access_token_;
46
}
47
54
std::string
accessWebsocket
() {
55
std::lock_guard<std::mutex> lock(mtx_);
56
if
(!ws_resp_.valid()) {
57
refreshWebsocket();
58
}
59
return
ws_resp_.approval_key_;
60
}
61
62
private
:
63
net::io_context& ioc_;
64
ssl::context& ctx_;
65
KisConfig
req_;
66
KisRest
rest_resp_;
67
KisWebsocket
ws_resp_;
68
std::mutex mtx_;
69
70
void
refresh() {
71
const
std::string jsonbody = req_.
to_jsonbody
();
72
KisHttpClient
rest(ioc_, ctx_, req_.
rest_host
(), req_.
rest_port
());
73
auto
response = rest.post(
"/oauth2/tokenP"
, jsonbody, {{
"content-type"
,
"application/json"
}});
74
if
(response.result_int() < 200 || response.result_int() >= 300) {
75
throw
std::runtime_error(
76
"Token authentication failed with HTTP status "
+ std::to_string(response.result_int())
77
);
78
}
79
const
std::string resp = std::move(response.body());
80
boost::system::error_code ec;
81
const
auto
jv = json::parse(resp, ec);
82
// const auto* doc = (!ec && jv.is_object()) ? &jv.as_object() : nullptr;
83
// if (!doc || !doc->contains("access_token")) {
84
// throw std::runtime_error("Token authentication failed: " + resp);
85
// }
86
// rest_resp_.access_token_ = doc->at("access_token").as_string().c_str();
87
// rest_resp_.expires_in_ = doc->contains("expires_in") ? doc->at("expires_in").as_int64() :
88
// 86400; rest_resp_.access_token_expired_ = doc->contains("access_token_token_expired") ?
89
// parse_expiry(doc->at("access_token_token_expired").as_string().c_str()) :
90
// std::chrono::system_clock::now() + std::chrono::seconds(86400);
91
if
(ec || !jv.is_object()) {
92
// Not the body: a token reply that did not parse may still hold the token.
93
throw
std::runtime_error(
94
"Token authentication failed: the reply is not a JSON object ("
+ std::to_string(resp.size()) +
" bytes)"
95
);
96
}
97
rest_resp_.from_json(jv.as_object());
98
}
99
100
void
refreshWebsocket() {
101
const
std::string jsonbody = req_.ws_to_jsonbody();
102
KisHttpClient
rest(ioc_, ctx_, req_.rest_host(), req_.rest_port());
103
// _base_headers_ws = {
104
// "content-type": "utf-8",
105
// }
106
auto
response = rest.post(
"/oauth2/Approval"
, jsonbody, {{
"content-type"
,
"utf-8"
}});
107
if
(response.result_int() < 200 || response.result_int() >= 300) {
108
throw
std::runtime_error(
109
"WebSocket authentication failed with HTTP status "
+ std::to_string(response.result_int())
110
);
111
}
112
const
std::string resp = std::move(response.body());
113
boost::system::error_code ec;
114
const
auto
jv = json::parse(resp, ec);
115
// const auto* doc = (!ec && jv.is_object()) ? &jv.as_object() : nullptr;
116
// if (!doc || !doc->contains("approval_key")) {
117
// throw std::runtime_error("WS approval key authentication failed: " + resp);
118
// }
119
// ws_resp_.approval_key = doc->at("approval_key").as_string().c_str();
120
// ws_resp_.last_auth_time = std::chrono::system_clock::now();
121
if
(ec || !jv.is_object()) {
122
// Not the body: an approval reply that did not parse may still hold the key.
123
throw
std::runtime_error(
124
"WebSocket authentication failed: the reply is not a JSON object ("
+ std::to_string(resp.size()) +
125
" bytes)"
126
);
127
}
128
ws_resp_.from_json(jv.as_object());
129
}
130
};
131
132
}
// namespace kis
133
}
// namespace algotradelib
algotradelib::kis::KisAuth
Obtains and caches KIS access tokens and WebSocket approval keys with blocking requests; thread-safe.
Definition
auth.hpp:19
algotradelib::kis::KisAuth::~KisAuth
virtual ~KisAuth()=default
Destroys the wrapper.
algotradelib::kis::KisAuth::accessWebsocket
std::string accessWebsocket()
Returns a WebSocket approval key, requesting a new one if none is held or it is a day old.
Definition
auth.hpp:54
algotradelib::kis::KisAuth::KisAuth
KisAuth(net::io_context &ioc, ssl::context &ctx, const KisConfig &config)
Constructs the wrapper.
Definition
auth.hpp:27
algotradelib::kis::KisAuth::accessToken
std::string accessToken()
Returns a REST access token, requesting a new one if none is held or it expires within five minutes.
Definition
auth.hpp:40
algotradelib::network::ClientCredentials::to_jsonbody
std::string to_jsonbody() const
Builds a JSON token-request body (grant type, key and secret under the broker's field names).
Definition
oauth.hpp:75
algotradelib::kis
The Korea Investment & Securities (KIS) Open API client.
Definition
auth.hpp:9
algotradelib::kis::KisHttpClient
network::HttpClient KisHttpClient
The blocking HTTP client KisAuth uses.
Definition
network.hpp:9
algotradelib
The library: broker-neutral types (core), and the modules below.
Definition
conversion.hpp:13
algotradelib::kis::KisConfig
KIS credentials (app key and secret), demo or real account, and the market-data tape.
Definition
config.hpp:90
algotradelib::kis::KisConfig::rest_port
const char * rest_port() const noexcept
Returns the REST port for the environment.
Definition
config.hpp:238
algotradelib::kis::KisConfig::rest_host
const char * rest_host() const noexcept
Returns the REST host for the environment.
Definition
config.hpp:230
algotradelib::kis::KisRest
A KIS REST access token and its expiry.
Definition
config.hpp:263
algotradelib::kis::KisWebsocket
A KIS WebSocket approval key and when it was issued.
Definition
config.hpp:309
algotradelib
src
brokers
kis
auth.hpp
Generated by
1.18.0