summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/modules/oauth
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/trunk/modules/oauth')
-rw-r--r--sca-cpp/trunk/modules/oauth/htdocs/login/index.html70
-rw-r--r--sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html76
-rw-r--r--sca-cpp/trunk/modules/oauth/htdocs/logout/index.html11
-rw-r--r--sca-cpp/trunk/modules/oauth/mod-oauth1.cpp87
-rw-r--r--sca-cpp/trunk/modules/oauth/mod-oauth2.cpp123
-rwxr-xr-xsca-cpp/trunk/modules/oauth/start-mixed-test25
-rwxr-xr-xsca-cpp/trunk/modules/oauth/start-test21
7 files changed, 232 insertions, 181 deletions
diff --git a/sca-cpp/trunk/modules/oauth/htdocs/login/index.html b/sca-cpp/trunk/modules/oauth/htdocs/login/index.html
index d1002f79ec..02439154e7 100644
--- a/sca-cpp/trunk/modules/oauth/htdocs/login/index.html
+++ b/sca-cpp/trunk/modules/oauth/htdocs/login/index.html
@@ -44,7 +44,7 @@ function queryParams() {
function oauthReferrer() {
r = queryParams()['openauth_referrer'];
if (typeof(r) == 'undefined')
- return r;
+ return '/';
q = r.indexOf('?');
if (q > 0)
return r.substring(0, q);
@@ -55,38 +55,48 @@ if (typeof(oauthReferrer()) == 'undefined') {
document.location = '/';
}
+function clearauthcookie() {
+ document.cookie = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/';
+ document.cookie = 'TuscanyOAuth1=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/';
+ document.cookie = 'TuscanyOAuth2=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/';
+ document.cookie = 'TuscanyOpenIDAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/';
+ return true;
+}
+
function submitSignin2(w) {
parms = w();
- var reset = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + window.location.hostname + '; path=/';
- document.cookie = reset;
- document.signin2.mod_oauth2_authorize.value = parms[0];
- document.signin2.mod_oauth2_access_token.value = parms[1];
- document.signin2.mod_oauth2_client_id.value = parms[2];
- document.signin2.mod_oauth2_info.value = parms[3];
- document.signin2.action = oauthReferrer();
+ clearauthcookie();
+ document.signin2.oauth2_authorize.value = parms[0];
+ document.signin2.oauth2_access_token.value = parms[1];
+ document.signin2.oauth2_client_id.value = parms[2];
+ document.signin2.oauth2_info.value = parms[3];
+ document.signin2.oauth2_scope.value = parms[4];
+ document.signin2.oauth2_display.value = parms[5];
+ document.signin2.openauth_referrer.value = oauthReferrer();
+ document.signin2.action = '/oauth2/authorize/';
document.signin2.submit();
}
function withFacebook() {
- var parms = ['https://graph.facebook.com/oauth/authorize', 'https://graph.facebook.com/oauth/access_token', 'facebook.com', 'https://graph.facebook.com/me'];
+ var parms = ['https://graph.facebook.com/oauth/authorize', 'https://graph.facebook.com/oauth/access_token', 'facebook.com', 'https://graph.facebook.com/me', 'email', 'page'];
return parms;
}
function withGithub() {
- var parms = ['https://github.com/login/oauth/authorize', 'https://github.com/login/oauth/access_token', 'github.com', 'https://github.com/api/v2/json/user/show'];
+ var parms = ['https://github.com/login/oauth/authorize', 'https://github.com/login/oauth/access_token', 'github.com', 'https://github.com/api/v2/json/user/show', 'email', ''];
return parms;
}
function submitSignin1(w) {
parms = w();
- var reset = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + window.location.hostname + '; path=/';
- document.cookie = reset;
- document.signin1.mod_oauth1_request_token.value = parms[0];
- document.signin1.mod_oauth1_authorize.value = parms[1];
- document.signin1.mod_oauth1_access_token.value = parms[2];
- document.signin1.mod_oauth1_client_id.value = parms[3];
- document.signin1.mod_oauth1_info.value = parms[4];
- document.signin1.action = oauthReferrer();
+ clearauthcookie();
+ document.signin1.oauth1_request_token.value = parms[0];
+ document.signin1.oauth1_authorize.value = parms[1];
+ document.signin1.oauth1_access_token.value = parms[2];
+ document.signin1.oauth1_client_id.value = parms[3];
+ document.signin1.oauth1_info.value = parms[4];
+ document.signin1.openauth_referrer.value = oauthReferrer();
+ document.signin1.action = '/oauth1/authorize/';
document.signin1.submit();
}
@@ -109,20 +119,22 @@ function withTwitter() {
</form>
<form name="signin2" action="/" method="GET">
-<input type="hidden" name="mod_oauth2_authorize" value=""/>
-<input type="hidden" name="mod_oauth2_access_token" value=""/>
-<input type="hidden" name="mod_oauth2_client_id" value=""/>
-<input type="hidden" name="mod_oauth2_info" value=""/>
-<input type="hidden" name="mod_oauth2_step" value="authorize"/>
+<input type="hidden" name="oauth2_authorize" value=""/>
+<input type="hidden" name="oauth2_access_token" value=""/>
+<input type="hidden" name="oauth2_client_id" value=""/>
+<input type="hidden" name="oauth2_info" value=""/>
+<input type="hidden" name="oauth2_scope" value=""/>
+<input type="hidden" name="oauth2_display" value=""/>
+<input type="hidden" name="openauth_referrer" value=""/>
</form>
<form name="signin1" action="/" method="GET">
-<input type="hidden" name="mod_oauth1_request_token" value=""/>
-<input type="hidden" name="mod_oauth1_authorize" value=""/>
-<input type="hidden" name="mod_oauth1_access_token" value=""/>
-<input type="hidden" name="mod_oauth1_client_id" value=""/>
-<input type="hidden" name="mod_oauth1_info" value=""/>
-<input type="hidden" name="mod_oauth1_step" value="authorize"/>
+<input type="hidden" name="oauth1_request_token" value=""/>
+<input type="hidden" name="oauth1_authorize" value=""/>
+<input type="hidden" name="oauth1_access_token" value=""/>
+<input type="hidden" name="oauth1_client_id" value=""/>
+<input type="hidden" name="oauth1_info" value=""/>
+<input type="hidden" name="openauth_referrer" value=""/>
</form>
</body>
diff --git a/sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html b/sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html
index 57484dc479..50d70f04e4 100644
--- a/sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html
+++ b/sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html
@@ -29,9 +29,16 @@
<h1>Sign in with a Form, an OpenID provider or an OAuth provider</h1>
<script type="text/javascript">
+function clearauthcookie() {
+ document.cookie = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/';
+ document.cookie = 'TuscanyOAuth1=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/';
+ document.cookie = 'TuscanyOAuth2=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/';
+ document.cookie = 'TuscanyOpenIDAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/';
+ return true;
+}
+
function submitFormSignin() {
- var reset = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + window.location.hostname + '; path=/';
- document.cookie = reset;
+ clearauthcookie();
document.formSignin.httpd_location.value = '/';
document.formSignin.submit();
}
@@ -50,7 +57,7 @@ function queryParams() {
function openauthReferrer() {
r = queryParams()['openauth_referrer'];
if (typeof(r) == 'undefined')
- return r;
+ return '/';
q = r.indexOf('?');
if (q > 0)
return r.substring(0, q);
@@ -62,8 +69,7 @@ if (typeof(openauthReferrer()) == 'undefined') {
}
function submitOpenIDSignin(w) {
- var reset = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + window.location.hostname + '; path=/';
- document.cookie = reset;
+ clearauthcookie();
document.openIDSignin.openid_identifier.value = w();
document.openIDSignin.action = openauthReferrer();
document.openIDSignin.submit();
@@ -111,36 +117,38 @@ function withXRDSEndpoint() {
function submitOAuth2Signin(w) {
parms = w();
- var reset = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + window.location.hostname + '; path=/';
- document.cookie = reset;
- document.oauth2Signin.mod_oauth2_authorize.value = parms[0];
- document.oauth2Signin.mod_oauth2_access_token.value = parms[1];
- document.oauth2Signin.mod_oauth2_client_id.value = parms[2];
- document.oauth2Signin.mod_oauth2_info.value = parms[3];
- document.oauth2Signin.action = openauthReferrer();
+ clearauthcookie();
+ document.oauth2Signin.oauth2_authorize.value = parms[0];
+ document.oauth2Signin.oauth2_access_token.value = parms[1];
+ document.oauth2Signin.oauth2_client_id.value = parms[2];
+ document.oauth2Signin.oauth2_info.value = parms[3];
+ document.oauth2Signin.oauth2_scope.value = parms[4];
+ document.oauth2Signin.oauth2_display.value = parms[5];
+ document.oauth2Signin.openauth_referrer.value = openauthReferrer();
+ document.oauth2Signin.action = '/oauth2/authorize/';
document.oauth2Signin.submit();
}
function withFacebook() {
- var parms = ['https://graph.facebook.com/oauth/authorize', 'https://graph.facebook.com/oauth/access_token', 'facebook.com', 'https://graph.facebook.com/me'];
+ var parms = ['https://graph.facebook.com/oauth/authorize', 'https://graph.facebook.com/oauth/access_token', 'facebook.com', 'https://graph.facebook.com/me', 'email', 'page'];
return parms;
}
function withGithub() {
- var parms = ['https://github.com/login/oauth/authorize', 'https://github.com/login/oauth/access_token', 'github.com', 'https://github.com/api/v2/json/user/show'];
+ var parms = ['https://github.com/login/oauth/authorize', 'https://github.com/login/oauth/access_token', 'github.com', 'https://github.com/api/v2/json/user/show', 'email', ''];
return parms;
}
function submitOAuth1Signin(w) {
parms = w();
- var reset = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + window.location.hostname + '; path=/';
- document.cookie = reset;
- document.oauth1Signin.mod_oauth1_request_token.value = parms[0];
- document.oauth1Signin.mod_oauth1_authorize.value = parms[1];
- document.oauth1Signin.mod_oauth1_access_token.value = parms[2];
- document.oauth1Signin.mod_oauth1_client_id.value = parms[3];
- document.oauth1Signin.mod_oauth1_info.value = parms[4];
- document.oauth1Signin.action = openauthReferrer();
+ clearauthcookie();
+ document.oauth1Signin.oauth1_request_token.value = parms[0];
+ document.oauth1Signin.oauth1_authorize.value = parms[1];
+ document.oauth1Signin.oauth1_access_token.value = parms[2];
+ document.oauth1Signin.oauth1_client_id.value = parms[3];
+ document.oauth1Signin.oauth1_info.value = parms[4];
+ document.oauth1Signin.openauth_referrer.value = openauthReferrer();
+ document.oauth1Signin.action = '/oauth1/authorize/';
document.oauth1Signin.submit();
}
@@ -205,20 +213,22 @@ function withTwitter() {
</form>
<form name="oauth2Signin" action="/" method="GET">
-<input type="hidden" name="mod_oauth2_authorize" value=""/>
-<input type="hidden" name="mod_oauth2_access_token" value=""/>
-<input type="hidden" name="mod_oauth2_client_id" value=""/>
-<input type="hidden" name="mod_oauth2_info" value=""/>
-<input type="hidden" name="mod_oauth2_step" value="authorize"/>
+<input type="hidden" name="oauth2_authorize" value=""/>
+<input type="hidden" name="oauth2_access_token" value=""/>
+<input type="hidden" name="oauth2_client_id" value=""/>
+<input type="hidden" name="oauth2_info" value=""/>
+<input type="hidden" name="oauth2_scope" value=""/>
+<input type="hidden" name="oauth2_display" value=""/>
+<input type="hidden" name="openauth_referrer" value=""/>
</form>
<form name="oauth1Signin" action="/" method="GET">
-<input type="hidden" name="mod_oauth1_request_token" value=""/>
-<input type="hidden" name="mod_oauth1_authorize" value=""/>
-<input type="hidden" name="mod_oauth1_access_token" value=""/>
-<input type="hidden" name="mod_oauth1_client_id" value=""/>
-<input type="hidden" name="mod_oauth1_info" value=""/>
-<input type="hidden" name="mod_oauth1_step" value="authorize"/>
+<input type="hidden" name="oauth1_request_token" value=""/>
+<input type="hidden" name="oauth1_authorize" value=""/>
+<input type="hidden" name="oauth1_access_token" value=""/>
+<input type="hidden" name="oauth1_client_id" value=""/>
+<input type="hidden" name="oauth1_info" value=""/>
+<input type="hidden" name="openauth_referrer" value=""/>
</form>
</body>
diff --git a/sca-cpp/trunk/modules/oauth/htdocs/logout/index.html b/sca-cpp/trunk/modules/oauth/htdocs/logout/index.html
index 35172da07f..a9d2e628d7 100644
--- a/sca-cpp/trunk/modules/oauth/htdocs/logout/index.html
+++ b/sca-cpp/trunk/modules/oauth/htdocs/logout/index.html
@@ -31,9 +31,16 @@
<form name="signout" action="/login" method="GET">
<script type="text/javascript">
+function clearauthcookie() {
+ document.cookie = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/';
+ document.cookie = 'TuscanyOAuth1=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/';
+ document.cookie = 'TuscanyOAuth2=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/';
+ document.cookie = 'TuscanyOpenIDAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/';
+ return true;
+}
+
function submitSignout() {
- var reset = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + window.location.hostname + '; path=/';
- document.cookie = reset;
+ clearauthcookie();
document.signout.submit();
return true;
}
diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp
index 1276ea4855..29fe756178 100644
--- a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp
+++ b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp
@@ -89,7 +89,7 @@ public:
* Return the user info for a session.
*/
const failable<value> userInfo(const value& sid, const memcache::MemCached& mc) {
- return memcache::get(mklist<value>("tuscanyOpenAuth", sid), mc);
+ return memcache::get(mklist<value>("tuscanyOAuth1", sid), mc);
}
/**
@@ -174,25 +174,28 @@ const list<string> sign(const string& verb, const string& uri, const list<value>
*/
const failable<int> authorize(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const memcache::MemCached& mc) {
// Extract authorize, access_token, client ID and info URIs
- const list<value> req = assoc<value>("mod_oauth1_request_token", args);
+ const list<value> ref = assoc<value>("openauth_referrer", args);
+ if (isNil(ref) || isNil(cdr(ref)))
+ return mkfailure<int>("Missing openauth_referrer parameter");
+ const list<value> req = assoc<value>("oauth1_request_token", args);
if (isNil(req) || isNil(cdr(req)))
- return mkfailure<int>("Missing mod_oauth1_request_token parameter");
- const list<value> auth = assoc<value>("mod_oauth1_authorize", args);
+ return mkfailure<int>("Missing oauth1_request_token parameter");
+ const list<value> auth = assoc<value>("oauth1_authorize", args);
if (isNil(auth) || isNil(cdr(auth)))
- return mkfailure<int>("Missing mod_oauth1_authorize parameter");
- const list<value> tok = assoc<value>("mod_oauth1_access_token", args);
+ return mkfailure<int>("Missing oauth1_authorize parameter");
+ const list<value> tok = assoc<value>("oauth1_access_token", args);
if (isNil(tok) || isNil(cdr(tok)))
- return mkfailure<int>("Missing mod_oauth1_access_token parameter");
- const list<value> cid = assoc<value>("mod_oauth1_client_id", args);
+ return mkfailure<int>("Missing oauth1_access_token parameter");
+ const list<value> cid = assoc<value>("oauth1_client_id", args);
if (isNil(cid) || isNil(cdr(cid)))
- return mkfailure<int>("Missing mod_oauth1_client_id parameter");
- const list<value> info = assoc<value>("mod_oauth1_info", args);
+ return mkfailure<int>("Missing oauth1_client_id parameter");
+ const list<value> info = assoc<value>("oauth1_info", args);
if (isNil(info) || isNil(cdr(info)))
- return mkfailure<int>("Missing mod_oauth1_info parameter");
+ return mkfailure<int>("Missing oauth1_info parameter");
// Build the redirect URI
- const list<list<value> > redirargs = mklist<list<value> >(mklist<value>("mod_oauth1_step", "access_token"), tok, cid, info);
- const string redir = httpd::url(r->uri, r) + string("?") + http::queryString(redirargs);
+ const list<list<value> > redirargs = mklist<list<value> >(tok, cid, info, ref);
+ const string redir = httpd::url("/oauth1/access_token/", r) + string("?") + http::queryString(redirargs);
debug(redir, "modoauth1::authorize::redir");
// Lookup client app configuration
@@ -296,15 +299,18 @@ const failable<list<value> > profileUserInfo(const value& cid, const string& inf
*/
const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const memcache::MemCached& mc) {
// Extract access_token URI, client ID and verification code
- const list<value> tok = assoc<value>("mod_oauth1_access_token", args);
+ const list<value> ref = assoc<value>("openauth_referrer", args);
+ if (isNil(ref) || isNil(cdr(ref)))
+ return mkfailure<int>("Missing openauth_referrer parameter");
+ const list<value> tok = assoc<value>("oauth1_access_token", args);
if (isNil(tok) || isNil(cdr(tok)))
- return mkfailure<int>("Missing mod_oauth1_access_token parameter");
- const list<value> cid = assoc<value>("mod_oauth1_client_id", args);
+ return mkfailure<int>("Missing oauth1_access_token parameter");
+ const list<value> cid = assoc<value>("oauth1_client_id", args);
if (isNil(cid) || isNil(cdr(cid)))
- return mkfailure<int>("Missing mod_oauth1_client_id parameter");
- const list<value> info = assoc<value>("mod_oauth1_info", args);
+ return mkfailure<int>("Missing oauth1_client_id parameter");
+ const list<value> info = assoc<value>("oauth1_info", args);
if (isNil(info) || isNil(cdr(info)))
- return mkfailure<int>("Missing mod_oauth1_info parameter");
+ return mkfailure<int>("Missing oauth1_info parameter");
const list<value> tv = assoc<value>("oauth_token", args);
if (isNil(tv) || isNil(cdr(tv)))
return mkfailure<int>("Missing oauth_token parameter");
@@ -372,14 +378,14 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r,
// Store user info in memcached keyed by session ID
const value sid = string("OAuth1_") + mkrand();
- const failable<bool> prc = memcache::put(mklist<value>("tuscanyOpenAuth", sid), content(iv), mc);
+ const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth1", sid), content(iv), mc);
if (!hasContent(prc))
return mkfailure<int>(reason(prc));
// Send session ID to the client in a cookie
- debug(c_str(openauth::cookie(sid, httpd::hostName(r))), "modoauth1::access_token::setcookie");
- apr_table_set(r->err_headers_out, "Set-Cookie", c_str(openauth::cookie(sid, httpd::hostName(r))));
- return httpd::externalRedirect(httpd::url(r->uri, r), r);
+ debug(c_str(openauth::cookie("TuscanyOAuth1", sid, httpd::hostName(r))), "modoauth1::access_token::setcookie");
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(openauth::cookie("TuscanyOAuth1", sid, httpd::hostName(r))));
+ return httpd::externalRedirect(httpd::url(httpd::unescape(cadr(ref)), r), r);
}
/**
@@ -391,6 +397,7 @@ static int checkAuthn(request_rec *r) {
if (!dc.enabled)
return DECLINED;
const char* atype = ap_auth_type(r);
+ debug(atype, "modopenauth::checkAuthn::auth_type");
if (atype == NULL || strcasecmp(atype, "Open"))
return DECLINED;
@@ -398,11 +405,11 @@ static int checkAuthn(request_rec *r) {
gc_scoped_pool pool(r->pool);
// Get the server configuration
- httpdDebugRequest(r, "modoauth1::checkAuthn::input");
+ debug_httpdRequest(r, "modoauth1::checkAuthn::input");
const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_oauth1);
// Get session id from the request
- const maybe<string> sid = openauth::sessionID(r);
+ const maybe<string> sid = openauth::sessionID(r, "TuscanyOAuth1");
if (hasContent(sid)) {
// Decline if the session id was not created by this module
if (substr(content(sid), 0, 7) != "OAuth1_")
@@ -416,33 +423,25 @@ static int checkAuthn(request_rec *r) {
}
}
- // Get the request args
- const list<list<value> > args = httpd::queryArgs(r);
-
- // Decline if the request is for another authentication provider
- if (!isNil(assoc<value>("openid_identifier", args)))
- return DECLINED;
- if (!isNil(assoc<value>("mod_oauth2_step", args)))
- return DECLINED;
-
- // Determine the OAuth protocol flow step, conveniently passed
- // around in a request arg
- const list<value> sl = assoc<value>("mod_oauth1_step", args);
- const value step = !isNil(sl) && !isNil(cdr(sl))? cadr(sl) : "";
-
// Handle OAuth authorize request step
- if (step == "authorize") {
+ if (string(r->uri) == "/oauth1/authorize/") {
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(authorize(args, r, sc.appkeys, sc.mc));
+ return httpd::reportStatus(authorize(httpd::queryArgs(r), r, sc.appkeys, sc.mc));
}
// Handle OAuth access_token request step
- if (step == "access_token") {
+ if (string(r->uri) == "/oauth1/access_token/") {
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(accessToken(args, r, sc.appkeys, sc.mc));
+ return httpd::reportStatus(accessToken(httpd::queryArgs(r), r, sc.appkeys, sc.mc));
}
- // Redirect to the login page
+ // Redirect to the login page, unless we have a session id from another module
+ if (hasContent(openauth::sessionID(r, "TuscanyOpenIDAuth")) ||
+ hasContent(openauth::sessionID(r, "TuscanyOpenAuth")) ||
+ hasContent(openauth::sessionID(r, "TuscanyOAuth2")))
+ return DECLINED;
+ if ((substr(string(r->uri), 0, 8) == "/oauth2/") || !isNil(assoc<value>("openid_identifier", httpd::queryArgs(r))))
+ return DECLINED;
r->ap_auth_type = const_cast<char*>(atype);
return httpd::reportStatus(openauth::login(dc.login, r));
}
diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp
index ace611d3dc..dbede7ed8b 100644
--- a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp
+++ b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp
@@ -83,7 +83,7 @@ public:
* Return the user info for a session.
*/
const failable<value> userInfo(const value& sid, const memcache::MemCached& mc) {
- return memcache::get(mklist<value>("tuscanyOpenAuth", sid), mc);
+ return memcache::get(mklist<value>("tuscanyOAuth2", sid), mc);
}
/**
@@ -126,25 +126,35 @@ const failable<int> authenticated(const list<list<value> >& attrs, const list<li
*/
const failable<int> authorize(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys) {
// Extract authorize, access_token, client ID and info URIs
- const list<value> auth = assoc<value>("mod_oauth2_authorize", args);
+ const list<value> ref = assoc<value>("openauth_referrer", args);
+ if (isNil(ref) || isNil(cdr(ref)))
+ return mkfailure<int>("Missing openauth_referrer parameter");
+ const list<value> auth = assoc<value>("oauth2_authorize", args);
if (isNil(auth) || isNil(cdr(auth)))
- return mkfailure<int>("Missing mod_oauth2_authorize parameter");
- const list<value> tok = assoc<value>("mod_oauth2_access_token", args);
+ return mkfailure<int>("Missing oauth2_authorize parameter");
+ const list<value> tok = assoc<value>("oauth2_access_token", args);
if (isNil(tok) || isNil(cdr(tok)))
- return mkfailure<int>("Missing mod_oauth2_access_token parameter");
- const list<value> cid = assoc<value>("mod_oauth2_client_id", args);
+ return mkfailure<int>("Missing oauth2_access_token parameter");
+ const list<value> cid = assoc<value>("oauth2_client_id", args);
if (isNil(cid) || isNil(cdr(cid)))
- return mkfailure<int>("Missing mod_oauth2_client_id parameter");
- const list<value> info = assoc<value>("mod_oauth2_info", args);
+ return mkfailure<int>("Missing oauth2_client_id parameter");
+ const list<value> info = assoc<value>("oauth2_info", args);
if (isNil(info) || isNil(cdr(info)))
- return mkfailure<int>("Missing mod_oauth2_info parameter");
- const list<value> display = assoc<value>("mod_oauth2_display", args);
+ return mkfailure<int>("Missing oauth2_info parameter");
+ const list<value> scope = assoc<value>("oauth2_scope", args);
+ if (isNil(scope) || isNil(cdr(scope)))
+ return mkfailure<int>("Missing oauth2_scope parameter");
+ const list<value> display = assoc<value>("oauth2_display", args);
// Build the redirect URI
- const list<list<value> > rargs = mklist<list<value> >(mklist<value>("mod_oauth2_step", "access_token"), tok, cid, info);
- const string redir = httpd::url(r->uri, r) + string("?") + http::queryString(rargs);
+ const string redir = httpd::url("/oauth2/access_token/", r);
debug(redir, "modoauth2::authorize::redir");
+ // Build the state URI
+ const list<list<value> > stargs = mklist<list<value> >(tok, cid, info, ref);
+ const string state = http::queryString(stargs);
+ debug(state, "modoauth2::authorize::state");
+
// Lookup client app configuration
const list<value> app = assoc<value>(cadr(cid), appkeys);
if (isNil(app) || isNil(cdr(app)))
@@ -153,7 +163,7 @@ const failable<int> authorize(const list<list<value> >& args, request_rec* r, co
// Redirect to the authorize URI
const list<value> adisplay = (isNil(display) || isNil(cdr(display)))? list<value>() : mklist<value>("display", cadr(display));
- const list<list<value> > aargs = mklist<list<value> >(mklist<value>("client_id", car(appkey)), mklist<value>("scope", "email"), adisplay, mklist<value>("redirect_uri", httpd::escape(redir)));
+ const list<list<value> > aargs = mklist<list<value> >(mklist<value>("response_type", "code"), mklist<value>("client_id", car(appkey)), mklist<value>("scope", cadr(scope)), adisplay, mklist<value>("redirect_uri", httpd::escape(redir)), mklist<value>("state", httpd::escape(state)));
const string uri = httpd::unescape(cadr(auth)) + string("?") + http::queryString(aargs);
debug(uri, "modoauth2::authorize::uri");
return httpd::externalRedirect(uri, r);
@@ -172,16 +182,23 @@ const failable<list<value> > profileUserInfo(const value& cid, const list<value>
* Handle an access_token request.
*/
const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const perthread_ptr<http::CURLSession>& cs, const memcache::MemCached& mc) {
- // Extract access_token URI, client ID and authorization code
- const list<value> tok = assoc<value>("mod_oauth2_access_token", args);
+ // Extract access_token URI, client ID and authorization code parameters
+ const list<value> state = assoc<value>("state", args);
+ if (isNil(state) || isNil(cdr(state)))
+ return mkfailure<int>("Missing state parameter");
+ const list<list<value> >& stargs = httpd::queryArgs(httpd::unescape(cadr(state)));
+ const list<value> ref = assoc<value>("openauth_referrer", stargs);
+ if (isNil(ref) || isNil(cdr(ref)))
+ return mkfailure<int>("Missing openauth_referrer parameter");
+ const list<value> tok = assoc<value>("oauth2_access_token", stargs);
if (isNil(tok) || isNil(cdr(tok)))
- return mkfailure<int>("Missing mod_oauth2_access_token parameter");
- const list<value> cid = assoc<value>("mod_oauth2_client_id", args);
+ return mkfailure<int>("Missing oauth2_access_token parameter");
+ const list<value> cid = assoc<value>("oauth2_client_id", stargs);
if (isNil(cid) || isNil(cdr(cid)))
- return mkfailure<int>("Missing mod_oauth2_client_id parameter");
- const list<value> info = assoc<value>("mod_oauth2_info", args);
+ return mkfailure<int>("Missing oauth2_client_id parameter");
+ const list<value> info = assoc<value>("oauth2_info", stargs);
if (isNil(info) || isNil(cdr(info)))
- return mkfailure<int>("Missing mod_oauth2_info parameter");
+ return mkfailure<int>("Missing oauth2_info parameter");
const list<value> code = assoc<value>("code", args);
if (isNil(code) || isNil(cdr(code)))
return mkfailure<int>("Missing code parameter");
@@ -193,19 +210,26 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r,
list<value> appkey = cadr(app);
// Build the redirect URI
- const list<list<value> > rargs = mklist<list<value> >(mklist<value>("mod_oauth2_step", "access_token"), tok, cid, info);
- const string redir = httpd::url(r->uri, r) + string("?") + http::queryString(rargs);
+ const string redir = httpd::url("/oauth2/access_token/", r);
debug(redir, "modoauth2::access_token::redir");
// Request access token
- const list<list<value> > targs = mklist<list<value> >(mklist<value>("client_id", car(appkey)), mklist<value>("redirect_uri", httpd::escape(redir)), mklist<value>("client_secret", cadr(appkey)), code);
- const string turi = httpd::unescape(cadr(tok)) + string("?") + http::queryString(targs);
+ const list<list<value> > targs = mklist<list<value> >(mklist<value>("client_id", car(appkey)), mklist<value>("redirect_uri", httpd::escape(redir)), mklist<value>("client_secret", cadr(appkey)), code, mklist<value>("grant_type", "authorization_code"));
+ const string tqs = http::queryString(targs);
+ debug(tqs, "modoauth2::access_token::tokenqs");
+ const string turi = httpd::unescape(cadr(tok));
debug(turi, "modoauth2::access_token::tokenuri");
- const failable<value> tr = http::get(turi, *(cs));
- if (!hasContent(tr))
- return mkfailure<int>(reason(tr));
+ const value tval = mklist<value>(string("application/x-www-form-urlencoded;charset=UTF-8"), mklist<value>(tqs));
+ const failable<value> ftr = http::post(tval, turi, *(cs));
+ if (!hasContent(ftr))
+ return mkfailure<int>(reason(ftr));
+ const value tr = content(ftr);
debug(tr, "modoauth2::access_token::response");
- const list<value> tv = assoc<value>("access_token", httpd::queryArgs(join("", convertValues<string>(cadr<value>(content(tr))))));
+ if (!isList(tr) || isNil(tr))
+ return mkfailure<int>("Empty access token");
+ const list<value> tv = isString(car<value>(tr)) ?
+ assoc<value>("access_token", httpd::queryArgs(join("", convertValues<string>(cadr<value>(tr))))) :
+ assoc<value>("access_token", tr);
if (isNil(tv) || isNil(cdr(tv)))
return mkfailure<int>("Couldn't retrieve access_token");
debug(tv, "modoauth2::access_token::token");
@@ -227,14 +251,14 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r,
// Store user info in memcached keyed by session ID
const value sid = string("OAuth2_") + mkrand();
- const failable<bool> prc = memcache::put(mklist<value>("tuscanyOpenAuth", sid), content(iv), mc);
+ const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth2", sid), content(iv), mc);
if (!hasContent(prc))
return mkfailure<int>(reason(prc));
// Send session ID to the client in a cookie
- debug(c_str(openauth::cookie(sid, httpd::hostName(r))), "modoauth2::access_token::setcookie");
- apr_table_set(r->err_headers_out, "Set-Cookie", c_str(openauth::cookie(sid, httpd::hostName(r))));
- return httpd::externalRedirect(httpd::url(r->uri, r), r);
+ debug(c_str(openauth::cookie("TuscanyOAuth2", sid, httpd::hostName(r))), "modoauth2::access_token::setcookie");
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(openauth::cookie("TuscanyOAuth2", sid, httpd::hostName(r))));
+ return httpd::externalRedirect(httpd::url(httpd::unescape(cadr(ref)), r), r);
}
/**
@@ -246,6 +270,7 @@ static int checkAuthn(request_rec *r) {
if (!dc.enabled)
return DECLINED;
const char* atype = ap_auth_type(r);
+ debug(atype, "modopenauth::checkAuthn::auth_type");
if (atype == NULL || strcasecmp(atype, "Open"))
return DECLINED;
@@ -253,11 +278,11 @@ static int checkAuthn(request_rec *r) {
gc_scoped_pool pool(r->pool);
// Get the server configuration
- httpdDebugRequest(r, "modoauth2::checkAuthn::input");
+ debug_httpdRequest(r, "modoauth2::checkAuthn::input");
const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_oauth2);
// Get session id from the request
- const maybe<string> sid = openauth::sessionID(r);
+ const maybe<string> sid = openauth::sessionID(r, "TuscanyOAuth2");
if (hasContent(sid)) {
// Decline if the session id was not created by this module
if (substr(content(sid), 0, 7) != "OAuth2_")
@@ -271,33 +296,25 @@ static int checkAuthn(request_rec *r) {
}
}
- // Get the request args
- const list<list<value> > args = httpd::queryArgs(r);
-
- // Decline if the request is for another authentication provider
- if (!isNil(assoc<value>("openid_identifier", args)))
- return DECLINED;
- if (!isNil(assoc<value>("mod_oauth1_step", args)))
- return DECLINED;
-
- // Determine the OAuth protocol flow step, conveniently passed
- // around in a request arg
- const list<value> sl = assoc<value>("mod_oauth2_step", args);
- const value step = !isNil(sl) && !isNil(cdr(sl))? cadr(sl) : "";
-
// Handle OAuth authorize request step
- if (step == "authorize") {
+ if (string(r->uri) == "/oauth2/authorize/") {
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(authorize(args, r, sc.appkeys));
+ return httpd::reportStatus(authorize(httpd::queryArgs(r), r, sc.appkeys));
}
// Handle OAuth access_token request step
- if (step == "access_token") {
+ if (string(r->uri) == "/oauth2/access_token/") {
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(accessToken(args, r, sc.appkeys, sc.cs, sc.mc));
+ return httpd::reportStatus(accessToken(httpd::queryArgs(r), r, sc.appkeys, sc.cs, sc.mc));
}
- // Redirect to the login page
+ // Redirect to the login page, unless we have a session id from another module
+ if (hasContent(openauth::sessionID(r, "TuscanyOpenIDAuth")) ||
+ hasContent(openauth::sessionID(r, "TuscanyOpenAuth")) ||
+ hasContent(openauth::sessionID(r, "TuscanyOAuth1")))
+ return DECLINED;
+ if ((substr(string(r->uri), 0, 8) == "/oauth1/") || !isNil(assoc<value>("openid_identifier", httpd::queryArgs(r))))
+ return DECLINED;
r->ap_auth_type = const_cast<char*>(atype);
return httpd::reportStatus(openauth::login(dc.login, r));
}
diff --git a/sca-cpp/trunk/modules/oauth/start-mixed-test b/sca-cpp/trunk/modules/oauth/start-mixed-test
index d0c184144b..11bba42ef0 100755
--- a/sca-cpp/trunk/modules/oauth/start-mixed-test
+++ b/sca-cpp/trunk/modules/oauth/start-mixed-test
@@ -17,6 +17,9 @@
# specific language governing permissions and limitations
# under the License.
+# For this module to work, add the www.example.com domain to your /etc/hosts as follows:
+# 127.0.0.1 www.example.com
+
# Test supporting both OpenID and OAuth in the same app
here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
@@ -24,14 +27,19 @@ here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $h
../../components/cache/memcached-start tmp 11212
../../components/cache/memcached-start tmp 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/ssl-ca-conf tmp www.example.com
+../../modules/http/ssl-cert-conf tmp www.example.com
+../../modules/http/httpd-conf tmp www.example.com 8090 htdocs
../../modules/http/httpd-ssl-conf tmp 8453
+../openid/openid-conf tmp
+../openid/openid-step2-conf tmp
+../openid/openid-memcached-conf tmp www.example.com 11212
+../openid/openid-memcached-conf tmp www.example.com 11213
+
./oauth-conf tmp
-./oauth-memcached-conf tmp localhost 11212
-./oauth-memcached-conf tmp localhost 11213
+./oauth-memcached-conf tmp www.example.com 11212
+./oauth-memcached-conf tmp www.example.com 11213
# Configure your app keys here
./oauth1-appkey-conf tmp twitter.com app2345 secret7890
@@ -39,11 +47,6 @@ here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $h
./oauth2-appkey-conf tmp facebook.com app1234 secret6789
./oauth2-appkey-conf tmp github.com app5678 secret8901
-../openid/openid-conf tmp
-../openid/openid-step2-conf tmp
-../openid/openid-memcached-conf tmp localhost 11212
-../openid/openid-memcached-conf tmp localhost 11213
-
../http/open-auth-conf tmp
../http/passwd-auth-conf tmp foo foo
@@ -51,7 +54,7 @@ here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $h
# to the authorized user group
../../modules/http/group-auth-conf tmp foo
../../modules/http/group-auth-conf tmp 123456
-../../modules/http/group-auth-conf tmp https://www.google.com/accounts/o8/id?id=12345678
+../../modules/http/group-auth-conf tmp jane@example.com
../../modules/server/server-conf tmp
../../modules/server/scheme-conf tmp
diff --git a/sca-cpp/trunk/modules/oauth/start-test b/sca-cpp/trunk/modules/oauth/start-test
index d38f8d3d1a..21e1e005bd 100755
--- a/sca-cpp/trunk/modules/oauth/start-test
+++ b/sca-cpp/trunk/modules/oauth/start-test
@@ -17,21 +17,24 @@
# specific language governing permissions and limitations
# under the License.
+# For this module to work, add the www.example.com domain to your /etc/hosts as follows:
+# 127.0.0.1 www.example.com
+
# Setup
-../../ubuntu/ip-redirect-all 80 8090
-../../ubuntu/ip-redirect-all 443 8453
+#../../ubuntu/ip-redirect-all 80 8090
+#../../ubuntu/ip-redirect-all 443 8453
../../components/cache/memcached-start tmp 11212
../../components/cache/memcached-start tmp 11213
-../../modules/http/ssl-ca-conf tmp localhost
-../../modules/http/ssl-cert-conf tmp localhost
-../../modules/http/httpd-conf tmp localhost 8090/80 htdocs
-../../modules/http/httpd-ssl-conf tmp 8453/443
+../../modules/http/ssl-ca-conf tmp www.example.com
+../../modules/http/ssl-cert-conf tmp www.example.com
+../../modules/http/httpd-conf tmp www.example.com 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-memcached-conf tmp www.example.com 11212
+./oauth-memcached-conf tmp www.example.com 11213
# Configure your app keys here
./oauth1-appkey-conf tmp twitter.com app2345 secret7890
@@ -41,7 +44,7 @@
# For this test to work you need to add your oauth user id to the
# authorized user group
-../../modules/http/group-auth-conf tmp 123456
+../../modules/http/group-auth-conf tmp jane@example.com
../../modules/server/server-conf tmp
../../modules/server/scheme-conf tmp