RESTinio
Loading...
Searching...
No Matches
basic_auth.hpp
Go to the documentation of this file.
1/*
2 * RESTinio
3 */
4
5/*!
6 * @file
7 * @brief Helpers for dealing with basic authentification.
8 *
9 * @since v.0.6.7
10 */
11
12#pragma once
13
14#include <restinio/helpers/http_field_parsers/authorization.hpp>
15
16#include <restinio/utils/base64.hpp>
17
18#include <restinio/http_headers.hpp>
19#include <restinio/request_handler.hpp>
20#include <restinio/expected.hpp>
21
22#include <iostream>
23
24namespace restinio
25{
26
27namespace http_field_parsers
28{
29
30namespace basic_auth
31{
32
33//
34// params_t
35//
36/*!
37 * @brief Parameters for basic authentification.
38 *
39 * @since v.0.6.7
40 */
42{
43 //! Name of a user.
44 /*!
45 * Can't be empty.
46 */
47 std::string username;
48
49 //! Password for a user.
50 /*!
51 * Can be empty.
52 */
53 std::string password;
54};
55
56//
57// extraction_error_t
58//
59/*!
60 * @brief Error codes for failures of extraction of basic authentification
61 * parameters.
62 *
63 * @since v.0.6.7
64 */
66{
67 //! There is no HTTP field with authentification parameters.
69
70 //! The HTTP field with authentification parameters can't be parsed.
72
73 //! Different authentification scheme found.
74 //! Basic authentification scheme is expected.
76
77 //! Invalid value of parameter for basic authentification scheme.
78 //! The single parameter in the form of token68 is expected.
80
81 //! Value of token68 parameter for basic authentification can't be decoded.
83
84 //! Wrong format for username:password in decoded token68 parameter.
85 //! Maybe there is no colon symbol.
87
88 //! Empty user name in username:password pair.
90};
91
92/*!
93 * @brief Helper function to get a string name of extraction_error enum.
94 *
95 * @since v.0.6.9
96 */
97[[nodiscard]]
98inline string_view_t
100{
101 string_view_t result{ "<unknown>" };
102
103 switch( what )
104 {
105 case extraction_error_t::no_auth_http_field:
106 result = string_view_t{ "no_auth_http_field" };
107 break;
108
109 case extraction_error_t::illegal_http_field_value:
110 result = string_view_t{ "illegal_http_field_value" };
111 break;
112
113 case extraction_error_t::not_basic_auth_scheme:
114 result = string_view_t{ "not_basic_auth_scheme" };
115 break;
116
117 case extraction_error_t::invalid_basic_auth_param:
118 result = string_view_t{ "invalid_basic_auth_param" };
119 break;
120
121 case extraction_error_t::token68_decode_error:
122 result = string_view_t{ "token68_decode_error" };
123 break;
124
125 case extraction_error_t::invalid_username_password_pair:
126 result = string_view_t{ "invalid_username_password_pair" };
127 break;
128
129 case extraction_error_t::empty_username:
130 result = string_view_t{ "empty_username" };
131 break;
132 }
133
134 return result;
135}
136
137//
138// try_extract_params
139//
140/*!
141 * @brief Helper function for getting parameters of basic authentification
142 * from an already parsed HTTP-field.
143 *
144 * @attention
145 * This function doesn't check the content of
146 * authorization_value_t::auth_scheme. It's expected that this field was
147 * checked earlier.
148 *
149 * Usage example:
150 * @code
151 * auto on_request(restinio::request_handle_t & req) {
152 * using namespace restinio::http_field_parsers;
153 * const auto opt_field = req.header().opt_value_of(
154 * restinio::http_field::authorization);
155 * if(opt_field) {
156 * const auto parsed_field = authorization_value_t::try_parse(*opt_field);
157 * if(parsed_field) {
158 * if("basic" == parsed_field->auth_scheme) {
159 * using namespace restinio::http_field_parsers::basic_auth;
160 * const auto basic_params = try_extract_params(*parsed_field);
161 * if(basic_params) {
162 * const std::string & username = auth_params->username;
163 * const std::string & password = auth_params->password;
164 * ... // Do something with username and password.
165 * }
166 * }
167 * else if("bearer" == parsed_field->auth_scheme) {
168 * ... // Dealing with bearer authentification.
169 * }
170 * else {
171 * ... // Other authentification schemes.
172 * }
173 * }
174 * }
175 * ...
176 * }
177 * @endcode
178 *
179 * @since v.0.6.8
180 */
181[[nodiscard]]
184 const authorization_value_t & http_field )
185{
186 const auto * token68 = std::get_if<authorization_value_t::token68_t>(
187 &http_field.auth_param );
188 if( !token68 )
189 return make_unexpected( extraction_error_t::invalid_basic_auth_param );
190
191 const auto unbase64_result =
192 restinio::utils::base64::try_decode( token68->value );
193 if( !unbase64_result )
194 return make_unexpected( extraction_error_t::token68_decode_error );
195
196 const std::string & username_password = *unbase64_result;
197 const auto first_colon = username_password.find( ':' );
198 if( std::string::npos == first_colon )
199 return make_unexpected(
201 if( 0u == first_colon )
202 return make_unexpected( extraction_error_t::empty_username );
203
204 return params_t{
205 username_password.substr( 0u, first_colon ),
206 username_password.substr( first_colon + 1u )
207 };
208}
209
210namespace impl
211{
212
213[[nodiscard]]
216 const std::optional< string_view_t > opt_field_value )
217{
218 if( !opt_field_value )
219 return make_unexpected( extraction_error_t::no_auth_http_field );
220
221 const auto field_value_parse_result = authorization_value_t::try_parse(
222 *opt_field_value );
223 if( !field_value_parse_result )
224 return make_unexpected( extraction_error_t::illegal_http_field_value );
225
226 const auto & parsed_value = *field_value_parse_result;
227 if( "basic" != parsed_value.auth_scheme )
228 return make_unexpected( extraction_error_t::not_basic_auth_scheme );
229
230 return try_extract_params( parsed_value );
231}
232
233} /* namespace impl */
234
235//
236// try_extract_params
237//
238/*!
239 * @brief Helper function for getting parameters of basic authentification
240 * from a set of HTTP-fields.
241 *
242 * This helper function is intended to be used for cases when authentification
243 * parameters are stored inside a HTTP-field with a custom name. For example:
244 * @code
245 * auto check_authorization(const restinio::http_header_fields_t & fields) {
246 * using namespace restinio::http_field_parsers::basic_auth;
247 * const auto auth_params = try_extract_params(fields, "X-My-Authorization");
248 * if(auth_params) {
249 * const std::string & username = auth_params->username;
250 * const std::string & password = auth_params->password;
251 * ... // Do something with username and password.
252 * }
253 * ...
254 * }
255 * @endcode
256 *
257 * @since v.0.6.9
258 */
259[[nodiscard]]
262 //! A set of HTTP-fields.
263 const http_header_fields_t & fields,
264 //! The name of a HTTP-field with authentification parameters.
265 string_view_t auth_field_name )
266{
267 return impl::perform_extraction_attempt(
268 fields.opt_value_of( auth_field_name ) );
269}
270
271/*!
272 * @brief Helper function for getting parameters of basic authentification
273 * from a request.
274 *
275 * This helper function is intended to be used for cases when authentification
276 * parameters are stored inside a HTTP-field with a custom name. For example:
277 * @code
278 * auto on_request(restinio::request_handle_t & req) {
279 * using namespace restinio::http_field_parsers::basic_auth;
280 * const auto auth_params = try_extract_params(*req, "X-My-Authorization");
281 * if(auth_params) {
282 * const std::string & username = auth_params->username;
283 * const std::string & password = auth_params->password;
284 * ... // Do something with username and password.
285 * }
286 * ...
287 * }
288 * @endcode
289 *
290 * @since v.0.6.7
291 */
292template< typename Extra_Data >
293[[nodiscard]]
296 //! A request that should hold a HTTP-field with authentification
297 //! parameters.
298 const generic_request_t< Extra_Data > & req,
299 //! The name of a HTTP-field with authentification parameters.
300 string_view_t auth_field_name )
301{
302 return try_extract_params( req.header(), auth_field_name );
303}
304
305/*!
306 * @brief Helper function for getting parameters of basic authentification
307 * from a set of HTTP-fields.
308 *
309 * Usage example:
310 * @code
311 * auto check_authorization(const restinio::http_header_fields_t & fields) {
312 * using namespace restinio::http_field_parsers::basic_auth;
313 * const auto auth_params = try_extract_params(
314 * fields, restinio::http_field::authorization);
315 * if(auth_params) {
316 * const std::string & username = auth_params->username;
317 * const std::string & password = auth_params->password;
318 * ... // Do something with username and password.
319 * }
320 * ...
321 * }
322 * @endcode
323 *
324 * @since v.0.6.9
325 */
326[[nodiscard]]
329 //! A set of HTTP-fields.
330 const http_header_fields_t & fields,
331 //! The ID of a HTTP-field with authentification parameters.
332 http_field_t auth_field_id )
333{
334 return impl::perform_extraction_attempt(
335 fields.opt_value_of( auth_field_id ) );
336}
337
338/*!
339 * @brief Helper function for getting parameters of basic authentification
340 * from a request.
341 *
342 * Usage example:
343 * @code
344 * auto on_request(restinio::request_handle_t & req) {
345 * using namespace restinio::http_field_parsers::basic_auth;
346 * const auto auth_params = try_extract_params(
347 * *req, restinio::http_field::authorization);
348 * if(auth_params) {
349 * const std::string & username = auth_params->username;
350 * const std::string & password = auth_params->password;
351 * ... // Do something with username and password.
352 * }
353 * ...
354 * }
355 * @endcode
356 *
357 * @since v.0.6.7
358 */
359template< typename Extra_Data >
360[[nodiscard]]
363 //! A request that should hold a HTTP-field with authentification
364 //! parameters.
365 const generic_request_t< Extra_Data > & req,
366 //! The ID of a HTTP-field with authentification parameters.
367 http_field_t auth_field_id )
368{
369 return try_extract_params( req.header(), auth_field_id );
370}
371
372} /* namespace basic_auth */
373
374} /* namespace http_field_parsers */
375
376} /* namespace restinio */
expected_t< params_t, extraction_error_t > perform_extraction_attempt(const std::optional< string_view_t > opt_field_value)
expected_t< params_t, extraction_error_t > try_extract_params(const http_header_fields_t &fields, http_field_t auth_field_id)
Helper function for getting parameters of basic authentification from a set of HTTP-fields.
extraction_error_t
Error codes for failures of extraction of basic authentification parameters.
@ not_basic_auth_scheme
Different authentification scheme found. Basic authentification scheme is expected.
@ token68_decode_error
Value of token68 parameter for basic authentification can't be decoded.
@ no_auth_http_field
There is no HTTP field with authentification parameters.
@ empty_username
Empty user name in username:password pair.
@ invalid_username_password_pair
Wrong format for username:password in decoded token68 parameter. Maybe there is no colon symbol.
@ illegal_http_field_value
The HTTP field with authentification parameters can't be parsed.
@ invalid_basic_auth_param
Invalid value of parameter for basic authentification scheme. The single parameter in the form of tok...
expected_t< params_t, extraction_error_t > try_extract_params(const authorization_value_t &http_field)
Helper function for getting parameters of basic authentification from an already parsed HTTP-field.
expected_t< params_t, extraction_error_t > try_extract_params(const generic_request_t< Extra_Data > &req, string_view_t auth_field_name)
Helper function for getting parameters of basic authentification from a request.
expected_t< params_t, extraction_error_t > try_extract_params(const http_header_fields_t &fields, string_view_t auth_field_name)
Helper function for getting parameters of basic authentification from a set of HTTP-fields.
expected_t< params_t, extraction_error_t > try_extract_params(const generic_request_t< Extra_Data > &req, http_field_t auth_field_id)
Helper function for getting parameters of basic authentification from a request.
string_view_t to_string_view(extraction_error_t what) noexcept
Helper function to get a string name of extraction_error enum.
http_field_t
C++ enum that repeats nodejs c-style enum.
Tools for working with the value of Authorization HTTP-field.
authorization_details::token68_t token68_t
Type for holding a value of token68 from RFC7235.
Parameters for basic authentification.