#ifndef __OPKELE_OAUTH_CONSUMER_H #define __OPKELE_OAUTH_CONSUMER_H #include #include #include #include namespace opkele { /** * @brief OAuth support namespace */ namespace oauth { using std::string; /** * oauth parameter passing method */ enum oauth_method_t { /** * via WWW-Authenticate header */ oauth_auth_header, /** * via POST body */ oauth_post_body, /** * via GET query string */ oauth_url_query, /** * default method */ oauth_method_default = oauth_auth_header }; /** * Service endpoint description */ struct service_endpoint_t { /** * endpoint URI */ string url; /** * signature method */ string signature_method; /** * OAuth parameter passing method */ oauth_method_t oauth_method; service_endpoint_t() : oauth_method(oauth_method_default) { } /** * @param u endpoint URI * @param sm signature method * @param om OAuth parameter passing method */ service_endpoint_t(const string& u,const string& sm,oauth_method_t om=oauth_method_default) : url(u), signature_method(sm), oauth_method(om) { } }; /** * Base class for OAuth provider endpoints description */ class basic_provider_endpoints { public: virtual ~basic_provider_endpoints() { } /** * Retrieve endpoint for obtaining an unauthorized request token * @return service endpoint description */ virtual const service_endpoint_t& get_request_token_endpoint() const = 0; /** * Retrieve endpoint for user authorization * @return service endpoint description */ virtual const service_endpoint_t& get_authorize_user_endpoint() const = 0; /** * Retrieve endpoint for obtaining an access token from the * authorized request token * @return service endpoint description */ virtual const service_endpoint_t& get_access_token_endpoint() const = 0; /** * Make up an endpoint description give an URI * @param sep reference to the service endpoint description object to fill in * @param url endpoint URL * @return reference to sep */ virtual service_endpoint_t& get_url_endpoint(service_endpoint_t& sep, const string& url) const = 0; }; /** * HTTP request information */ struct http_request_t { /** * WWW-Authenticate header */ string authorize_header; /** * HTTP method */ string method; /** * Target URL */ string url; /** * POST body */ string body; /** * curl-ready headers */ util::curl_slist_t _curl_headers_list; /** * @param m HTTP method * @param u target URL */ http_request_t(const string& m,const string& u) : method(m), url(u) { } /** * Set relevant curl handle options */ void setup_curl(CURL *curl); }; /** * OAuth consumer base class */ class basic_consumer { public: /** * Consumer token */ token_t consumer_token; /** * @param ct consumer token */ basic_consumer(const token_t& ct) : consumer_token(ct) { } virtual ~basic_consumer() { } /** * Retrieve reference to the provider endpoints description object * @return reference to the provider endpoints description object */ virtual const basic_provider_endpoints& get_endpoints() const = 0; /** * Allocate nonce * @param ts request timestamp * @return nonce string */ virtual const string allocate_nonce(time_t ts) = 0; /** * Obtain an unauthorized request token * @return request token */ token_t get_request_token(); /** * Retrieve the user authorization URL * @param rt unauthorized request token * @param callback callback URL to be passed to oauth provider * to redirect user to upon authorization * @return user authorization URL */ const string get_authorize_url(const token_t& rt,const string& callback=""); /** * Trade an authorized request token for an access token * @param rt authorized request token * @return access token */ token_t get_access_token(const token_t& rt); /** * Prepare http request parameters * @param req request description to fill in * @param qf query string parameters * @param pf post body parameters * @param om OAuth method * @param sm signature method * @param t pointer to the token to use to sign request, if any. * @param realm authorization realm * @return reference to req */ http_request_t& prepare_request( http_request_t& req, const basic_fields& qf,const basic_fields& pf, oauth_method_t om,const string& sm, const token_t *t=0,const string& realm=""); /** * Prepare http request parameters * @param req request description to fill in * @param qf query string parameters * @param pf post body parameters * @param sep service endpoint description * @param t pointer to the token to use to sign request, if any. * @param realm authorization realm * @return reference to req */ http_request_t& prepare_request( http_request_t& req, const basic_fields& qf,const basic_fields& pf, const service_endpoint_t& sep, const token_t *t=0,const string& realm=""); /** * Prepare http request parameters * @param req request description to fill in * @param qf query string parameters * @param pf post body parameters * @param t pointer to the token to use to sign request, if any. * @param realm authorization realm * @return reference to req */ http_request_t& prepare_request( http_request_t& req, const basic_fields& qf,const basic_fields& pf, const token_t *t=0,const string& realm=""); /** * Calculate request signature * @param method http method * @param url the url being invoked * @param fields all request fields (query string, auth header, * post body) * @param rt pointer to the request token to be used for * signing, if any. */ const string signature( const string& method, const string& url, const basic_fields& fields, const token_t* rt=0); /** * Acquire token from an OAuth provider * @param sep service endpoint description * @param rt pointer to the request token to use for signing, * if any * @return the acquired token */ token_t acquire_token( const service_endpoint_t& sep, const token_t* rt=0); }; class simple_provider_endpoints : public basic_provider_endpoints { public: service_endpoint_t sep_request_token; service_endpoint_t sep_authorize_user; service_endpoint_t sep_access_token; service_endpoint_t sep_generic; /** * @param rt request token endpoint URL * @param au user authorization endpoint URL * @param at access token endpoint URL * @param sm signature method * @param ams authentication method for service endpoints * @param amr authentication method for resource access */ simple_provider_endpoints( const string& rt,const string& au,const string& at, const string& sm, oauth_method_t ams=oauth_post_body, oauth_method_t amr=oauth_auth_header ) : sep_request_token(rt,sm,ams), sep_authorize_user(au,sm,oauth_url_query), sep_access_token(at,sm,ams), sep_generic("",sm,amr) { } const service_endpoint_t& get_request_token_endpoint() const; const service_endpoint_t& get_authorize_user_endpoint() const; const service_endpoint_t& get_access_token_endpoint() const; service_endpoint_t& get_url_endpoint(service_endpoint_t& sep, const string& url) const; }; class simple_consumer : public basic_consumer { public: simple_provider_endpoints peps; /** * @param eps provider endpoints * @param ct consumer token * @see simple_provider_endpoints * @see token_t */ simple_consumer(const simple_provider_endpoints& eps, const token_t& ct) : basic_consumer(ct), peps(eps) { } const basic_provider_endpoints& get_endpoints() const; const string allocate_nonce(time_t ts); }; } } #endif /* __OPKELE_OAUTH_CONSUMER_H */