2#ifndef KURLYK_HEADER_KURLYK_HTTP_AUTH_O_AUTH_PKCE_CLIENT_HPP_INCLUDED
3#define KURLYK_HEADER_KURLYK_HTTP_AUTH_O_AUTH_PKCE_CLIENT_HPP_INCLUDED
18#if KURLYK_JSON_SUPPORT
19# include <nlohmann/json.hpp>
35 const std::string& raw_response,
37 std::string& out_error)>;
62 params.emplace(
"response_type",
"code");
68 params.emplace(
"state",
m_state);
106 out_result.
error_message =
"token_endpoint is not configured";
111 body_params.emplace(
"grant_type",
"authorization_code");
112 body_params.emplace(
"code", code);
124 headers.emplace(
"Content-Type",
"application/x-www-form-urlencoded");
127 (void)request_result.first;
131 response = request_result.second.get();
132 }
catch (
const std::exception& e) {
134 out_result.
error_message = std::string(
"HTTP request failed: ") + e.what();
140 out_result.
error_message =
"HTTP request returned null response";
146 if (response->status_code < 200 || response->status_code >= 300) {
149 std::to_string(response->status_code);
163 if (refresh_token.empty()) {
171 out_result.
error_message =
"token_endpoint is not configured";
176 body_params.emplace(
"grant_type",
"refresh_token");
177 body_params.emplace(
"refresh_token", refresh_token);
185 headers.emplace(
"Content-Type",
"application/x-www-form-urlencoded");
188 (void)request_result.first;
192 response = request_result.second.get();
193 }
catch (
const std::exception& e) {
195 out_result.
error_message = std::string(
"HTTP request failed: ") + e.what();
201 out_result.
error_message =
"HTTP request returned null response";
207 if (response->status_code < 200 || response->status_code >= 300) {
210 std::to_string(response->status_code);
236#if KURLYK_JSON_SUPPORT
238 nlohmann::json j = nlohmann::json::parse(raw_response);
240 if (j.contains(
"error")) {
243 j.value(
"error",
"unknown error"));
249 if (j.contains(
"access_token")) token.
access_token = j[
"access_token"].get<std::string>();
250 if (j.contains(
"refresh_token")) token.
refresh_token = j[
"refresh_token"].get<std::string>();
251 if (j.contains(
"token_type")) token.
token_type = j[
"token_type"].get<std::string>();
252 if (j.contains(
"scope")) token.
scope = j[
"scope"].get<std::string>();
254 if (j.contains(
"expires_in")) {
255 int64_t expires_in = j[
"expires_in"].get<int64_t>();
256 auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
257 std::chrono::system_clock::now().time_since_epoch()).count();
263 out_result.
error_message =
"access_token is missing in response";
267 out_result.
token = token;
270 }
catch (
const std::exception& e) {
272 out_result.
error_message = std::string(
"JSON parse error: ") + e.what();
277 std::string error_msg;
281 out_result.
error_message = error_msg.empty() ?
"custom token parser failed" : error_msg;
289 out_result.
error_message =
"JSON support disabled and no custom token parser set";
Defines authentication result types and error codes.
Defines the OAuthConfig structure for OAuth2 client configuration.
std::string m_code_challenge
bool exchange_code(const std::string &code, AuthResult &out_result)
Exchanges an authorization code for an access token.
TokenParser m_token_parser
std::function< bool( const std::string &raw_response, OAuthToken &out_token, std::string &out_error)> TokenParser
Callback type for custom token parsing when JSON support is disabled.
std::string build_authorization_url()
Builds the full authorization URL with query parameters.
bool refresh_access_token(const std::string &refresh_token, AuthResult &out_result)
Refreshes an access token using a refresh token.
const std::string & state() const
Returns the state parameter used in the last authorization request.
bool validate_state(const std::string &returned_state) const
Validates the state parameter returned by the authorization server.
void set_token_parser(TokenParser parser)
Sets a custom token parser for non-JSON builds.
const std::string & code_verifier() const
Returns the code verifier used in the last PKCE exchange.
OAuthPkceClient(const OAuthConfig &config)
Constructs a client with the given OAuth configuration.
std::string m_code_verifier
bool parse_token_response(const std::string &raw_response, AuthResult &out_result)
Contains utility functions for handling HTTP requests, rate limiting, and request cancellation.
Provides utility functions for parsing HTTP headers and cookies.
std::string to_query_string(const QueryParams &query, const std::string &prefix=std::string()) noexcept
Converts a map of query parameters into a URL query string.
PkcePair make_pkce_pair()
Creates a PKCE pair with a freshly generated verifier.
std::string generate_code_verifier(std::size_t length=64)
Generates a cryptographically strong PKCE code verifier.
Primary namespace for the Kurlyk library, encompassing initialization, request management,...
std::unique_ptr< HttpResponse > HttpResponsePtr
Owning pointer to an HTTP response.
utils::CaseInsensitiveMultimap Headers
Alias for HTTP headers, providing a case-insensitive unordered multimap.
@ HttpError
HTTP request failed (non-2xx status or transport error).
@ InvalidResponse
Server response could not be parsed.
@ InvalidConfig
Missing or invalid client configuration.
@ UnsupportedFlow
The requested OAuth flow is not supported.
utils::CaseInsensitiveMultimap QueryParams
Alias for query parameters in HTTP requests, stored case-insensitively.
uint64_t http_post(const std::string &url, const QueryParams &query, const Headers &headers, const std::string &content, HttpResponseCallback callback)
Sends an asynchronous HTTP POST request with a callback.
Provides functions for percent-encoding and decoding strings.
Provides PKCE (Proof Key for Code Exchange) utilities per RFC 7636.
Encapsulates the outcome of an authentication operation.
std::string error_message
Human-readable error description (if any).
AuthError error
Error classification.
std::string raw_response
Raw server response body for diagnostics.
bool success
Whether the operation succeeded.
OAuthToken token
Token data on success (may be partially filled on failure).
Stores client configuration for an OAuth2 Authorization Code + PKCE flow.
std::string prompt
Optional prompt parameter (e.g. "consent").
std::string client_secret
Client secret (optional, usually empty for public/PKCE clients).
std::string redirect_uri
Registered redirect URI.
std::string audience
Optional audience parameter.
std::string client_id
OAuth2 client identifier.
std::string access_type
Optional access_type parameter (e.g. "offline").
bool use_pkce
Whether to use PKCE (RFC 7636). Default true.
std::string authorization_endpoint
Authorization server URL.
std::string token_endpoint
Token exchange URL.
std::string scope
Space-separated requested scopes.
Holds the result of an OAuth2 token exchange.
int64_t expires_at_ms
Absolute expiration time in milliseconds since epoch (0 = unknown).
std::string raw_response
Raw server response body for debugging.
std::string scope
Granted scope (may be empty).
std::string access_token
The access token string.
std::string token_type
Token type, typically "Bearer".
std::string refresh_token
The refresh token string (may be empty).
Stores PKCE verifier and challenge values.
std::string code_challenge_method
Challenge method, always "S256".
std::string code_verifier
Randomly generated code verifier.
std::string code_challenge
Derived S256 code challenge.