RESTinio
bearer_auth.hpp
Go to the documentation of this file.
1 /*
2  * RESTinio
3  */
4 
5 /*!
6  * @file
7  * @brief Helpers for dealing with bearer authentification.
8  *
9  * @since v.0.6.7.1
10  */
11 
12 #pragma once
13 
14 #include <restinio/helpers/http_field_parsers/authorization.hpp>
15 
16 #include <restinio/http_headers.hpp>
17 #include <restinio/request_handler.hpp>
18 #include <restinio/expected.hpp>
19 
20 #include <iostream>
21 
22 namespace restinio
23 {
24 
25 namespace http_field_parsers
26 {
27 
28 namespace bearer_auth
29 {
30 
31 //
32 // params_t
33 //
34 /*!
35  * @brief Parameters for bearer authentification.
36  *
37  * @since v.0.6.7.1
38  */
39 struct params_t
40 {
41  //! Access Token.
42  /*!
43  * Can't be empty.
44  */
46 };
47 
48 //
49 // extraction_error_t
50 //
51 /*!
52  * @brief Error codes for failures of extraction of bearer authentification
53  * parameters.
54  *
55  * @since v.0.6.7.1
56  */
58 {
59  //! There is no HTTP field with authentification parameters.
61 
62  //! The HTTP field with authentification parameters can't be parsed.
64 
65  //! Different authentification scheme found.
66  //! bearer authentification scheme is expected.
68 
69  //! Invalid value of parameter for bearer authentification scheme.
70  //! The single parameter in the form of b64token is expected.
72 };
73 
74 /*!
75  * @brief Helper function to get a string name of extraction_error enum.
76  *
77  * @since v.0.6.9
78  */
79 [[nodiscard]]
80 inline string_view_t
82 {
83  string_view_t result{ "<unknown>" };
84 
85  switch( what )
86  {
87  case extraction_error_t::no_auth_http_field:
88  result = string_view_t{ "no_auth_http_field" };
89  break;
90 
91  case extraction_error_t::illegal_http_field_value:
92  result = string_view_t{ "illegal_http_field_value" };
93  break;
94 
95  case extraction_error_t::not_bearer_auth_scheme:
96  result = string_view_t{ "not_bearer_auth_scheme" };
97  break;
98 
99  case extraction_error_t::invalid_bearer_auth_param:
100  result = string_view_t{ "invalid_bearer_auth_param" };
101  break;
102  }
103 
104  return result;
105 }
106 
107 //
108 // try_extract_params
109 //
110 /*!
111  * @brief Helper function for getting parameters of bearer authentification
112  * from an already parsed HTTP-field.
113  *
114  * @attention
115  * This function doesn't check the content of
116  * authorization_value_t::auth_scheme. It's expected that this field was
117  * checked earlier.
118  *
119  * Usage example:
120  * @code
121  * auto on_request(restinio::request_handle_t & req) {
122  * using namespace restinio::http_field_parsers;
123  * const auto opt_field = req.header().opt_value_of(
124  * restinio::http_field::authorization);
125  * if(opt_field) {
126  * const auto parsed_field = authorization_value_t::try_parse(*opt_field);
127  * if(parsed_field) {
128  * if("basic" == parsed_field->auth_scheme) {
129  * ... // Dealing with Basic authentification scheme.
130  * }
131  * else if("bearer" == parsed_field->auth_scheme) {
132  * using namespace restinio::http_field_parsers::bearer_auth;
133  * const auto bearer_params = try_extract_params(*parsed_field);
134  * if(bearer_params) {
135  * const std::string & token = auth_params->token;
136  * ... // Do something with token.
137  * }
138  * }
139  * else {
140  * ... // Other authentification schemes.
141  * }
142  * }
143  * }
144  * ...
145  * }
146  * @endcode
147  *
148  * @since v.0.6.8
149  */
150 [[nodiscard]]
154 {
155  const auto * b64token = std::get_if<authorization_value_t::token68_t>(
156  &http_field.auth_param );
157  if( !b64token )
158  return make_unexpected( extraction_error_t::invalid_bearer_auth_param );
159 
160  return params_t{ b64token->value };
161 }
162 
163 /*!
164  * @brief Helper function for getting parameters of bearer authentification
165  * from an already parsed HTTP-field.
166  *
167  * @attention
168  * This function doesn't check the content of
169  * authorization_value_t::auth_scheme. It's expected that this field was
170  * checked earlier.
171  *
172  * @note
173  * This function can be used if one wants to avoid memory allocation
174  * and can reuse value of auth_params.
175  *
176  * Usage example (please note that `const` is not used in code when
177  * authorization HTTP-field is parsed):
178  * @code
179  * auto on_request(restinio::request_handle_t & req) {
180  * using namespace restinio::http_field_parsers;
181  * const auto opt_field = req.header().opt_value_of(
182  * restinio::http_field::authorization);
183  * if(opt_field) {
184  * // parsed_field is a mutable object.
185  * // The content of parsed_field->auth_param can be moved out.
186  * auto parsed_field = authorization_value_t::try_parse(*opt_field);
187  * if(parsed_field) {
188  * if("basic" == parsed_field->auth_scheme) {
189  * ... // Dealing with Basic authentification scheme.
190  * }
191  * else if("bearer" == parsed_field->auth_scheme) {
192  * using namespace restinio::http_field_parsers::bearer_auth;
193  * const auto bearer_params =
194  * // Please note the usage of std::move here.
195  * try_extract_params(std::move(*parsed_field));
196  * if(bearer_params) {
197  * const std::string & token = auth_params->token;
198  * ... // Do something with token.
199  * }
200  * }
201  * else {
202  * ... // Other authentification schemes.
203  * }
204  * }
205  * }
206  * ...
207  * }
208  * @endcode
209  *
210  * @since v.0.6.8
211  */
212 [[nodiscard]]
216 {
217  auto * b64token = std::get_if<authorization_value_t::token68_t>(
218  &http_field.auth_param );
219  if( !b64token )
220  return make_unexpected( extraction_error_t::invalid_bearer_auth_param );
221 
222  return params_t{ std::move(b64token->value) };
223 }
224 
225 namespace impl
226 {
227 
228 [[nodiscard]]
232 {
233  if( !opt_field_value )
234  return make_unexpected( extraction_error_t::no_auth_http_field );
235 
236  auto field_value_parse_result = authorization_value_t::try_parse(
237  *opt_field_value );
238  if( !field_value_parse_result )
239  return make_unexpected( extraction_error_t::illegal_http_field_value );
240 
241  auto & parsed_value = *field_value_parse_result;
242  if( "bearer" != parsed_value.auth_scheme )
243  return make_unexpected( extraction_error_t::not_bearer_auth_scheme );
244 
245  return try_extract_params( std::move(parsed_value) );
246 }
247 
248 } /* namespace impl */
249 
250 //
251 // try_extract_params
252 //
253 /*!
254  * @brief Helper function for getting parameters of bearer authentification
255  * from a set of HTTP-fields.
256  *
257  * This helper function is intended to be used for cases when authentification
258  * parameters are stored inside a HTTP-field with a custom name. For example:
259  * @code
260  * auto check_authorization(const restinio::http_header_fields_t & fields) {
261  * using namespace restinio::http_field_parsers::bearer_auth;
262  * const auto auth_params = try_extract_params(fields, "X-My-Authorization");
263  * if(auth_params) {
264  * const std::string & token = auth_params->token;
265  * ... // Do something with token.
266  * }
267  * ...
268  * }
269  * @endcode
270  *
271  * @since v.0.6.9
272  */
273 [[nodiscard]]
276  //! A set of HTTP-fields.
278  //! The name of a HTTP-field with authentification parameters.
280 {
281  return impl::perform_extraction_attempt(
282  fields.opt_value_of( auth_field_name ) );
283 }
284 
285 /*!
286  * @brief Helper function for getting parameters of bearer authentification
287  * from a request.
288  *
289  * This helper function is intended to be used for cases when authentification
290  * parameters are stored inside a HTTP-field with a custom name. For example:
291  * @code
292  * auto on_request(restinio::request_handle_t & req) {
293  * using namespace restinio::http_field_parsers::bearer_auth;
294  * const auto auth_params = try_extract_params(*req, "X-My-Authorization");
295  * if(auth_params) {
296  * const std::string & token = auth_params->token;
297  * ... // Do something with token.
298  * }
299  * ...
300  * }
301  * @endcode
302  *
303  * @since v.0.6.7.1
304  */
305 template< typename Extra_Data >
306 [[nodiscard]]
309  //! A request that should hold a HTTP-field with authentification
310  //! parameters.
311  const generic_request_t< Extra_Data > & req,
312  //! The name of a HTTP-field with authentification parameters.
314 {
316 }
317 
318 /*!
319  * @brief Helper function for getting parameters of bearer authentification
320  * from a set of HTTP-fields.
321  *
322  * Usage example:
323  * @code
324  * auto check_authorization(const restinio::http_header_fields_t & fields) {
325  * using namespace restinio::http_field_parsers::bearer_auth;
326  * const auto auth_params = try_extract_params(
327  * fields, restinio::http_field::authorization);
328  * if(auth_params) {
329  * const std::string & token = auth_params->token;
330  * ... // Do something with token.
331  * }
332  * ...
333  * }
334  * @endcode
335  *
336  * @since v.0.6.9
337  */
338 [[nodiscard]]
341  //! A set of HTTP-fields.
343  //! The ID of a HTTP-field with authentification parameters.
345 {
346  return impl::perform_extraction_attempt(
347  fields.opt_value_of( auth_field_id ) );
348 }
349 
350 /*!
351  * @brief Helper function for getting parameters of bearer authentification
352  * from a request.
353  *
354  * Usage example:
355  * @code
356  * auto on_request(restinio::request_handle_t & req) {
357  * using namespace restinio::http_field_parsers::bearer_auth;
358  * const auto auth_params = try_extract_params(
359  * *req, restinio::http_field::authorization);
360  * if(auth_params) {
361  * const std::string & token = auth_params->token;
362  * ... // Do something with token.
363  * }
364  * ...
365  * }
366  * @endcode
367  *
368  * @since v.0.6.7.1
369  */
370 template< typename Extra_Data >
371 [[nodiscard]]
374  //! A request that should hold a HTTP-field with authentification
375  //! parameters.
376  const generic_request_t< Extra_Data > & req,
377  //! The ID of a HTTP-field with authentification parameters.
379 {
381 }
382 
383 } /* namespace bearer_auth */
384 
385 } /* namespace http_field_parsers */
386 
387 } /* namespace restinio */
expected_t< std::optional< string_view_t >, not_found_t > find_first(const parameter_with_optional_value_container_t &where, string_view_t what)
A helper function to find the first occurence of a parameter with the specified value.
Definition: basics.hpp:1740
There is no HTTP field with authentification parameters.
string_view_t to_string_view(extraction_error_t what) noexcept
Helper function to get a string name of extraction_error enum.
Definition: bearer_auth.hpp:81
Parameters for bearer authentification.
Definition: bearer_auth.hpp:39
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 bearer authentification from a request. ...
expected_t< params_t, extraction_error_t > try_extract_params(authorization_value_t &&http_field)
Helper function for getting parameters of bearer authentification from an already parsed HTTP-field...
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, std::optional< Value_Type > >::type opt_value(const Parameter_Container &params, string_view_t key)
Gets the value of a parameter specified by key wrapped in std::optional<Value_Type> if parameter exis...
Definition: value_or.hpp:64
expected_t< params_t, extraction_error_t > try_extract_params(const authorization_value_t &http_field)
Helper function for getting parameters of bearer authentification from an already parsed HTTP-field...
The HTTP field with authentification parameters can&#39;t be parsed.
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 bearer authentification from a set of HTTP-fields.
extraction_error_t
Error codes for failures of extraction of bearer authentification parameters.
Definition: bearer_auth.hpp:57
Invalid value of parameter for bearer authentification scheme. The single parameter in the form of b6...
Different authentification scheme found. bearer authentification scheme is expected.