DeterministicESPAsyncWebServer v6.28.0
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
oauth2.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file oauth2.h
6 * @brief OAuth2 token-endpoint client - authorization-code + refresh (DETWS_ENABLE_OAUTH2).
7 *
8 * The other half of the OAuth/OIDC story (services/oidc verifies the ID token;
9 * this obtains the tokens). A relying party exchanges an authorization code for
10 * tokens at the provider's token endpoint, or refreshes them, per RFC 6749 §4.1.3
11 * / §6:
12 *
13 * - **Pure core (host-tested):** build the `application/x-www-form-urlencoded`
14 * request body (proper percent-encoding) for the `authorization_code` and
15 * `refresh_token` grants, and parse the JSON token response (reusing the
16 * library's zero-heap JSON reader) into ::DetwsOAuth2Tokens.
17 * - **ESP32 convenience (needs DETWS_ENABLE_HTTP_CLIENT):**
18 * detws_oauth2_exchange_code() / _refresh() POST to the token URL over the
19 * HTTP(S) client and parse the result.
20 *
21 * Supports a confidential client (client_secret) or a public client with PKCE
22 * (code_verifier, RFC 7636) - pass whichever applies, nullptr for the other. No
23 * heap, no stdlib.
24 *
25 * @author Douglas Quigg (dstroy0)
26 * @date 2026
27 */
28
29#ifndef DETERMINISTICESPASYNCWEBSERVER_OAUTH2_H
30#define DETERMINISTICESPASYNCWEBSERVER_OAUTH2_H
31
32#include "ServerConfig.h"
33#include <stddef.h>
34#include <stdint.h>
35
36#if DETWS_ENABLE_OAUTH2
37
38/** @brief Tokens parsed from a token-endpoint response. Absent fields are empty / 0. */
39struct DetwsOAuth2Tokens
40{
41 char access_token[DETWS_OAUTH2_TOKEN_LEN];
42 char id_token[DETWS_OAUTH2_TOKEN_LEN]; ///< OIDC ID token (verify with services/oidc).
43 char refresh_token[DETWS_OAUTH2_RT_LEN];
44 char token_type[24]; ///< usually "Bearer".
45 long expires_in; ///< access-token lifetime in seconds (0 if absent).
46};
47
48/** @brief oauth2 result codes (HTTP status codes are positive on success). */
49enum class DetwsOAuth2Result : int32_t
50{
51 DETWS_OAUTH2_ERR_BUILD = -1, ///< request body did not fit @p cap.
52 DETWS_OAUTH2_ERR_TRANSPORT = -2, ///< HTTP client error (no DNS / TLS / connection).
53 DETWS_OAUTH2_ERR_RESPONSE = -3, ///< response was not a valid token JSON (no access_token).
54};
55
56// ---------------------------------------------------------------------------
57// Pure core (host-testable)
58// ---------------------------------------------------------------------------
59
60/**
61 * @brief Build the form body for the authorization_code grant.
62 *
63 * @param code,redirect_uri,client_id required parameters.
64 * @param client_secret confidential-client secret, or nullptr.
65 * @param code_verifier PKCE verifier (RFC 7636) for a public client, or nullptr.
66 * @return bytes written (excluding NUL), or 0 if it does not fit.
67 */
68int detws_oauth2_build_code_request(const char *code, const char *redirect_uri, const char *client_id,
69 const char *client_secret, const char *code_verifier, char *out, size_t cap);
70
71/**
72 * @brief Build the form body for the refresh_token grant.
73 * @return bytes written (excluding NUL), or 0 if it does not fit.
74 */
75int detws_oauth2_build_refresh_request(const char *refresh_token, const char *client_id, const char *client_secret,
76 char *out, size_t cap);
77
78/**
79 * @brief Parse a token-endpoint JSON response into @p out.
80 * @return true if an access_token is present (a usable token response).
81 */
82bool detws_oauth2_parse_token_response(const char *json, DetwsOAuth2Tokens *out);
83
84#if DETWS_ENABLE_HTTP_CLIENT
85// ---------------------------------------------------------------------------
86// ESP32 convenience (over the HTTP(S) client)
87// ---------------------------------------------------------------------------
88
89/**
90 * @brief Exchange an authorization code at @p token_url for tokens.
91 * @return the HTTP status (200 on success) or a negative ::DetwsOAuth2Result.
92 */
93int detws_oauth2_exchange_code(const char *token_url, const char *code, const char *redirect_uri, const char *client_id,
94 const char *client_secret, const char *code_verifier, DetwsOAuth2Tokens *out);
95
96/**
97 * @brief Refresh tokens at @p token_url using a refresh token.
98 * @return the HTTP status (200 on success) or a negative ::DetwsOAuth2Result.
99 */
100int detws_oauth2_refresh(const char *token_url, const char *refresh_token, const char *client_id,
101 const char *client_secret, DetwsOAuth2Tokens *out);
102#endif
103
104#endif // DETWS_ENABLE_OAUTH2
105#endif // DETERMINISTICESPASYNCWEBSERVER_OAUTH2_H
User-facing configuration for DeterministicESPAsyncWebServer.