diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-09-06 07:45:00 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-09-06 07:45:00 +0000 |
commit | 2d574d2281d05383e646f20147adbc3ca8934430 (patch) | |
tree | 194c6dcfdfb0bbbaf6dd439dcd95bb6235b9a3eb | |
parent | e6c50210013371ca5c1e45e4c86178a1fc212d49 (diff) |
Strawman implementation of the OAuth 2.0 protocol. Minor improvements to the OpenID support and changes to enable it to co-exist with OAuth.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@992963 13f79535-47bb-0310-9956-ffa450edef68
43 files changed, 1160 insertions, 77 deletions
diff --git a/sca-cpp/trunk/INSTALL b/sca-cpp/trunk/INSTALL index cd8b24d9c1..d2e642f23c 100644 --- a/sca-cpp/trunk/INSTALL +++ b/sca-cpp/trunk/INSTALL @@ -157,6 +157,12 @@ To build the SQL Database utility component (requires PostgreSQL): To build the Web service utility component (requires Apache Axis2/C): --enable-webservice +To build the support for OAuth authentication: +--enable-oauth + +To build the support for OpenID authentication: +--enable-openid + To generate doxygen documentation, add: --enable-doxygen diff --git a/sca-cpp/trunk/components/cache/client-test.cpp b/sca-cpp/trunk/components/cache/client-test.cpp index 4f655c3d98..4fb4cfe4e1 100644 --- a/sca-cpp/trunk/components/cache/client-test.cpp +++ b/sca-cpp/trunk/components/cache/client-test.cpp @@ -40,7 +40,7 @@ const string memcacheuri("http://localhost:8090/memcache"); const string frontcacheuri("http://localhost:8090/frontcache"); bool testCache(const string& uri) { - http::CURLSession cs; + http::CURLSession cs("", "", ""); const list<value> i = list<value>() + (list<value>() + "name" + string("Apple")) @@ -113,7 +113,7 @@ bool testGetPerf() { + (list<value>() + "price" + string("$4.55")); const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); - http::CURLSession cs; + http::CURLSession cs("", "", ""); const failable<value> id = http::post(a, memcacheuri, cs); assert(hasContent(id)); const string p = path(content(id)); diff --git a/sca-cpp/trunk/components/chat/client-test.cpp b/sca-cpp/trunk/components/chat/client-test.cpp index 702d3ae041..2c91fda1f2 100644 --- a/sca-cpp/trunk/components/chat/client-test.cpp +++ b/sca-cpp/trunk/components/chat/client-test.cpp @@ -83,7 +83,7 @@ bool testListen() { bool testPost() { gc_scoped_pool pool; - http::CURLSession ch; + http::CURLSession ch("", "", ""); const failable<value> id = http::post(entry, "http://localhost:8090/print-sender/sca2@localhost", ch); assert(hasContent(id)); return true; diff --git a/sca-cpp/trunk/components/log/client-test.cpp b/sca-cpp/trunk/components/log/client-test.cpp index e972ed59bf..5f13f64ac1 100644 --- a/sca-cpp/trunk/components/log/client-test.cpp +++ b/sca-cpp/trunk/components/log/client-test.cpp @@ -39,7 +39,7 @@ namespace log { const string uri("http://localhost:8090/log"); bool testLog() { - http::CURLSession cs; + http::CURLSession cs("", "", ""); const list<value> i = list<value>() + (list<value>() + "name" + string("Apple")) @@ -71,7 +71,7 @@ bool testLogPerf() { + (list<value>() + "price" + string("$2.99")); const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); - http::CURLSession cs; + http::CURLSession cs("", "", ""); const failable<value> id = http::post(a, uri, cs); assert(hasContent(id)); @@ -82,7 +82,7 @@ bool testLogPerf() { } bool testLogger() { - http::CURLSession cs; + http::CURLSession cs("", "", ""); const failable<value> res = http::evalExpr(mklist<value>(string("sum"), 33, 22), string("http://localhost:8090/client"), cs); assert(hasContent(res)); diff --git a/sca-cpp/trunk/components/nosqldb/client-test.cpp b/sca-cpp/trunk/components/nosqldb/client-test.cpp index f28f084487..8eed7ce8cd 100644 --- a/sca-cpp/trunk/components/nosqldb/client-test.cpp +++ b/sca-cpp/trunk/components/nosqldb/client-test.cpp @@ -39,7 +39,7 @@ namespace nosqldb { const string uri("http://localhost:8090/nosqldb"); bool testNoSqlDb() { - http::CURLSession cs; + http::CURLSession cs("", "", ""); const list<value> i = list<value>() + (list<value>() + "name" + string("Apple")) @@ -104,7 +104,7 @@ bool testGetPerf() { + (list<value>() + "price" + string("$4.55")); const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); - http::CURLSession cs; + http::CURLSession cs("", "", ""); const failable<value> id = http::post(a, uri, cs); assert(hasContent(id)); const string p = path(content(id)); diff --git a/sca-cpp/trunk/components/queue/client-test.cpp b/sca-cpp/trunk/components/queue/client-test.cpp index c80b2d2a31..286faa2930 100644 --- a/sca-cpp/trunk/components/queue/client-test.cpp +++ b/sca-cpp/trunk/components/queue/client-test.cpp @@ -77,7 +77,7 @@ bool testListen() { bool testPost() { gc_scoped_pool pool; - http::CURLSession ch; + http::CURLSession ch("", "", ""); const failable<value> id = http::post(entry, "http://localhost:8090/print-sender", ch); assert(hasContent(id)); return true; diff --git a/sca-cpp/trunk/components/sqldb/client-test.cpp b/sca-cpp/trunk/components/sqldb/client-test.cpp index 303afe3c10..4e5c067633 100644 --- a/sca-cpp/trunk/components/sqldb/client-test.cpp +++ b/sca-cpp/trunk/components/sqldb/client-test.cpp @@ -39,7 +39,7 @@ namespace sqldb { const string uri("http://localhost:8090/sqldb"); bool testSqlDb() { - http::CURLSession cs; + http::CURLSession cs("", "", ""); const list<value> i = list<value>() + (list<value>() + "name" + string("Apple")) @@ -104,7 +104,7 @@ bool testGetPerf() { + (list<value>() + "price" + string("$4.55")); const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); - http::CURLSession cs; + http::CURLSession cs("", "", ""); const failable<value> id = http::post(a, uri, cs); assert(hasContent(id)); const string p = path(content(id)); diff --git a/sca-cpp/trunk/components/webservice/client-test.cpp b/sca-cpp/trunk/components/webservice/client-test.cpp index e666895717..658c87e2fc 100644 --- a/sca-cpp/trunk/components/webservice/client-test.cpp +++ b/sca-cpp/trunk/components/webservice/client-test.cpp @@ -60,7 +60,7 @@ bool testModAxis2() { } bool testEval() { - http::CURLSession cs; + http::CURLSession cs("", "", ""); const value func = "http://ws.apache.org/axis2/c/samples/echoString"; const list<value> arg = mklist<value>( diff --git a/sca-cpp/trunk/configure.ac b/sca-cpp/trunk/configure.ac index e5c66254e8..6f69a60e7b 100644 --- a/sca-cpp/trunk/configure.ac +++ b/sca-cpp/trunk/configure.ac @@ -508,6 +508,27 @@ else AM_CONDITIONAL([WANT_OPENID], false) fi +# Enable support for OAuth. +AC_MSG_CHECKING([whether to enable OAuth support]) +AC_ARG_ENABLE(oauth, [AS_HELP_STRING([--enable-oauth], [enable OAuth support [default=no]])], +[ case "${enableval}" in + no) + AC_MSG_RESULT(no) + ;; + *) + AC_MSG_RESULT(yes) + want_oauth=true + ;; + esac ], +[ AC_MSG_RESULT(no)]) +if test "${want_oauth}" = "true"; then + AM_CONDITIONAL([WANT_OAUTH], true) + AC_DEFINE([WANT_OAUTH], 1, [enable OAuth support]) + +else + AM_CONDITIONAL([WANT_OAUTH], false) +fi + # Enable support for Google AppEngine. AC_MSG_CHECKING([whether to enable Google AppEngine support]) AC_ARG_ENABLE(gae, [AS_HELP_STRING([--enable-gae], [enable Google AppEngine support [default=no]])], @@ -842,6 +863,7 @@ AC_CONFIG_FILES([Makefile modules/python/Makefile modules/java/Makefile modules/openid/Makefile + modules/oauth/Makefile modules/wsgi/Makefile components/Makefile components/cache/Makefile diff --git a/sca-cpp/trunk/kernel/value.hpp b/sca-cpp/trunk/kernel/value.hpp index 24688648d2..211873ef0c 100644 --- a/sca-cpp/trunk/kernel/value.hpp +++ b/sca-cpp/trunk/kernel/value.hpp @@ -28,6 +28,8 @@ #include <stdlib.h> #include <apr_uuid.h> +#include <apr_time.h> + #include "string.hpp" #include "sstream.hpp" #include "gc.hpp" @@ -601,5 +603,22 @@ const value mkuuid() { return value(string(buf, APR_UUID_FORMATTED_LENGTH)); } +/** + * Make a random alphanumeric value. + */ +const int intrand() { + const apr_uint64_t now = apr_time_now(); + srand((unsigned int)(((now >> 32) ^ now) & 0xffffffff)); + return rand() & 0x0FFFF; +} + +const value mkrand() { + char buf[32]; + const char* an = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + for (int i =0; i < 32; i++) + buf[i] = an[intrand() % 62]; + return value(string(buf, 32)); +} + } #endif /* tuscany_value_hpp */ diff --git a/sca-cpp/trunk/modules/Makefile.am b/sca-cpp/trunk/modules/Makefile.am index 0924fd04ca..fa07c599ca 100644 --- a/sca-cpp/trunk/modules/Makefile.am +++ b/sca-cpp/trunk/modules/Makefile.am @@ -15,5 +15,5 @@ # specific language governing permissions and limitations # under the License. -SUBDIRS = scheme atom rss json scdl http server python java openid wsgi +SUBDIRS = scheme atom rss json scdl http server python java openid oauth wsgi diff --git a/sca-cpp/trunk/modules/http/curl-test.cpp b/sca-cpp/trunk/modules/http/curl-test.cpp index 1d1b07bff4..a7b8fd90b6 100644 --- a/sca-cpp/trunk/modules/http/curl-test.cpp +++ b/sca-cpp/trunk/modules/http/curl-test.cpp @@ -40,7 +40,7 @@ ostream* curlWriter(const string& s, ostream* os) { } const bool testGet() { - CURLSession ch; + CURLSession ch("", "", ""); { ostringstream os; const failable<list<ostream*> > r = get<ostream*>(curlWriter, &os, testURI, ch); @@ -69,7 +69,7 @@ struct getLoop { }; const bool testGetPerf() { - CURLSession ch; + CURLSession ch("", "", ""); lambda<bool()> gl = getLoop(ch); cout << "Static GET test " << time(gl, 5, 200) << " ms" << endl; return true; diff --git a/sca-cpp/trunk/modules/http/http.hpp b/sca-cpp/trunk/modules/http/http.hpp index 6180518e23..1932ac3420 100644 --- a/sca-cpp/trunk/modules/http/http.hpp +++ b/sca-cpp/trunk/modules/http/http.hpp @@ -63,7 +63,10 @@ public: */ class CURLSession { public: - CURLSession(const string& ca = "", const string& cert = "", const string& key = "") : h(curl_easy_init()), p(gc_pool(mkpool())), sock(NULL), wpollset(NULL), wpollfd(NULL), rpollset(NULL), rpollfd(NULL), owner(true), ca(ca), cert(cert), key(key) { + CURLSession() : h(NULL), p(NULL), sock(NULL), wpollset(NULL), wpollfd(NULL), rpollset(NULL), rpollfd(NULL), owner(false), ca(""), cert(""), key("") { + } + + CURLSession(const string& ca, const string& cert, const string& key) : h(curl_easy_init()), p(gc_pool(mkpool())), sock(NULL), wpollset(NULL), wpollfd(NULL), rpollset(NULL), rpollfd(NULL), owner(true), ca(ca), cert(cert), key(key) { } CURLSession(const CURLSession& c) : h(c.h), p(c.p), sock(c.sock), wpollset(c.wpollset), wpollfd(c.wpollfd), rpollset(c.rpollset), rpollfd(c.rpollfd), owner(false), ca(c.ca), cert(c.cert), key(c.key) { @@ -86,7 +89,7 @@ private: apr_pollfd_t* wpollfd; apr_pollset_t* rpollset; apr_pollfd_t* rpollfd; - const bool owner; + bool owner; friend CURL* handle(const CURLSession& cs); friend apr_socket_t* sock(const CURLSession& cs); @@ -95,9 +98,9 @@ private: friend const failable<int> recv(char* c, const int l, const CURLSession& cs); public: - const string ca; - const string cert; - const string key; + string ca; + string cert; + string key; }; /** @@ -397,24 +400,31 @@ const failable<value> get(const string& url, const CURLSession& cs) { const list<string> ls(reverse(cadr(content(res)))); const string ct(content(contentType(car(content(res))))); - if (ct == "application/atom+xml;type=entry") { + debug(ct, "http::get::contentType"); + if (contains(ct, "application/atom+xml;type=entry")) { // Read an ATOM entry const value val(atom::entryValue(content(atom::readATOMEntry(ls)))); debug(val, "http::get::result"); return val; } - if (ct == "application/atom+xml;type=feed" || atom::isATOMFeed(ls)) { + if (contains(ct, "application/atom+xml;type=feed") || atom::isATOMFeed(ls)) { // Read an ATOM feed const value val(atom::feedValues(content(atom::readATOMFeed(ls)))); debug(val, "http::get::result"); return val; } - if (ct == "application/rss+xml" || rss::isRSSFeed(ls)) { + if (contains(ct, "application/rss+xml") || rss::isRSSFeed(ls)) { // Read an RSS feed const value val(rss::feedValues(content(rss::readRSSFeed(ls)))); debug(val, "http::get::result"); return val; } + if (contains(ct, "text/javascript") || contains(ct, "application/json-rpc")) { + json::JSONContext cx; + const value val(json::jsonValues(content(json::readJSON(ls, cx)))); + debug(val, "http::get::result"); + return val; + } // Return the content as a list of values const value val(mkvalues(ls)); diff --git a/sca-cpp/trunk/modules/http/httpd.hpp b/sca-cpp/trunk/modules/http/httpd.hpp index f1b54d79ad..f407e1012e 100644 --- a/sca-cpp/trunk/modules/http/httpd.hpp +++ b/sca-cpp/trunk/modules/http/httpd.hpp @@ -49,6 +49,7 @@ #include "string.hpp" #include "stream.hpp" +#include "sstream.hpp" #include "list.hpp" #include "value.hpp" #include "monad.hpp" @@ -60,7 +61,7 @@ namespace httpd { /** * Returns a server-scoped module configuration. */ -template<typename C> void* makeServerConf(apr_pool_t *p, server_rec *s) { +template<typename C> void* makeServerConf(apr_pool_t* p, server_rec* s) { return new (gc_new<C>(p)) C(p, s); } @@ -72,10 +73,24 @@ template<typename C> C& serverConf(const server_rec* s, const module* mod) { return *(C*)ap_get_module_config(s->module_config, mod); } -template<typename C> C& serverConf(const cmd_parms *cmd, const module* mod) { +template<typename C> C& serverConf(const cmd_parms* cmd, const module* mod) { return *(C*)ap_get_module_config(cmd->server->module_config, mod); } +/** + * Returns a directory-scoped module configuration. + */ +template<typename C> void* makeDirConf(apr_pool_t *p, char* d) { + return new (gc_new<C>(p)) C(p, d); +} + +template<typename C> const C& dirConf(const request_rec* r, const module* mod) { + return *(C*)ap_get_module_config(r->per_dir_config, mod); +} + +template<typename C> C& dirConf(const void* c) { + return *(C*)c; +} /** * Return the name of a server. @@ -172,18 +187,96 @@ const list<value> pathInfo(const list<value>& uri, const list<value>& path) { } /** + * Convert a URI and a path to an absolute URL. + */ +const string url(const string& uri, const list<value>& p, request_rec* r) { + const string u = uri + path(p); + return ap_construct_url(r->pool, c_str(u), r); +} + +/** + * Convert a URI to an absolute URL. + */ +const string url(const string& uri, request_rec* r) { + return ap_construct_url(r->pool, c_str(uri), r); +} + +/** + * Escape a URI. + */ +const char escape_c2x[] = "0123456789abcdef"; +const string escape(const string& uri) { + debug(uri, "httpd::escape::uri"); + char* copy = (char*)apr_palloc(gc_current_pool(), 3 * length(uri) + 3); + const unsigned char* s = (const unsigned char *)c_str(uri); + unsigned char* d = (unsigned char*)copy; + unsigned c; + while ((c = *s)) { + if (apr_isalnum(c) || c == '_') + *d++ = (unsigned char)c; + else if (c == ' ') + *d++ = '+'; + else { + *d++ = '%'; + *d++ = escape_c2x[c >> 4]; + *d++ = escape_c2x[c & 0xf]; + } + ++s; + } + *d = '\0'; + debug(copy, "httpd::escape::result"); + return copy; +} + +/** + * Unescape a URI. + */ +const string unescape(const string& uri) { + debug(uri, "httpd::unescape::uri"); + char* b = const_cast<char*>(c_str(string(c_str(uri)))); + ap_unescape_url(b); + debug(b, "httpd::unescape::result"); + return b; +} + +/** * Returns a list of key value pairs from the args in a query string. */ const list<value> queryArg(const string& s) { + debug(s, "httpd::queryArg::string"); const list<string> t = tokenize("=", s); return mklist<value>(c_str(car(t)), cadr(t)); } +const list<list<value> > queryArgs(const string& a) { + return map<string, list<value>>(queryArg, tokenize("&", a)); +} + +/** + * Returns a list of key value pairs from the args in an HTTP request. + */ const list<list<value> > queryArgs(const request_rec* r) { - const char* a = r->args; - if (a == NULL) + if (r->args == NULL) return list<list<value> >(); - return map<string, list<value>>(queryArg, tokenize("&", a)); + return queryArgs(r->args); +} + +/** + * Converts a list of key value pairs to a query string. + */ +ostringstream& queryString(const list<list<value> > args, ostringstream& os) { + if (isNil(args)) + return os; + debug(car(args), "httpd::queryString::arg"); + os << car(car(args)) << "=" << c_str(cadr(car(args))); + if (!isNil(cdr(args))) + os << "&"; + return queryString(cdr(args), os); +} + +const string queryString(const list<list<value> > args) { + ostringstream os; + return str(queryString(args, os)); } /** @@ -222,14 +315,6 @@ const list<string> read(request_rec* r) { } /** - * Convert a URI represented as a list to an absolute URL. - */ -const char* url(const list<value>& v, request_rec* r) { - const string u = string(r->uri) + path(v); - return ap_construct_url(r->pool, c_str(u), r); -} - -/** * Write an HTTP result. */ const failable<int> writeResult(const failable<list<string> >& ls, const string& ct, request_rec* r) { @@ -238,7 +323,7 @@ const failable<int> writeResult(const failable<list<string> >& ls, const string& ostringstream os; write(content(ls), os); const string ob(str(os)); - debug(ob, "httpd::result"); + debug(ob, "httpd::writeResult"); // Make sure browsers come back and check for updated dynamic content apr_table_setn(r->headers_out, "Expires", "Tue, 01 Jan 1980 00:00:00 GMT"); @@ -478,6 +563,16 @@ const failable<request_rec*, int> internalSubRequest(const string& nr_uri, reque } /** + * Return an HTTP external redirect request. + */ +const int externalRedirect(const string& uri, request_rec* r) { + r->status = HTTP_MOVED_TEMPORARILY; + apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, c_str(uri))); + r->filename = apr_pstrdup(r->pool, c_str(string("/redirect:/") + uri)); + return OK; +} + +/** * Put a value in the process user data. */ const bool putUserData(const string& k, const void* v, const server_rec* s) { diff --git a/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp b/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp index 0d4fe3045f..c241cd982d 100644 --- a/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp +++ b/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp @@ -68,11 +68,11 @@ extern module AP_DECLARE_DATA core_module; * Process the module configuration. */ int M_SSLTUNNEL; -int postConfigParse(ServerConf& mainsc, apr_pool_t* p, server_rec* s) { +int postConfigMerge(ServerConf& mainsc, apr_pool_t* p, server_rec* s) { if (s == NULL) return OK; ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_ssltunnel); - debug(httpd::serverName(s), "modwiring::postConfigParse::serverName"); + debug(httpd::serverName(s), "modwiring::postConfigMerge::serverName"); // Merge configuration from main server if (length(sc.ca) == 0 && length(mainsc.ca) !=0) @@ -93,7 +93,7 @@ int postConfigParse(ServerConf& mainsc, apr_pool_t* p, server_rec* s) { sc.host = uri.hostname; sc.path = uri.path; } - return postConfigParse(mainsc, p, s->next); + return postConfigMerge(mainsc, p, s->next); } int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp, server_rec* s) { @@ -104,8 +104,8 @@ int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp, // Register the SSLTUNNEL method M_SSLTUNNEL = ap_method_register(p, "SSLTUNNEL"); - // Parse the configured TunnelPass URI - return postConfigParse(sc, p, s); + // Merge and process server configurations + return postConfigMerge(sc, p, s); } /** @@ -296,7 +296,7 @@ int handler(request_rec* r) { debug(url, "modssltunnel::handler::target"); // Create the target connection - http::CURLSession cs; + http::CURLSession cs("", "", ""); // Run the tunnel return tunnel(r->connection, cs, url, "", gc_pool(r->pool), connectionFilter(r->proto_input_filters), connectionFilter(r->proto_output_filters)); diff --git a/sca-cpp/trunk/modules/json/json.hpp b/sca-cpp/trunk/modules/json/json.hpp index f904718f05..bade096b86 100644 --- a/sca-cpp/trunk/modules/json/json.hpp +++ b/sca-cpp/trunk/modules/json/json.hpp @@ -388,6 +388,13 @@ const failable<value> jsonResultValue(const list<string>& s, JSONContext& cx) { } /** + * Convert a JSON payload to a list of values. + */ +const list<value> jsonValues(const list<value>& e) { + return elementsToValues(e); +} + +/** * Return a portable function name from a JSON-RPC function name. * Strip the "system." and "Service." prefixes added by some JSON-RPC clients. */ diff --git a/sca-cpp/trunk/modules/oauth/Makefile.am b/sca-cpp/trunk/modules/oauth/Makefile.am new file mode 100644 index 0000000000..077b50bddf --- /dev/null +++ b/sca-cpp/trunk/modules/oauth/Makefile.am @@ -0,0 +1,37 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +if WANT_OAUTH + +INCLUDES = -I${HTTPD_INCLUDE} + +dist_mod_SCRIPTS = oauth-conf oauth-memcached-conf oauth-app-conf +moddir=$(prefix)/modules/oauth + +mod_LTLIBRARIES = libmod_tuscany_oauth.la +noinst_DATA = libmod_tuscany_oauth.so + +libmod_tuscany_oauth_la_SOURCES = mod-oauth.cpp +libmod_tuscany_oauth_la_LDFLAGS = -lxml2 -lcurl -lmozjs +libmod_tuscany_oauth.so: + ln -s .libs/libmod_tuscany_oauth.so + +EXTRA_DIST = oauth.composite user-info.scm htdocs/index.html htdocs/login/index.html htdocs/logout/index.html htdocs/unprotected/index.html + +dist_noinst_SCRIPTS = start-test stop-test + +endif diff --git a/sca-cpp/trunk/modules/oauth/htdocs/index.html b/sca-cpp/trunk/modules/oauth/htdocs/index.html new file mode 100644 index 0000000000..e6295a93b5 --- /dev/null +++ b/sca-cpp/trunk/modules/oauth/htdocs/index.html @@ -0,0 +1,43 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> + +<html> +<head> +<script type="text/javascript" src="/js/tuscany-ref.js"></script> +<script type="text/javascript"> +var component = new tuscany.sca.Component("Protected"); +var userInfo = new tuscany.sca.Reference("userInfo"); +var user = userInfo.apply("getuser"); +var email = userInfo.apply("getemail"); +</script> +</head> +<body> +<h1>Protected area - It works!</h1> +<p>The following info is returned by a JSONRPC service:</p> +<div id="user"></div> +<div id="email"></div> +<script type="text/javascript"> +document.getElementById('user').innerHTML="User: " + user; +document.getElementById('email').innerHTML="Email: " + email; +</script> +<p><a href="info">User info</a></p> +<p><a href="login">Sign in</a></p> +<p><a href="logout">Sign out</a></p> +<p><a href="unprotected">Unprotected area</a></p> +</body></html> diff --git a/sca-cpp/trunk/modules/oauth/htdocs/login/index.html b/sca-cpp/trunk/modules/oauth/htdocs/login/index.html new file mode 100644 index 0000000000..fcf5a870c0 --- /dev/null +++ b/sca-cpp/trunk/modules/oauth/htdocs/login/index.html @@ -0,0 +1,82 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> + +<html><body><h1>Sign in with an OAuth 2.0 provider</h1> + +<script type="text/javascript"> +function queryParams() { + qp = new Array(); + qs = window.location.search.substring(1).split('&'); + for (i = 0; i < qs.length; i++) { + e = qs[i].indexOf('='); + if (e > 0) + qp[qs[i].substring(0, e)] = unescape(qs[i].substring(e + 1)); + } + return qp; +} + +function oauthReferrer() { + r = queryParams()['mod_oauth_referrer']; + if (typeof(r) == 'undefined') + return r; + q = r.indexOf('?'); + if (q > 0) + return r.substring(0, q); + return r; +} + +if (typeof(oauthReferrer()) == 'undefined') { + document.location = '/'; +} + +function submitSignin(w) { + parms = w(); + document.signin.mod_oauth_authorize.value = parms[0]; + document.signin.mod_oauth_access_token.value = parms[1]; + document.signin.mod_oauth_client_id.value = parms[2]; + document.signin.mod_oauth_info.value = parms[3]; + document.signin.action = oauthReferrer(); + document.signin.submit(); +} + +function withFacebook() { + var parms = ['https://graph.facebook.com/oauth/authorize', 'https://graph.facebook.com/oauth/access_token', 'app1234', 'https://graph.facebook.com/me']; + return parms; +} + +function withGithub() { + var parms = ['https://github.com/login/oauth/authorize', 'https://github.com/login/oauth/access_token', 'app2345', 'https://github.com/api/v2/json/user/show']; + return parms; +} +</script> + +<form name="signin" action="/" method="GET"> +<input type="hidden" name="mod_oauth_authorize" value="https://graph.facebook.com/oauth/authorize"/> +<input type="hidden" name="mod_oauth_access_token" value="https://graph.facebook.com/oauth/access_token"/> +<input type="hidden" name="mod_oauth_client_id" value="app1234"/> +<input type="hidden" name="mod_oauth_info" value="https://graph.facebook.com/me"/> +<input type="hidden" name="mod_oauth_step" value="authorize"/> +</form> + +<form name="fields"> +<p>Sign in with your Facebook account<br/><input type="button" onclick="submitSignin(withFacebook)" value="Sign in"/></p> +<p>Sign in with your Github account<br/><input type="button" onclick="submitSignin(withGithub)" value="Sign in"/></p> +</form> + +</body></html> diff --git a/sca-cpp/trunk/modules/oauth/htdocs/logout/index.html b/sca-cpp/trunk/modules/oauth/htdocs/logout/index.html new file mode 100644 index 0000000000..02a92d1b31 --- /dev/null +++ b/sca-cpp/trunk/modules/oauth/htdocs/logout/index.html @@ -0,0 +1,33 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> + +<html><body> +<h1>Sign out</h1> + +<form name="signout" action="/login" method="GET"> +<script type="text/javascript"> +function submitSignout() { + document.cookie = 'TuscanyOpenAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/;secure=TRUE'; + document.signout.submit(); + return true; +} +</script> +<input type="button" onclick="submitSignout()" value="Sign out"/> +</form> +</body></html> diff --git a/sca-cpp/trunk/modules/oauth/htdocs/unprotected/index.html b/sca-cpp/trunk/modules/oauth/htdocs/unprotected/index.html new file mode 100644 index 0000000000..af2cd7ca19 --- /dev/null +++ b/sca-cpp/trunk/modules/oauth/htdocs/unprotected/index.html @@ -0,0 +1,27 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> + +<html> +<body> +<h1>Unprotected area - It works!</h1> +<p><a href="/info">User info</a></p> +<p><a href="/login">Sign in</a></p> +<p><a href="/logout">Sign out</a></p> +<p><a href="/">Protected area</a></p> +</body></html> diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth.cpp new file mode 100644 index 0000000000..9a0c9aa078 --- /dev/null +++ b/sca-cpp/trunk/modules/oauth/mod-oauth.cpp @@ -0,0 +1,415 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +/** + * HTTPD module for OAuth 2.0 authentication. + */ + +#include <sys/stat.h> + +#include "string.hpp" +#include "stream.hpp" +#include "list.hpp" +#include "tree.hpp" +#include "value.hpp" +#include "monad.hpp" +#include "../http/httpd.hpp" +#include "../http/http.hpp" +#include "../../components/cache/memcache.hpp" + +extern "C" { +extern module AP_MODULE_DECLARE_DATA mod_tuscany_oauth; +} + +namespace tuscany { +namespace oauth { + +/** + * Server configuration. + */ +class ServerConf { +public: + ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s) { + } + + const gc_pool p; + server_rec* server; + string ca; + string cert; + string key; + list<list<value> > apps; + list<string> mcaddrs; + memcache::MemCached mc; + http::CURLSession cs; +}; + +/** + * Directory configuration. + */ +class DirConf { +public: + DirConf(apr_pool_t* p, char* d) : p(p), dir(d), enabled(false), login("") { + } + + const gc_pool p; + const char* dir; + bool enabled; + string login; +}; + +/** + * Check user authentication. + */ +static int checkUserID(request_rec *r) { + // Decline if we're not enabled or AuthType is not set to Open + const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_oauth); + if (!dc.enabled) + return DECLINED; + const char* atype = ap_auth_type(r); + if (atype == NULL || strcasecmp(atype, "Open")) + return DECLINED; + + gc_scoped_pool pool(r->pool); + httpdDebugRequest(r, "modoauth::checkUserID::input"); + return OK; +} + +/** + * Return the session id from a request. + */ +const maybe<string> sessionID(const list<string> c) { + if (isNil(c)) + return maybe<string>(); + const list<string> kv = tokenize("=", car(c)); + if (!isNil(kv) && !isNil(cdr(kv))) { + if (car(kv) == "TuscanyOpenAuth") + return cadr(kv); + } + return sessionID(cdr(c)); +} + +const maybe<string> sessionID(const request_rec* r) { + const char* c = apr_table_get(r->headers_in, "Cookie"); + debug(c, "modoauth::sessionid::cookies"); + if (c == NULL) + return maybe<string>(); + return sessionID(tokenize(";", c)); +} + +/** + * Return the user info for a session. + */ +const failable<value> userInfo(const value& sid, const ServerConf& sc) { + return memcache::get(mklist<value>("tuscanyOpenAuth", sid), sc.mc); +} + +/** + * Handle an authenticated request. + */ +const failable<int> authenticated(const list<list<value> >& info, request_rec* r) { + debug(info, "modoauth::authenticated::info"); + + const list<value> id = assoc<value>("id", info); + r->user = apr_pstrdup(r->pool, c_str(cadr(id))); + + const list<value> email = assoc<value>("email", info); + apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "EMAIL"), apr_pstrdup(r->pool, c_str(cadr(email)))); + + const list<value> fullname = assoc<value>("name", info); + apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "NICKNAME"), apr_pstrdup(r->pool, c_str(cadr(fullname)))); + apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "FULLNAME"), apr_pstrdup(r->pool, c_str(cadr(fullname)))); + + const list<value> firstname = assoc<value>("first_name", info); + apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "FIRSTNAME"), apr_pstrdup(r->pool, c_str(cadr(firstname)))); + + const list<value> lastname = assoc<value>("last_name", info); + apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "LASTNAME"), apr_pstrdup(r->pool, c_str(cadr(lastname)))); + + if(r->ap_auth_type == NULL) + r->ap_auth_type = const_cast<char*>("OAuth"); + return DECLINED; +} + +/** + * Redirect to the configured login page. + */ +const failable<int> login(const string& page, request_rec* r) { + const list<list<value> > largs = mklist<list<value> >(mklist<value>("mod_oauth_referrer", httpd::escape(httpd::url(r->uri, r)))); + const string loc = httpd::url(page, r) + string("?") + httpd::queryString(largs); + debug(loc, "modoauth::login::uri"); + return httpd::externalRedirect(loc, r); +} + +/** + * Handle an authorize request. + */ +const failable<int> authorize(const list<list<value> >& args, request_rec* r) { + // Extract authorize URI, access_token URI and client ID + const list<value> auth = assoc<value>("mod_oauth_authorize", args); + const list<value> tok = assoc<value>("mod_oauth_access_token", args); + const list<value> cid = assoc<value>("mod_oauth_client_id", args); + const list<value> info = assoc<value>("mod_oauth_info", args); + + // Build the redirect URI + const list<list<value> > rargs = mklist<list<value> >(mklist<value>("mod_oauth_step", "access_token"), tok, cid, info); + const string redir = httpd::url(r->uri, r) + string("?") + httpd::queryString(rargs); + debug(redir, "modoauth::authorize::redir"); + + // Redirect to the authorize URI + const list<list<value> > aargs = mklist<list<value> >(mklist<value>("client_id", cadr(cid)), mklist<value>("scope", "email"), mklist<value>("redirect_uri", httpd::escape(redir))); + const string uri = httpd::unescape(cadr(auth)) + string("?") + httpd::queryString(aargs); + debug(uri, "modoauth::authorize::uri"); + return httpd::externalRedirect(uri, r); +} + +/** + * Convert a session id to a cookie string. + */ +const string cookie(const string& sid) { + const time_t t = time(NULL) + 86400; + char exp[32]; + strftime(exp, 32, "%a, %d-%b-%Y %H:%M:%S GMT", gmtime(&t)); + const string c = string("TuscanyOpenAuth=") + sid + string(";path=/;expires=" + string(exp)) + ";secure=TRUE"; + debug(c, "modoauth::cookie"); + return c; +} + +/** + * Handle an access_token request. + */ +const failable<int> access_token(const list<list<value> >& args, request_rec* r, const ServerConf& sc) { + // Extract access_token URI, client ID and authorization code + const list<value> tok = assoc<value>("mod_oauth_access_token", args); + const list<value> cid = assoc<value>("mod_oauth_client_id", args); + const list<value> info = assoc<value>("mod_oauth_info", args); + const list<value> code = assoc<value>("code", args); + + // Lookup client app configuration + const list<value> app = assoc<value>(cadr(cid), sc.apps); + + // Build the redirect URI + const list<list<value> > rargs = mklist<list<value> >(mklist<value>("mod_oauth_step", "access_token"), tok, cid, info); + const string redir = httpd::url(r->uri, r) + string("?") + httpd::queryString(rargs); + debug(redir, "modoauth::access_token::redir"); + + // Request access token + const list<list<value> > targs = mklist<list<value> >(mklist<value>("client_id", cadr(cid)), mklist<value>("redirect_uri", httpd::escape(redir)), mklist<value>("client_secret", cadr(app)), code); + const string turi = httpd::unescape(cadr(tok)) + string("?") + httpd::queryString(targs); + debug(turi, "modoauth::access_token::tokenuri"); + const failable<value> tr = http::get(turi, sc.cs); + debug(tr, "modoauth::access_token::response"); + const list<value> tv = assoc<value>("access_token", httpd::queryArgs(join("", convertValues<string>(content(tr))))); + debug(tv, "modoauth::access_token::token"); + + // Request user info + const list<list<value> > iargs = mklist<list<value> >(tv); + const string iuri = httpd::unescape(cadr(info)) + string("?") + httpd::queryString(iargs); + debug(iuri, "modoauth::access_token::infouri"); + const failable<value> iv = http::get(iuri, sc.cs); + debug(iv, "modoauth::access_token::info"); + + // Store user info in memcached keyed by session ID + const value sid = mkrand(); + memcache::put(mklist<value>("tuscanyOpenAuth", sid), content(iv), sc.mc); + + // Send session ID to the client in a cookie + apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie(sid))); + return httpd::externalRedirect(httpd::url(r->uri, r), r); +} + +/** + * Handle a request. + */ +int handler(request_rec* r) { + // Decline if we're not enabled or if the user is already + // authenticated by another module + const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_oauth); + if(!dc.enabled) + return DECLINED; + if (r->user != NULL || apr_table_get(r->subprocess_env, "SSL_REMOTE_USER") != NULL) + return DECLINED; + + gc_scoped_pool pool(r->pool); + httpdDebugRequest(r, "modoauth::handler::input"); + const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_oauth); + + // Nothing to do if we're already authenticated + const maybe<string> sid = sessionID(r); + if (hasContent(sid)) { + const failable<value> info = userInfo(content(sid), sc); + if (hasContent(info)) + return httpd::reportStatus(authenticated(content(info), r)); + } + + // Get the current protocol flow step from the query string + const list<list<value> > args = httpd::queryArgs(r); + const list<value> sl = assoc<value>("mod_oauth_step", args); + const value step = !isNil(sl) && !isNil(cdr(sl))? cadr(sl) : ""; + + // Handle an authorize request + if (step == "authorize") + return httpd::reportStatus(authorize(args, r)); + + // Handle an access_token request + if (step == "access_token") + return httpd::reportStatus(access_token(args, r, sc)); + + // Redirect to the login page + return httpd::reportStatus(login(dc.login, r)); +} + +/** + * Process the module configuration. + */ +int postConfigMerge(ServerConf& mainsc, server_rec* s) { + if (s == NULL) + return OK; + ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_oauth); + debug(httpd::serverName(s), "modoauth::postConfigMerge::serverName"); + + // Merge configuration from main server + if (isNil(sc.apps)) + sc.apps = mainsc.apps; + sc.mc = mainsc.mc; + sc.cs = mainsc.cs; + + return postConfigMerge(mainsc, s->next); +} + +int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp, server_rec* s) { + gc_scoped_pool pool(p); + ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_oauth); + debug(httpd::serverName(s), "modoauth::postConfig::serverName"); + + // Merge server configurations + return postConfigMerge(sc, s); +} + +/** + * Child process initialization. + */ +void childInit(apr_pool_t* p, server_rec* s) { + gc_scoped_pool pool(p); + ServerConf* psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_oauth); + if(psc == NULL) { + cfailure << "[Tuscany] Due to one or more errors mod_tuscany_oauth loading failed. Causing apache to stop loading." << endl; + exit(APEXIT_CHILDFATAL); + } + ServerConf& sc = *psc; + + // Connect to Memcached + if (isNil(sc.mcaddrs)) + sc.mc = *(new (gc_new<memcache::MemCached>()) memcache::MemCached("localhost", 11211)); + else + sc.mc = *(new (gc_new<memcache::MemCached>()) memcache::MemCached(sc.mcaddrs)); + + // Setup a CURL session + sc.cs = *(new (gc_new<http::CURLSession>()) http::CURLSession(sc.ca, sc.cert, sc.key)); + + // Merge the updated configuration into the virtual hosts + postConfigMerge(sc, s->next); +} + +/** + * Configuration commands. + */ +const char* confApp(cmd_parms *cmd, unused void *c, const char *arg1, const char* arg2) { + gc_scoped_pool pool(cmd->pool); + ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth); + sc.apps = cons<list<value> >(mklist<value>(arg1, arg2), sc.apps); + return NULL; +} +const char* confMemcached(cmd_parms *cmd, unused void *c, const char *arg) { + gc_scoped_pool pool(cmd->pool); + ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth); + sc.mcaddrs = cons<string>(arg, sc.mcaddrs); + return NULL; +} +const char* confEnabled(cmd_parms *cmd, void *c, const int arg) { + gc_scoped_pool pool(cmd->pool); + DirConf& dc = httpd::dirConf<DirConf>(c); + dc.enabled = (bool)arg; + debug(dc.dir, "modoauth::confEnabled::dir"); + debug(dc.enabled, "modoauth::confEnabled::enabled"); + return NULL; +} +const char* confLogin(cmd_parms *cmd, void *c, const char* arg) { + gc_scoped_pool pool(cmd->pool); + DirConf& dc = httpd::dirConf<DirConf>(c); + dc.login = arg; + return NULL; +} +const char* confCAFile(cmd_parms *cmd, unused void *c, const char *arg) { + gc_scoped_pool pool(cmd->pool); + ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth); + sc.ca = arg; + return NULL; +} +const char* confCertFile(cmd_parms *cmd, unused void *c, const char *arg) { + gc_scoped_pool pool(cmd->pool); + ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth); + sc.cert = arg; + return NULL; +} +const char* confCertKeyFile(cmd_parms *cmd, unused void *c, const char *arg) { + gc_scoped_pool pool(cmd->pool); + ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth); + sc.key = arg; + return NULL; +} + +/** + * HTTP server module declaration. + */ +const command_rec commands[] = { + AP_INIT_ITERATE2("AddAuthOAuthApp", (const char*(*)())confApp, NULL, RSRC_CONF, "OAuth app-id app-secret"), + AP_INIT_ITERATE("AddAuthOAuthMemcached", (const char*(*)())confMemcached, NULL, RSRC_CONF, "Memcached server host:port"), + AP_INIT_FLAG("AuthOAuth", (const char*(*)())confEnabled, NULL, OR_AUTHCFG, "OAuth authentication On | Off"), + AP_INIT_TAKE1("AuthOAuthLoginPage", (const char*(*)())confLogin, NULL, OR_AUTHCFG, "OAuth login page"), + AP_INIT_TAKE1("AuthOAuthSSLCACertificateFile", (const char*(*)())confCAFile, NULL, RSRC_CONF, "OAUth SSL CA certificate file"), + AP_INIT_TAKE1("AuthOAuthSSLCertificateFile", (const char*(*)())confCertFile, NULL, RSRC_CONF, "OAuth SSL certificate file"), + AP_INIT_TAKE1("AuthOAuthSSLCertificateKeyFile", (const char*(*)())confCertKeyFile, NULL, RSRC_CONF, "OAuth SSL certificate key file"), + {NULL, NULL, NULL, 0, NO_ARGS, NULL} +}; + +void registerHooks(unused apr_pool_t *p) { + ap_hook_post_config(postConfig, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_child_init(childInit, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_check_user_id(checkUserID, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_handler(handler, NULL, NULL, APR_HOOK_MIDDLE); +} + +} +} + +extern "C" { + +module AP_MODULE_DECLARE_DATA mod_tuscany_oauth = { + STANDARD20_MODULE_STUFF, + // dir config and merger + tuscany::httpd::makeDirConf<tuscany::oauth::DirConf>, NULL, + // server config and merger + tuscany::httpd::makeServerConf<tuscany::oauth::ServerConf>, NULL, + // commands and hooks + tuscany::oauth::commands, tuscany::oauth::registerHooks +}; + +} diff --git a/sca-cpp/trunk/modules/oauth/oauth-app-conf b/sca-cpp/trunk/modules/oauth/oauth-app-conf new file mode 100755 index 0000000000..56beb0af95 --- /dev/null +++ b/sca-cpp/trunk/modules/oauth/oauth-app-conf @@ -0,0 +1,32 @@ +#!/bin/sh + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +here=`readlink -f $0`; here=`dirname $here` +mkdir -p $1 +root=`readlink -f $1` +id=$2 +secret=$3 + +# Configure an OAuth App +cat >>$root/conf/httpd.conf <<EOF +# Generated by: oauth-app-conf $* +AddAuthOAuthApp $id $secret + +EOF + diff --git a/sca-cpp/trunk/modules/oauth/oauth-conf b/sca-cpp/trunk/modules/oauth/oauth-conf new file mode 100755 index 0000000000..7123d8710e --- /dev/null +++ b/sca-cpp/trunk/modules/oauth/oauth-conf @@ -0,0 +1,64 @@ +#!/bin/sh + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Generate an OAuth server conf +here=`readlink -f $0`; here=`dirname $here` +mkdir -p $1 +root=`readlink -f $1` + +conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"` +host=`echo $conf | awk '{ print $6 }'` + +# Configure HTTPD mod_tuscany_oauth module +cat >>$root/conf/httpd.conf <<EOF +# Generated by: oauth-conf $* +# Load support for OAuth authentication +LoadModule mod_tuscany_oauth $here/libmod_tuscany_oauth.so + +# Enable OAuth authentication +<Location /> +AuthType Open +AuthOAuth On +AuthOAuthLoginPage /login +</Location> + +# Enable unauthenticated access to unprotected areas +<Location /login> +AuthOAuth Off +</Location> +<Location /logout> +AuthOAuth Off +</Location> +<Location /unprotected> +AuthOAuth Off +</Location> + +EOF + +cat >>$root/conf/vhost-ssl.conf <<EOF +# Generated by: openid-conf $* +# Require OAuth authentication +<Location /> +AuthType Open +AuthName "$host" +Require valid-user +</Location> + +EOF + diff --git a/sca-cpp/trunk/modules/oauth/oauth-memcached-conf b/sca-cpp/trunk/modules/oauth/oauth-memcached-conf new file mode 100755 index 0000000000..8c133688d7 --- /dev/null +++ b/sca-cpp/trunk/modules/oauth/oauth-memcached-conf @@ -0,0 +1,32 @@ +#!/bin/sh + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +here=`readlink -f $0`; here=`dirname $here` +mkdir -p $1 +root=`readlink -f $1` +host=$2 +port=$3 + +# Configure HTTPD mod_tuscany_oauth module cache +cat >>$root/conf/httpd.conf <<EOF +# Generated by: oauth-cache-conf $* +AddAuthOAuthMemcached $host:$port + +EOF + diff --git a/sca-cpp/trunk/modules/oauth/oauth.composite b/sca-cpp/trunk/modules/oauth/oauth.composite new file mode 100644 index 0000000000..b1fc095ce5 --- /dev/null +++ b/sca-cpp/trunk/modules/oauth/oauth.composite @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" + xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" + targetNamespace="http://tuscany.apache.org/xmlns/sca/components" + name="oauth"> + + <component name="Protected"> + <t:implementation.widget location="protected/index.html"/> + <reference name="userInfo" target="UserInfo"/> + </component> + + <component name="UserInfo"> + <t:implementation.scheme script="user-info.scm"/> + <service name="info"> + <t:binding.jsonrpc uri="info"/> + </service> + <property name="user">anonymous</property> + <property name="email">anonymous@example.com</property> + </component> + +</composite> diff --git a/sca-cpp/trunk/modules/oauth/start-test b/sca-cpp/trunk/modules/oauth/start-test new file mode 100755 index 0000000000..0946397f1a --- /dev/null +++ b/sca-cpp/trunk/modules/oauth/start-test @@ -0,0 +1,42 @@ +#!/bin/sh + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Setup +../../components/cache/memcached-start 11212 +../../components/cache/memcached-start 11213 + +../../modules/http/ssl-ca-conf tmp localhost +../../modules/http/ssl-cert-conf tmp localhost +../../modules/http/httpd-conf tmp localhost 8090 htdocs +../../modules/http/httpd-ssl-conf tmp 8453 + +./oauth-conf tmp +./oauth-memcached-conf tmp localhost 11212 +./oauth-memcached-conf tmp localhost 11213 +./oauth-app-conf tmp app1234 secret6789 + +../../modules/server/server-conf tmp +../../modules/server/scheme-conf tmp +cat >>tmp/conf/httpd.conf <<EOF +SCAContribution `pwd`/ +SCAComposite oauth.composite +EOF + +../../modules/http/httpd-start tmp + diff --git a/sca-cpp/trunk/modules/oauth/stop-test b/sca-cpp/trunk/modules/oauth/stop-test new file mode 100755 index 0000000000..a0587f8cb7 --- /dev/null +++ b/sca-cpp/trunk/modules/oauth/stop-test @@ -0,0 +1,24 @@ +#!/bin/sh + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Cleanup +../../modules/http/httpd-stop tmp + +../../components/cache/memcached-stop 11212 +../../components/cache/memcached-stop 11213 diff --git a/sca-cpp/trunk/modules/oauth/user-info.scm b/sca-cpp/trunk/modules/oauth/user-info.scm new file mode 100644 index 0000000000..0c4ebcfaf7 --- /dev/null +++ b/sca-cpp/trunk/modules/oauth/user-info.scm @@ -0,0 +1,26 @@ +; Licensed to the Apache Software Foundation (ASF) under one +; or more contributor license agreements. See the NOTICE file +; distributed with this work for additional information +; regarding copyright ownership. The ASF licenses this file +; to you under the Apache License, Version 2.0 (the +; "License"); you may not use this file except in compliance +; with the License. You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, +; software distributed under the License is distributed on an +; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +; KIND, either express or implied. See the License for the +; specific language governing permissions and limitations +; under the License. + +; OAuth support test case + +(define (get id user email) (list "text/html" (list + "<html><body><p>The following info is generated on the server:</p><div>User: " (user) "</div><div>Email: " (email) "</div></body></html>"))) + +(define (getuser user email) (user)) + +(define (getemail user email) (email)) + diff --git a/sca-cpp/trunk/modules/openid/Makefile.am b/sca-cpp/trunk/modules/openid/Makefile.am index a613f2ef78..ba6e523ad2 100644 --- a/sca-cpp/trunk/modules/openid/Makefile.am +++ b/sca-cpp/trunk/modules/openid/Makefile.am @@ -25,7 +25,7 @@ mod_DATA = openid.prefix openid.prefix: $(top_builddir)/config.status echo ${MODAUTHOPENID_PREFIX} >openid.prefix -EXTRA_DIST = openid.composite user-info.scm htdocs/index.html htdocs/login/index.html htdocs/logout/index.html htdocs/protected/index.html +EXTRA_DIST = openid.composite user-info.scm htdocs/index.html htdocs/login/index.html htdocs/logout/index.html htdocs/unprotected/index.html dist_noinst_SCRIPTS = start-test stop-test diff --git a/sca-cpp/trunk/modules/openid/htdocs/login/index.html b/sca-cpp/trunk/modules/openid/htdocs/login/index.html index 14f378e968..e6b8c6fce3 100644 --- a/sca-cpp/trunk/modules/openid/htdocs/login/index.html +++ b/sca-cpp/trunk/modules/openid/htdocs/login/index.html @@ -68,6 +68,10 @@ function withVerisign() { return 'https://pip.verisignlabs.com/'; } +function withMySpace() { + return 'https://api.myspace.com/openid'; +} + function withGoogleApps() { return 'https://www.google.com/accounts/o8/site-xrds?ns=2&hd=' + document.fields.domain.value; } @@ -86,6 +90,7 @@ function withXRDSEndpoint() { <p>Sign in with your Yahoo account<br/><input type="button" onclick="submitSignin(withYahoo)" value="Sign in"/></p> <p>Sign in with your MyOpenID account<br/><input type="button" onclick="submitSignin(withMyOpenID)" value="Sign in"/></p> <p>Sign in with your Verisign account<br/><input type="button" onclick="submitSignin(withVerisign)" value="Sign in"/></p> +<p>Sign in with your MySpace account<br/><input type="button" onclick="submitSignin(withMySpace)" value="Sign in"/></p> <p>Sign in with a Google apps domain<br/> <input type="text" size="20" name="domain" value="example.com"/><br/> <input type="button" onclick="submitSignin(withGoogleApps)" value="Sign in"/></p> diff --git a/sca-cpp/trunk/modules/openid/htdocs/logout/index.html b/sca-cpp/trunk/modules/openid/htdocs/logout/index.html index 5b58a1c38b..02a92d1b31 100644 --- a/sca-cpp/trunk/modules/openid/htdocs/logout/index.html +++ b/sca-cpp/trunk/modules/openid/htdocs/logout/index.html @@ -23,7 +23,7 @@ <form name="signout" action="/login" method="GET"> <script type="text/javascript"> function submitSignout() { - document.cookie = 'TuscanyOpenIDAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/;secure=TRUE'; + document.cookie = 'TuscanyOpenAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/;secure=TRUE'; document.signout.submit(); return true; } diff --git a/sca-cpp/trunk/modules/openid/openid-conf b/sca-cpp/trunk/modules/openid/openid-conf index a8314261ac..95cdb1945c 100755 --- a/sca-cpp/trunk/modules/openid/openid-conf +++ b/sca-cpp/trunk/modules/openid/openid-conf @@ -34,13 +34,17 @@ LoadModule authopenid_module $openid_prefix/modules/mod_auth_openid.so # Enable OpenID authentication <Location /> -AuthType OpenID +AuthType Open AuthOpenIDEnabled On AuthOpenIDCookiePath / -AuthOpenIDCookieName TuscanyOpenIDAuth +AuthOpenIDCookieName TuscanyOpenAuth AuthOpenIDSecureCookie On AuthOpenIDLoginPage /login AuthOpenIDAXAdd EMAIL http://axschema.org/contact/email +AuthOpenIDAXAdd FULLNAME http://axschema.org/namePerson +AuthOpenIDAXAdd NICKNAME http://axschema.org/namePerson/friendly +AuthOpenIDAXAdd FIRSTNAME http://axschema.org/namePerson/first +AuthOpenIDAXAdd LASTNAME http://axschema.org/namePerson/last </Location> # Enable unauthenticated access to unprotected areas @@ -60,7 +64,7 @@ cat >>$root/conf/vhost-ssl.conf <<EOF # Generated by: openid-conf $* # Require OpenID authentication <Location /> -AuthType OpenID +AuthType Open AuthName "$host" Require valid-user </Location> diff --git a/sca-cpp/trunk/modules/server/client-test.hpp b/sca-cpp/trunk/modules/server/client-test.hpp index f2fdb60877..c17f012012 100644 --- a/sca-cpp/trunk/modules/server/client-test.hpp +++ b/sca-cpp/trunk/modules/server/client-test.hpp @@ -46,7 +46,7 @@ ostream* curlWriter(const string& s, ostream* os) { const bool testGet() { gc_scoped_pool pool; - http::CURLSession ch; + http::CURLSession ch("", "", ""); { ostringstream os; const failable<list<ostream*> > r = http::get<ostream*>(curlWriter, &os, "http://localhost:8090/index.html", ch); @@ -76,7 +76,7 @@ struct getLoop { const bool testGetPerf() { gc_scoped_pool pool; - http::CURLSession ch; + http::CURLSession ch("", "", ""); const lambda<bool()> gl = getLoop(ch); cout << "Static GET test " << time(gl, 5, 200) << " ms" << endl; return true; @@ -84,7 +84,7 @@ const bool testGetPerf() { const bool testEval() { gc_scoped_pool pool; - http::CURLSession ch; + http::CURLSession ch("", "", ""); const value val = content(http::evalExpr(mklist<value>(string("echo"), string("Hello")), testURI, ch)); assert(val == string("Hello")); return true; @@ -119,7 +119,7 @@ struct blobEvalLoop { const bool testEvalPerf() { gc_scoped_pool pool; - http::CURLSession ch; + http::CURLSession ch("", "", ""); const lambda<bool()> el = evalLoop(testURI, ch); cout << "JSON-RPC eval echo test " << time(el, 5, 200) << " ms" << endl; @@ -136,7 +136,7 @@ bool testPost() { + (list<value>() + "name" + string("Apple")) + (list<value>() + "price" + string("$2.99")); const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); - http::CURLSession ch; + http::CURLSession ch("", "", ""); const failable<value> id = http::post(a, testURI, ch); assert(hasContent(id)); return true; @@ -171,7 +171,7 @@ struct postBlobLoop { const bool testPostPerf() { gc_scoped_pool pool; - http::CURLSession ch; + http::CURLSession ch("", "", ""); { const list<value> i = list<value>() + (list<value>() + "name" + string("Apple")) @@ -197,7 +197,7 @@ const bool testPostPerf() { const bool postThread(const string& uri, const int count, const value& val) { gc_scoped_pool pool; - http::CURLSession ch; + http::CURLSession ch("", "", ""); const lambda<bool()> pl = postLoop(uri, val, ch); time(pl, 0, count); return true; @@ -251,7 +251,7 @@ const bool testPostThreadPerf() { const bool postProc(const string& uri, const int count, const value& val) { gc_scoped_pool pool; - http::CURLSession ch; + http::CURLSession ch("", "", ""); const lambda<bool()> pl = postLoop(uri, val, ch); time(pl, 0, count); return true; @@ -315,7 +315,7 @@ const bool testPut() { + (list<value>() + "name" + string("Apple")) + (list<value>() + "price" + string("$2.99")); const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); - http::CURLSession ch; + http::CURLSession ch("", "", ""); value rc = content(http::put(a, testURI + "/111", ch)); assert(rc == value(true)); return true; @@ -323,7 +323,7 @@ const bool testPut() { const bool testDel() { gc_scoped_pool pool; - http::CURLSession ch; + http::CURLSession ch("", "", ""); value rc = content(http::del(testURI + "/111", ch)); assert(rc == value(true)); return true; diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp index 95c3d7cd09..40164530b7 100644 --- a/sca-cpp/trunk/modules/server/mod-eval.hpp +++ b/sca-cpp/trunk/modules/server/mod-eval.hpp @@ -194,7 +194,7 @@ const failable<int> post(request_rec* r, const lambda<value(const list<value>&)> // Return the created resource location debug(content(val), "modeval::post::location"); - apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, httpd::url(content(val), r))); + apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, c_str(httpd::url(r->uri, content(val), r)))); r->status = HTTP_CREATED; return OK; } @@ -366,15 +366,16 @@ struct hostPropProxy { } }; -struct emailPropProxy { +struct envPropProxy { + const string name; const value v; - emailPropProxy(const value& v) : v(v) { + envPropProxy(const string& name, const value& v) : name(name), v(v) { } const value operator()(unused const list<value>& params) const { - const char* email = apr_table_get(currentRequest->subprocess_env, "EMAIL"); - if (email == NULL || *email == '\0') + const char* env = apr_table_get(currentRequest->subprocess_env, c_str(name)); + if (env == NULL || *env == '\0') return v; - return string(email); + return string(env); } }; @@ -392,10 +393,18 @@ struct userPropProxy { const value mkpropProxy(const value& prop) { if (scdl::name(prop) == "host") return lambda<value(const list<value>&)>(hostPropProxy(elementValue(prop))); - if (scdl::name(prop) == "email") - return lambda<value(const list<value>&)>(emailPropProxy(elementValue(prop))); if (scdl::name(prop) == "user") return lambda<value(const list<value>&)>(userPropProxy(elementValue(prop))); + if (scdl::name(prop) == "email") + return lambda<value(const list<value>&)>(envPropProxy("EMAIL", elementValue(prop))); + if (scdl::name(prop) == "nickname") + return lambda<value(const list<value>&)>(envPropProxy("NICKNAME", elementValue(prop))); + if (scdl::name(prop) == "fullname") + return lambda<value(const list<value>&)>(envPropProxy("FULLNAME", elementValue(prop))); + if (scdl::name(prop) == "firstname") + return lambda<value(const list<value>&)>(envPropProxy("FIRSTNAME", elementValue(prop))); + if (scdl::name(prop) == "lastname") + return lambda<value(const list<value>&)>(envPropProxy("LASTNAME", elementValue(prop))); return lambda<value(const list<value>&)>(propProxy(elementValue(prop))); } @@ -828,7 +837,6 @@ const char* confCertKeyFile(cmd_parms *cmd, unused void *c, const char *arg) { sc.key = arg; return NULL; } - const char* confEnv(unused cmd_parms *cmd, unused void *c, const char *name, const char *value) { gc_scoped_pool pool(cmd->pool); setenv(name, value != NULL? value : "", 1); diff --git a/sca-cpp/trunk/modules/server/mod-wiring.cpp b/sca-cpp/trunk/modules/server/mod-wiring.cpp index 188aa620fb..1a7105013c 100644 --- a/sca-cpp/trunk/modules/server/mod-wiring.cpp +++ b/sca-cpp/trunk/modules/server/mod-wiring.cpp @@ -112,12 +112,9 @@ int translateReference(const ServerConf& sc, request_rec *r) { return OK; } - r->status = HTTP_MOVED_TEMPORARILY; - apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, c_str(target))); - r->filename = apr_pstrdup(r->pool, c_str(string("/redirect:/") + target)); debug(target, "modwiring::translateReference::location"); r->handler = "mod_tuscany_wiring"; - return OK; + return httpd::externalRedirect(target, r); } // Route to a relative target URI using a local internal redirect @@ -397,8 +394,7 @@ int postConfig(apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp, */ void childInit(apr_pool_t* p, server_rec* s) { gc_scoped_pool pool(p); - ServerConf *conf = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_wiring); - if(conf == NULL) { + if(ap_get_module_config(s->module_config, &mod_tuscany_wiring) == NULL) { cfailure << "[Tuscany] Due to one or more errors mod_tuscany_wiring loading failed. Causing apache to stop loading." << endl; exit(APEXIT_CHILDFATAL); } diff --git a/sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/login/index.html b/sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/login/index.html index 14f378e968..e6b8c6fce3 100644 --- a/sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/login/index.html +++ b/sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/login/index.html @@ -68,6 +68,10 @@ function withVerisign() { return 'https://pip.verisignlabs.com/'; } +function withMySpace() { + return 'https://api.myspace.com/openid'; +} + function withGoogleApps() { return 'https://www.google.com/accounts/o8/site-xrds?ns=2&hd=' + document.fields.domain.value; } @@ -86,6 +90,7 @@ function withXRDSEndpoint() { <p>Sign in with your Yahoo account<br/><input type="button" onclick="submitSignin(withYahoo)" value="Sign in"/></p> <p>Sign in with your MyOpenID account<br/><input type="button" onclick="submitSignin(withMyOpenID)" value="Sign in"/></p> <p>Sign in with your Verisign account<br/><input type="button" onclick="submitSignin(withVerisign)" value="Sign in"/></p> +<p>Sign in with your MySpace account<br/><input type="button" onclick="submitSignin(withMySpace)" value="Sign in"/></p> <p>Sign in with a Google apps domain<br/> <input type="text" size="20" name="domain" value="example.com"/><br/> <input type="button" onclick="submitSignin(withGoogleApps)" value="Sign in"/></p> diff --git a/sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/logout/index.html b/sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/logout/index.html index 55cbfac110..02a92d1b31 100644 --- a/sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/logout/index.html +++ b/sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/logout/index.html @@ -23,7 +23,7 @@ <form name="signout" action="/login" method="GET"> <script type="text/javascript"> function submitSignout() { - document.cookie = 'open_id_session_id=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/'; + document.cookie = 'TuscanyOpenAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/;secure=TRUE'; document.signout.submit(); return true; } diff --git a/sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/login/index.html b/sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/login/index.html index 14f378e968..e6b8c6fce3 100644 --- a/sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/login/index.html +++ b/sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/login/index.html @@ -68,6 +68,10 @@ function withVerisign() { return 'https://pip.verisignlabs.com/'; } +function withMySpace() { + return 'https://api.myspace.com/openid'; +} + function withGoogleApps() { return 'https://www.google.com/accounts/o8/site-xrds?ns=2&hd=' + document.fields.domain.value; } @@ -86,6 +90,7 @@ function withXRDSEndpoint() { <p>Sign in with your Yahoo account<br/><input type="button" onclick="submitSignin(withYahoo)" value="Sign in"/></p> <p>Sign in with your MyOpenID account<br/><input type="button" onclick="submitSignin(withMyOpenID)" value="Sign in"/></p> <p>Sign in with your Verisign account<br/><input type="button" onclick="submitSignin(withVerisign)" value="Sign in"/></p> +<p>Sign in with your MySpace account<br/><input type="button" onclick="submitSignin(withMySpace)" value="Sign in"/></p> <p>Sign in with a Google apps domain<br/> <input type="text" size="20" name="domain" value="example.com"/><br/> <input type="button" onclick="submitSignin(withGoogleApps)" value="Sign in"/></p> diff --git a/sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/logout/index.html b/sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/logout/index.html index 55cbfac110..02a92d1b31 100644 --- a/sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/logout/index.html +++ b/sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/logout/index.html @@ -23,7 +23,7 @@ <form name="signout" action="/login" method="GET"> <script type="text/javascript"> function submitSignout() { - document.cookie = 'open_id_session_id=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/'; + document.cookie = 'TuscanyOpenAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/;secure=TRUE'; document.signout.submit(); return true; } diff --git a/sca-cpp/trunk/samples/store-cluster/htdocs/login/index.html b/sca-cpp/trunk/samples/store-cluster/htdocs/login/index.html index 14f378e968..e6b8c6fce3 100644 --- a/sca-cpp/trunk/samples/store-cluster/htdocs/login/index.html +++ b/sca-cpp/trunk/samples/store-cluster/htdocs/login/index.html @@ -68,6 +68,10 @@ function withVerisign() { return 'https://pip.verisignlabs.com/'; } +function withMySpace() { + return 'https://api.myspace.com/openid'; +} + function withGoogleApps() { return 'https://www.google.com/accounts/o8/site-xrds?ns=2&hd=' + document.fields.domain.value; } @@ -86,6 +90,7 @@ function withXRDSEndpoint() { <p>Sign in with your Yahoo account<br/><input type="button" onclick="submitSignin(withYahoo)" value="Sign in"/></p> <p>Sign in with your MyOpenID account<br/><input type="button" onclick="submitSignin(withMyOpenID)" value="Sign in"/></p> <p>Sign in with your Verisign account<br/><input type="button" onclick="submitSignin(withVerisign)" value="Sign in"/></p> +<p>Sign in with your MySpace account<br/><input type="button" onclick="submitSignin(withMySpace)" value="Sign in"/></p> <p>Sign in with a Google apps domain<br/> <input type="text" size="20" name="domain" value="example.com"/><br/> <input type="button" onclick="submitSignin(withGoogleApps)" value="Sign in"/></p> diff --git a/sca-cpp/trunk/samples/store-cluster/htdocs/logout/index.html b/sca-cpp/trunk/samples/store-cluster/htdocs/logout/index.html index 5b58a1c38b..02a92d1b31 100644 --- a/sca-cpp/trunk/samples/store-cluster/htdocs/logout/index.html +++ b/sca-cpp/trunk/samples/store-cluster/htdocs/logout/index.html @@ -23,7 +23,7 @@ <form name="signout" action="/login" method="GET"> <script type="text/javascript"> function submitSignout() { - document.cookie = 'TuscanyOpenIDAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/;secure=TRUE'; + document.cookie = 'TuscanyOpenAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/;secure=TRUE'; document.signout.submit(); return true; } diff --git a/sca-cpp/trunk/ubuntu/ubuntu-install-all b/sca-cpp/trunk/ubuntu/ubuntu-install-all index 288e73ae9a..9a717781e7 100755 --- a/sca-cpp/trunk/ubuntu/ubuntu-install-all +++ b/sca-cpp/trunk/ubuntu/ubuntu-install-all @@ -323,7 +323,7 @@ git clone git://git.apache.org/tuscany-sca-cpp.git cd tuscany-sca-cpp cp etc/git-exclude .git/info/exclude ./bootstrap -./configure --prefix=$build/tuscany-sca-cpp-bin --with-curl=$build/curl-7.19.5-bin --with-apr=$build/httpd-2.2.16-bin --with-httpd=$build/httpd-2.2.16-bin --with-memcached=$build/memcached-1.4.4-bin --with-tinycdb=$build/tinycdb-0.77-bin --with-js-include=$build/tracemonkey-bin/include/js --with-js-lib=$build/tracemonkey-bin/lib --with-libcloud=$build/libcloud-0.3.1-bin --enable-threads --enable-python --enable-gae --with-gae=$build/google_appengine --enable-java --with-java=/usr/lib/jvm/java-6-openjdk --enable-webservice --with-libxml2=$build/libxml2-2.7.7-bin --with-axis2c=$build/axis2c-1.6.0-bin --enable-queue --with-qpidc=$build/qpidc-0.6-bin --enable-chat --with-libstrophe=$build/libstrophe-bin --with-vysper=$build/vysper-0.5 --enable-sqldb --with-pgsql=$build/postgresql-9.0-bin --enable-log --with-thrift=$build/thrift-0.2.0-bin --with-scribe=$build/scribe-2.2-bin --enable-openid --with-mod-auth-openid=$build/mod-auth-openid-bin +./configure --prefix=$build/tuscany-sca-cpp-bin --with-curl=$build/curl-7.19.5-bin --with-apr=$build/httpd-2.2.16-bin --with-httpd=$build/httpd-2.2.16-bin --with-memcached=$build/memcached-1.4.4-bin --with-tinycdb=$build/tinycdb-0.77-bin --with-js-include=$build/tracemonkey-bin/include/js --with-js-lib=$build/tracemonkey-bin/lib --with-libcloud=$build/libcloud-0.3.1-bin --enable-threads --enable-python --enable-gae --with-gae=$build/google_appengine --enable-java --with-java=/usr/lib/jvm/java-6-openjdk --enable-webservice --with-libxml2=$build/libxml2-2.7.7-bin --with-axis2c=$build/axis2c-1.6.0-bin --enable-queue --with-qpidc=$build/qpidc-0.6-bin --enable-chat --with-libstrophe=$build/libstrophe-bin --with-vysper=$build/vysper-0.5 --enable-sqldb --with-pgsql=$build/postgresql-9.0-bin --enable-log --with-thrift=$build/thrift-0.2.0-bin --with-scribe=$build/scribe-2.2-bin --enable-openid --with-mod-auth-openid=$build/mod-auth-openid-bin --enable-oauth make make install if [ "$?" != "0" ]; then |