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/Makefile.am2
-rw-r--r--sca-cpp/trunk/modules/oauth/mod-oauth1.cpp139
-rw-r--r--sca-cpp/trunk/modules/oauth/mod-oauth2.cpp141
-rwxr-xr-xsca-cpp/trunk/modules/oauth/oauth-conf20
-rwxr-xr-xsca-cpp/trunk/modules/oauth/oauth12-conf115
-rwxr-xr-xsca-cpp/trunk/modules/oauth/start-mixed-test13
-rwxr-xr-xsca-cpp/trunk/modules/oauth/start-test6
7 files changed, 358 insertions, 78 deletions
diff --git a/sca-cpp/trunk/modules/oauth/Makefile.am b/sca-cpp/trunk/modules/oauth/Makefile.am
index a5a5916a84..9e8eb5a0dd 100644
--- a/sca-cpp/trunk/modules/oauth/Makefile.am
+++ b/sca-cpp/trunk/modules/oauth/Makefile.am
@@ -19,7 +19,7 @@ if WANT_OAUTH
INCLUDES = -I${HTTPD_INCLUDE} -I${LIBOAUTH_INCLUDE}
-dist_mod_SCRIPTS = oauth-conf oauth-memcached-conf oauth1-appkey-conf oauth2-appkey-conf
+dist_mod_SCRIPTS = oauth-conf oauth12-conf oauth-memcached-conf oauth1-appkey-conf oauth2-appkey-conf
moddir=$(prefix)/modules/oauth
mod_LTLIBRARIES = libmod_tuscany_oauth1.la libmod_tuscany_oauth2.la
diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp
index eb23443491..d2c7cf7ddd 100644
--- a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp
+++ b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp
@@ -71,6 +71,20 @@ public:
};
/**
+ * Authentication provider configuration.
+ */
+class AuthnProviderConf {
+public:
+ AuthnProviderConf() : name(), provider(NULL) {
+ }
+ AuthnProviderConf(const string name, const authn_provider* provider) : name(name), provider(provider) {
+ }
+
+ string name;
+ const authn_provider* provider;
+};
+
+/**
* Directory configuration.
*/
class DirConf {
@@ -83,9 +97,39 @@ public:
bool enabled;
string login;
list<list<value> > scopeattrs;
+ list<AuthnProviderConf> apcs;
};
/**
+ * Run the authnz hooks to authenticate a request.
+ */
+const failable<int> checkAuthnzProviders(const string& user, request_rec* r, const list<AuthnProviderConf>& apcs) {
+ if (isNil(apcs))
+ return mkfailure<int>("Authentication failure for: " + user, HTTP_UNAUTHORIZED);
+ const AuthnProviderConf apc = car<AuthnProviderConf>(apcs);
+ if (apc.provider == NULL || !apc.provider->check_password)
+ return checkAuthnzProviders(user, r, cdr(apcs));
+
+ apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, c_str(apc.name));
+ const authn_status auth_result = apc.provider->check_password(r, c_str(string("/oauth1/") + user), "password");
+ apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE);
+ if (auth_result != AUTH_GRANTED)
+ return checkAuthnzProviders(user, r, cdr(apcs));
+ return OK;
+}
+
+const failable<int> checkAuthnz(const string& user, request_rec* r, const list<AuthnProviderConf>& apcs) {
+ if (substr(user, 0, 1) == "/")
+ return mkfailure<int>(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED);
+
+ if (isNil(apcs)) {
+ const authn_provider* provider = (const authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, AUTHN_DEFAULT_PROVIDER, AUTHN_PROVIDER_VERSION);
+ return checkAuthnzProviders(user, r, mklist<AuthnProviderConf>(AuthnProviderConf(AUTHN_DEFAULT_PROVIDER, provider)));
+ }
+ return checkAuthnzProviders(user, r, apcs);
+}
+
+/**
* Return the user info for a session.
*/
const failable<value> userInfo(const value& sid, const memcache::MemCached& mc) {
@@ -95,27 +139,31 @@ const failable<value> userInfo(const value& sid, const memcache::MemCached& mc)
/**
* Handle an authenticated request.
*/
-const failable<int> authenticated(const list<list<value> >& attrs, const list<list<value> >& info, request_rec* r) {
- debug(info, "modoauth1::authenticated::info");
+const failable<int> authenticated(const list<list<value> >& userinfo, const bool check, request_rec* r, const list<list<value> >& scopeattrs, const list<AuthnProviderConf>& apcs) {
+ debug(userinfo, "modoauth2::authenticated::userinfo");
- if (isNil(attrs)) {
+ if (isNil(scopeattrs)) {
// Store user id in an environment variable
- const list<value> id = assoc<value>("id", info);
+ const list<value> id = assoc<value>("id", userinfo);
if (isNil(id) || isNil(cdr(id)))
return mkfailure<int>("Couldn't retrieve user id");
- apr_table_set(r->subprocess_env, "OAUTH1_ID", apr_pstrdup(r->pool, c_str(cadr(id))));
+ apr_table_set(r->subprocess_env, "OAUTH2_ID", apr_pstrdup(r->pool, c_str(cadr(id))));
// If the request user field has not been mapped to another attribute, map the
// OAuth id attribute to it
if (r->user == NULL || r->user[0] == '\0')
r->user = apr_pstrdup(r->pool, c_str(cadr(id)));
+
+ // Run the authnz hooks to check the authenticated user
+ if (check)
+ return checkAuthnz(r->user == NULL? "" : r->user, r, apcs);
return OK;
}
- // Store each configure OAuth scope attribute in an environment variable
- const list<value> a = car(attrs);
- const list<value> v = assoc<value>(cadr(a), info);
+ // Store each configured OAuth scope attribute in an environment variable
+ const list<value> a = car(scopeattrs);
+ const list<value> v = assoc<value>(cadr(a), userinfo);
if (!isNil(v) && !isNil(cdr(v))) {
// Map the REMOTE_USER attribute to the request user field
@@ -124,7 +172,7 @@ const failable<int> authenticated(const list<list<value> >& attrs, const list<li
else
apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, c_str(car(a))), apr_pstrdup(r->pool, c_str(cadr(v))));
}
- return authenticated(cdr(attrs), info, r);
+ return authenticated(userinfo, check, r, cdr(scopeattrs), apcs);
}
/**
@@ -297,7 +345,8 @@ const failable<list<value> > profileUserInfo(const value& cid, const string& inf
/**
* Handle an access_token request.
*/
-const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const memcache::MemCached& mc) {
+const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const list<list<value> >& scopeattrs, const list<AuthnProviderConf>& apcs, const memcache::MemCached& mc) {
+
// Extract access_token URI, client ID and verification code
const list<value> ref = assoc<value>("openauth_referrer", args);
if (isNil(ref) || isNil(cdr(ref)))
@@ -372,13 +421,18 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r,
debug(profres, "modoauth1::access_token::profres");
// Retrieve the user info from the profile
- const failable<list<value> > iv = profileUserInfo(cadr(cid), profres);
- if (!hasContent(iv))
- return mkfailure<int>(iv);
+ const failable<list<value> > userinfo = profileUserInfo(cadr(cid), profres);
+ if (!hasContent(userinfo))
+ return mkfailure<int>(userinfo);
+
+ // Validate the authenticated user
+ const failable<int> authrc = authenticated(content(userinfo), true, r, scopeattrs, apcs);
+ if (!hasContent(authrc))
+ return authrc;
// Store user info in memcached keyed by session ID
const value sid = string("OAuth1_") + mkrand();
- const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth1", sid), content(iv), mc);
+ const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth1", sid), content(userinfo), mc);
if (!hasContent(prc))
return mkfailure<int>(prc);
@@ -392,20 +446,19 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r,
* Check user authentication.
*/
static int checkAuthn(request_rec *r) {
+ gc_scoped_pool pool(r->pool);
+
// Decline if we're not enabled or AuthType is not set to Open
const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_oauth1);
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;
-
- // Create a scoped memory pool
- gc_scoped_pool pool(r->pool);
+ debug_httpdRequest(r, "modoauth1::checkAuthn::input");
+ debug(atype, "modopenauth::checkAuthn::auth_type");
// Get the server configuration
- debug_httpdRequest(r, "modoauth1::checkAuthn::input");
const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_oauth1);
// Get session id from the request
@@ -415,24 +468,33 @@ static int checkAuthn(request_rec *r) {
if (substr(content(sid), 0, 7) != "OAuth1_")
return DECLINED;
- // If we're authenticated store the user info in the request
- const failable<value> info = userInfo(content(sid), sc.mc);
- if (hasContent(info)) {
- r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(authenticated(dc.scopeattrs, content(info), r));
- }
+ // Extract the user info from the auth session
+ const failable<value> userinfo = userInfo(content(sid), sc.mc);
+ if (!hasContent(userinfo))
+ return httpd::reportStatus(mkfailure<int>(userinfo));
+ r->ap_auth_type = const_cast<char*>(atype);
+ return httpd::reportStatus(authenticated(content(userinfo), false, r, dc.scopeattrs, dc.apcs));
}
+ // Get the request args
+ const list<list<value> > args = httpd::queryArgs(r);
+
// Handle OAuth authorize request step
if (string(r->uri) == "/oauth1/authorize/") {
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(authorize(httpd::queryArgs(r), r, sc.appkeys, sc.mc));
+ return httpd::reportStatus(authorize(args, r, sc.appkeys, sc.mc));
}
// Handle OAuth access_token request step
if (string(r->uri) == "/oauth1/access_token/") {
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(accessToken(httpd::queryArgs(r), r, sc.appkeys, sc.mc));
+ const failable<int> authrc = accessToken(args, r, sc.appkeys, dc.scopeattrs, dc.apcs, sc.mc);
+
+ // Redirect to the login page if user is not authorized
+ if (!hasContent(authrc) && rcode(authrc) == HTTP_UNAUTHORIZED)
+ return httpd::reportStatus(openauth::login(dc.login, string("/"), 1, r));
+
+ return httpd::reportStatus(authrc);
}
// Redirect to the login page, unless we have a session id or an authorization
@@ -443,10 +505,11 @@ static int checkAuthn(request_rec *r) {
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))))
+ if ((substr(string(r->uri), 0, 8) == "/oauth2/") || !isNil(assoc<value>("openid_identifier", args)))
return DECLINED;
+
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(openauth::login(dc.login, r));
+ return httpd::reportStatus(openauth::login(dc.login, value(), value(), r));
}
/**
@@ -471,6 +534,7 @@ int postConfigMerge(ServerConf& mainsc, server_rec* s) {
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_oauth1);
debug(httpd::serverName(s), "modoauth1::postConfig::serverName");
@@ -487,7 +551,7 @@ public:
}
const gc_ptr<http::CURLSession> operator()() const {
- return new (gc_new<http::CURLSession>()) http::CURLSession(ca, cert, key, "");
+ return new (gc_new<http::CURLSession>()) http::CURLSession(ca, cert, key, "", 0);
}
private:
@@ -501,6 +565,7 @@ private:
*/
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_oauth1);
if(psc == NULL) {
cfailure << "[Tuscany] Due to one or more errors mod_tuscany_oauth1 loading failed. Causing apache to stop loading." << endl;
@@ -572,11 +637,25 @@ const char* confScopeAttr(cmd_parms *cmd, void* c, const char* arg1, const char*
dc.scopeattrs = cons<list<value> >(mklist<value>(arg1, arg2), dc.scopeattrs);
return NULL;
}
+const char* confAuthnProvider(cmd_parms *cmd, void *c, const char* arg) {
+ gc_scoped_pool pool(cmd->pool);
+ DirConf& dc = httpd::dirConf<DirConf>(c);
+
+ // Lookup and cache the Authn provider
+ const authn_provider* provider = (authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, arg, AUTHN_PROVIDER_VERSION);
+ if (provider == NULL)
+ return apr_psprintf(cmd->pool, "Unknown Authn provider: %s", arg);
+ if (!provider->check_password)
+ return apr_psprintf(cmd->pool, "The '%s' Authn provider doesn't support password authentication", arg);
+ dc.apcs = append<AuthnProviderConf>(dc.apcs, mklist<AuthnProviderConf>(AuthnProviderConf(arg, provider)));
+ return NULL;
+}
/**
* HTTP server module declaration.
*/
const command_rec commands[] = {
+ AP_INIT_ITERATE("AuthOAuthProvider", (const char*(*)())confAuthnProvider, NULL, OR_AUTHCFG, "Auth providers for a directory or location"),
AP_INIT_TAKE3("AddAuthOAuth1AppKey", (const char*(*)())confAppKey, NULL, RSRC_CONF, "OAuth 1.0 name app-id app-key"),
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 1.0 authentication On | Off"),
diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp
index cbece191aa..e384a0e742 100644
--- a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp
+++ b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp
@@ -65,6 +65,20 @@ public:
};
/**
+ * Authentication provider configuration.
+ */
+class AuthnProviderConf {
+public:
+ AuthnProviderConf() : name(), provider(NULL) {
+ }
+ AuthnProviderConf(const string name, const authn_provider* provider) : name(name), provider(provider) {
+ }
+
+ string name;
+ const authn_provider* provider;
+};
+
+/**
* Directory configuration.
*/
class DirConf {
@@ -77,9 +91,39 @@ public:
bool enabled;
string login;
list<list<value> > scopeattrs;
+ list<AuthnProviderConf> apcs;
};
/**
+ * Run the authnz hooks to authenticate a request.
+ */
+const failable<int> checkAuthnzProviders(const string& user, request_rec* r, const list<AuthnProviderConf>& apcs) {
+ if (isNil(apcs))
+ return mkfailure<int>("Authentication failure for: " + user, HTTP_UNAUTHORIZED);
+ const AuthnProviderConf apc = car<AuthnProviderConf>(apcs);
+ if (apc.provider == NULL || !apc.provider->check_password)
+ return checkAuthnzProviders(user, r, cdr(apcs));
+
+ apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, c_str(apc.name));
+ const authn_status auth_result = apc.provider->check_password(r, c_str(string("/oauth2/") + user), "password");
+ apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE);
+ if (auth_result != AUTH_GRANTED)
+ return checkAuthnzProviders(user, r, cdr(apcs));
+ return OK;
+}
+
+const failable<int> checkAuthnz(const string& user, request_rec* r, const list<AuthnProviderConf>& apcs) {
+ if (substr(user, 0, 1) == "/")
+ return mkfailure<int>(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED);
+
+ if (isNil(apcs)) {
+ const authn_provider* provider = (const authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, AUTHN_DEFAULT_PROVIDER, AUTHN_PROVIDER_VERSION);
+ return checkAuthnzProviders(user, r, mklist<AuthnProviderConf>(AuthnProviderConf(AUTHN_DEFAULT_PROVIDER, provider)));
+ }
+ return checkAuthnzProviders(user, r, apcs);
+}
+
+/**
* Return the user info for a session.
*/
const failable<value> userInfo(const value& sid, const memcache::MemCached& mc) {
@@ -89,13 +133,13 @@ const failable<value> userInfo(const value& sid, const memcache::MemCached& mc)
/**
* Handle an authenticated request.
*/
-const failable<int> authenticated(const list<list<value> >& attrs, const list<list<value> >& info, request_rec* r) {
- debug(info, "modoauth2::authenticated::info");
+const failable<int> authenticated(const list<list<value> >& userinfo, const bool check, request_rec* r, const list<list<value> >& scopeattrs, const list<AuthnProviderConf>& apcs) {
+ debug(userinfo, "modoauth2::authenticated::userinfo");
- if (isNil(attrs)) {
+ if (isNil(scopeattrs)) {
// Store user id in an environment variable
- const list<value> id = assoc<value>("id", info);
+ const list<value> id = assoc<value>("id", userinfo);
if (isNil(id) || isNil(cdr(id)))
return mkfailure<int>("Couldn't retrieve user id");
apr_table_set(r->subprocess_env, "OAUTH2_ID", apr_pstrdup(r->pool, c_str(cadr(id))));
@@ -104,12 +148,16 @@ const failable<int> authenticated(const list<list<value> >& attrs, const list<li
// OAuth id attribute to it
if (r->user == NULL || r->user[0] == '\0')
r->user = apr_pstrdup(r->pool, c_str(cadr(id)));
+
+ // Run the authnz hooks to check the authenticated user
+ if (check)
+ return checkAuthnz(r->user == NULL? "" : r->user, r, apcs);
return OK;
}
- // Store each configure OAuth scope attribute in an environment variable
- const list<value> a = car(attrs);
- const list<value> v = assoc<value>(cadr(a), info);
+ // Store each configured OAuth scope attribute in an environment variable
+ const list<value> a = car(scopeattrs);
+ const list<value> v = assoc<value>(cadr(a), userinfo);
if (!isNil(v) && !isNil(cdr(v))) {
// Map the REMOTE_USER attribute to the request user field
@@ -118,7 +166,7 @@ const failable<int> authenticated(const list<list<value> >& attrs, const list<li
else
apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, c_str(car(a))), apr_pstrdup(r->pool, c_str(cadr(v))));
}
- return authenticated(cdr(attrs), info, r);
+ return authenticated(userinfo, check, r, cdr(scopeattrs), apcs);
}
/**
@@ -181,7 +229,8 @@ 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) {
+const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const perthread_ptr<http::CURLSession>& cs, const list<list<value> >& scopeattrs, const list<AuthnProviderConf>& apcs, const memcache::MemCached& mc) {
+
// Extract access_token URI, client ID and authorization code parameters
const list<value> state = assoc<value>("state", args);
if (isNil(state) || isNil(cdr(state)))
@@ -245,17 +294,22 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r,
debug(content(profres), "modoauth2::access_token::info");
// Retrieve the user info from the profile
- const failable<list<value> > iv = profileUserInfo(cadr(cid), content(profres));
- if (!hasContent(iv))
- return mkfailure<int>(iv);
+ const failable<list<value> > userinfo = profileUserInfo(cadr(cid), content(profres));
+ if (!hasContent(userinfo))
+ return mkfailure<int>(userinfo);
- // Store user info in memcached keyed by session ID
+ // Validate the authenticated user
+ const failable<int> authrc = authenticated(content(userinfo), true, r, scopeattrs, apcs);
+ if (!hasContent(authrc))
+ return authrc;
+
+ // Store user info in memcached keyed by a session ID
const value sid = string("OAuth2_") + mkrand();
- const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth2", sid), content(iv), mc);
+ const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth2", sid), content(userinfo), mc);
if (!hasContent(prc))
return mkfailure<int>(prc);
- // Send session ID to the client in a cookie
+ // Send the session ID to the client in a cookie
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);
@@ -265,20 +319,19 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r,
* Check user authentication.
*/
static int checkAuthn(request_rec *r) {
+ gc_scoped_pool pool(r->pool);
+
// Decline if we're not enabled or AuthType is not set to Open
const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_oauth2);
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;
-
- // Create a scoped memory pool
- gc_scoped_pool pool(r->pool);
+ debug_httpdRequest(r, "modoauth2::checkAuthn::input");
+ debug(atype, "modopenauth::checkAuthn::auth_type");
// Get the server configuration
- debug_httpdRequest(r, "modoauth2::checkAuthn::input");
const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_oauth2);
// Get session id from the request
@@ -288,24 +341,33 @@ static int checkAuthn(request_rec *r) {
if (substr(content(sid), 0, 7) != "OAuth2_")
return DECLINED;
- // If we're authenticated store the user info in the request
- const failable<value> info = userInfo(content(sid), sc.mc);
- if (hasContent(info)) {
- r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(authenticated(dc.scopeattrs, content(info), r));
- }
+ // Extract the user info from the auth session
+ const failable<value> userinfo = userInfo(content(sid), sc.mc);
+ if (!hasContent(userinfo))
+ return httpd::reportStatus(mkfailure<int>(userinfo));
+ r->ap_auth_type = const_cast<char*>(atype);
+ return httpd::reportStatus(authenticated(content(userinfo), false, r, dc.scopeattrs, dc.apcs));
}
+ // Get the request args
+ const list<list<value> > args = httpd::queryArgs(r);
+
// Handle OAuth authorize request step
if (string(r->uri) == "/oauth2/authorize/") {
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(authorize(httpd::queryArgs(r), r, sc.appkeys));
+ return httpd::reportStatus(authorize(args, r, sc.appkeys));
}
// Handle OAuth access_token request step
if (string(r->uri) == "/oauth2/access_token/") {
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(accessToken(httpd::queryArgs(r), r, sc.appkeys, sc.cs, sc.mc));
+ const failable<int> authrc = accessToken(args, r, sc.appkeys, sc.cs, dc.scopeattrs, dc.apcs, sc.mc);
+
+ // Redirect to the login page if user is not authorized
+ if (!hasContent(authrc) && rcode(authrc) == HTTP_UNAUTHORIZED)
+ return httpd::reportStatus(openauth::login(dc.login, string("/"), 1, r));
+
+ return httpd::reportStatus(authrc);
}
// Redirect to the login page, unless we have a session id or an authorization
@@ -316,10 +378,11 @@ static int checkAuthn(request_rec *r) {
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))))
+ if ((substr(string(r->uri), 0, 8) == "/oauth1/") || !isNil(assoc<value>("openid_identifier", args)))
return DECLINED;
+
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(openauth::login(dc.login, r));
+ return httpd::reportStatus(openauth::login(dc.login, value(), value(), r));
}
/**
@@ -344,6 +407,7 @@ int postConfigMerge(ServerConf& mainsc, server_rec* s) {
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_oauth2);
debug(httpd::serverName(s), "modoauth2::postConfig::serverName");
@@ -360,7 +424,7 @@ public:
}
const gc_ptr<http::CURLSession> operator()() const {
- return new (gc_new<http::CURLSession>()) http::CURLSession(ca, cert, key, "");
+ return new (gc_new<http::CURLSession>()) http::CURLSession(ca, cert, key, "", 0);
}
private:
@@ -374,6 +438,7 @@ private:
*/
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_oauth2);
if(psc == NULL) {
cfailure << "[Tuscany] Due to one or more errors mod_tuscany_oauth2 loading failed. Causing apache to stop loading." << endl;
@@ -445,11 +510,25 @@ const char* confScopeAttr(cmd_parms *cmd, void* c, const char* arg1, const char*
dc.scopeattrs = cons<list<value> >(mklist<value>(arg1, arg2), dc.scopeattrs);
return NULL;
}
+const char* confAuthnProvider(cmd_parms *cmd, void *c, const char* arg) {
+ gc_scoped_pool pool(cmd->pool);
+ DirConf& dc = httpd::dirConf<DirConf>(c);
+
+ // Lookup and cache the Authn provider
+ const authn_provider* provider = (authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, arg, AUTHN_PROVIDER_VERSION);
+ if (provider == NULL)
+ return apr_psprintf(cmd->pool, "Unknown Authn provider: %s", arg);
+ if (!provider->check_password)
+ return apr_psprintf(cmd->pool, "The '%s' Authn provider doesn't support password authentication", arg);
+ dc.apcs = append<AuthnProviderConf>(dc.apcs, mklist<AuthnProviderConf>(AuthnProviderConf(arg, provider)));
+ return NULL;
+}
/**
* HTTP server module declaration.
*/
const command_rec commands[] = {
+ AP_INIT_ITERATE("AuthOAuthProvider", (const char*(*)())confAuthnProvider, NULL, OR_AUTHCFG, "Auth providers for a directory or location"),
AP_INIT_TAKE3("AddAuthOAuth2AppKey", (const char*(*)())confAppKey, NULL, RSRC_CONF, "OAuth 2.0 name app-id app-key"),
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 2.0 authentication On | Off"),
diff --git a/sca-cpp/trunk/modules/oauth/oauth-conf b/sca-cpp/trunk/modules/oauth/oauth-conf
index 0b8f14b636..26e654036b 100755
--- a/sca-cpp/trunk/modules/oauth/oauth-conf
+++ b/sca-cpp/trunk/modules/oauth/oauth-conf
@@ -39,18 +39,23 @@ else
sslsuffix="-ssl"
fi
+if [ "$2" = "" ]; then
+ providers="file"
+else
+ providers="$2 file"
+fi
+
# Configure HTTPD mod_tuscany_oauth module
cat >>$root/conf/modules.conf <<EOF
# Generated by: oauth-conf $*
# Load support for OAuth authentication
-LoadModule mod_tuscany_oauth1 $here/libmod_tuscany_oauth1$libsuffix
LoadModule mod_tuscany_oauth2 $here/libmod_tuscany_oauth2$libsuffix
EOF
# Disallow public access to server resources
cat >$root/conf/noauth$sslsuffix.conf <<EOF
-# Generated by: oauth-auth-conf $*
+# Generated by: oauth-conf $*
# Disallow public access to server resources
EOF
@@ -62,9 +67,12 @@ cat >>$root/conf/locauth$sslsuffix.conf <<EOF
<Location />
AuthType Open
AuthName "$host"
+AuthOAuthProvider socache $providers
+AuthnCacheProvideFor $providers
+AuthnCacheContext /
Require valid-user
AuthOAuth On
-AuthOAuthLoginPage /login
+AuthOAuthLoginPage /login/
AddAuthOAuth2ScopeAttr REALM realm
AddAuthOAuth2ScopeAttr REMOTE_USER email
AddAuthOAuth2ScopeAttr EMAIL email
@@ -72,13 +80,7 @@ AddAuthOAuth2ScopeAttr NICKNAME name
AddAuthOAuth2ScopeAttr FULLNAME name
AddAuthOAuth2ScopeAttr FIRSTNAME first_name
AddAuthOAuth2ScopeAttr LASTNAME last_name
-AddAuthOAuth1ScopeAttr REALM realm
-AddAuthOAuth1ScopeAttr REMOTE_USER email
-AddAuthOAuth1ScopeAttr EMAIL email
-AddAuthOAuth1ScopeAttr NICKNAME screen_name
AddAuthOAuth2ScopeAttr FULLNAME name
-AddAuthOAuth1ScopeAttr FIRSTNAME first-name
-AddAuthOAuth1ScopeAttr LASTNAME last-name
</Location>
EOF
diff --git a/sca-cpp/trunk/modules/oauth/oauth12-conf b/sca-cpp/trunk/modules/oauth/oauth12-conf
new file mode 100755
index 0000000000..43c879faee
--- /dev/null
+++ b/sca-cpp/trunk/modules/oauth/oauth12-conf
@@ -0,0 +1,115 @@
+#!/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=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+mkdir -p $1
+root=`echo "import os; print os.path.realpath('$1')" | python`
+
+uname=`uname -s`
+if [ $uname = "Darwin" ]; then
+ libsuffix=".dylib"
+else
+ libsuffix=".so"
+fi
+
+conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"`
+host=`echo $conf | awk '{ print $6 }'`
+
+sslconf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-ssl-conf"`
+if [ "$sslconf" = "" ]; then
+ sslsuffix=""
+else
+ sslsuffix="-ssl"
+fi
+
+if [ "$2" = "" ]; then
+ providers="file"
+else
+ providers="$2 file"
+fi
+
+# Configure HTTPD mod_tuscany_oauth module
+cat >>$root/conf/modules.conf <<EOF
+# Generated by: oauth12-conf $*
+# Load support for OAuth authentication
+LoadModule mod_tuscany_oauth1 $here/libmod_tuscany_oauth1$libsuffix
+LoadModule mod_tuscany_oauth2 $here/libmod_tuscany_oauth2$libsuffix
+
+EOF
+
+# Disallow public access to server resources
+cat >$root/conf/noauth$sslsuffix.conf <<EOF
+# Generated by: oauth12-conf $*
+# Disallow public access to server resources
+
+EOF
+
+# Configure OAuth authentication
+cat >>$root/conf/locauth$sslsuffix.conf <<EOF
+# Generated by: oauth12-conf $*
+# Enable OAuth authentication
+<Location />
+AuthType Open
+AuthName "$host"
+AuthOAuthProvider socache $providers
+AuthnCacheProvideFor $providers
+AuthnCacheContext /
+Require valid-user
+AuthOAuth On
+AuthOAuthLoginPage /login/
+AddAuthOAuth2ScopeAttr REALM realm
+AddAuthOAuth2ScopeAttr REMOTE_USER email
+AddAuthOAuth2ScopeAttr EMAIL email
+AddAuthOAuth2ScopeAttr NICKNAME name
+AddAuthOAuth2ScopeAttr FULLNAME name
+AddAuthOAuth2ScopeAttr FIRSTNAME first_name
+AddAuthOAuth2ScopeAttr LASTNAME last_name
+AddAuthOAuth1ScopeAttr REALM realm
+AddAuthOAuth1ScopeAttr REMOTE_USER email
+AddAuthOAuth1ScopeAttr EMAIL email
+AddAuthOAuth1ScopeAttr NICKNAME screen_name
+AddAuthOAuth2ScopeAttr FULLNAME name
+AddAuthOAuth1ScopeAttr FIRSTNAME first-name
+AddAuthOAuth1ScopeAttr LASTNAME last-name
+</Location>
+
+EOF
+
+cat >>$root/conf/auth.conf <<EOF
+# Configure OAuth App keys
+Include $root/cert/oauth-keys.conf
+
+EOF
+
+mkdir -p $root/cert
+cat >$root/cert/oauth-keys.conf <<EOF
+# Generated by: oauth12-conf $*
+# OAuth App keys
+
+EOF
+
+if [ -d "$HOME/.oauth" ]; then
+ cat >>$root/conf/auth.conf <<EOF
+# Configure OAuth App keys
+Include $HOME/.oauth/*-key.conf
+
+EOF
+fi
+
diff --git a/sca-cpp/trunk/modules/oauth/start-mixed-test b/sca-cpp/trunk/modules/oauth/start-mixed-test
index e5a8837354..478f2cc777 100755
--- a/sca-cpp/trunk/modules/oauth/start-mixed-test
+++ b/sca-cpp/trunk/modules/oauth/start-mixed-test
@@ -38,7 +38,7 @@ rm -rf tmp
../openid/openid-memcached-conf tmp www.example.com 11212
../openid/openid-memcached-conf tmp www.example.com 11213
-./oauth-conf tmp
+./oauth12-conf tmp
./oauth-memcached-conf tmp www.example.com 11212
./oauth-memcached-conf tmp www.example.com 11213
@@ -48,13 +48,16 @@ rm -rf tmp
./oauth2-appkey-conf tmp facebook.com app1234 secret6789
./oauth2-appkey-conf tmp github.com app5678 secret8901
-../http/open-auth-conf tmp
-../http/passwd-auth-conf tmp foo foo
+../../modules/http/open-auth-conf tmp
-# For this test to work you need to add your form, oauth and open id ids
-# to the authorized user group
+# For this test to work you need to add your oauth and openid user ids to
+# the password file with a dummy 'password' password, and to the group
+# of authorized users
+../../modules/http/passwd-auth-conf tmp foo foo
../../modules/http/group-auth-conf tmp foo
+../../modules/http/passwd-auth-conf tmp /openid/123456 password
../../modules/http/group-auth-conf tmp 123456
+../../modules/http/passwd-auth-conf tmp /oauth2/jane@example.com password
../../modules/http/group-auth-conf tmp jane@example.com
../../modules/server/server-conf tmp
diff --git a/sca-cpp/trunk/modules/oauth/start-test b/sca-cpp/trunk/modules/oauth/start-test
index 8fc41cdb9a..cadbed2bac 100755
--- a/sca-cpp/trunk/modules/oauth/start-test
+++ b/sca-cpp/trunk/modules/oauth/start-test
@@ -33,7 +33,7 @@ rm -rf tmp
../../modules/http/httpd-conf tmp www.example.com 8090 htdocs
../../modules/http/httpd-ssl-conf tmp 8453
-./oauth-conf tmp
+./oauth12-conf tmp
./oauth-memcached-conf tmp www.example.com 11212
./oauth-memcached-conf tmp www.example.com 11213
@@ -44,7 +44,9 @@ rm -rf tmp
./oauth2-appkey-conf tmp github.com app5678 secret8901
# For this test to work you need to add your oauth user id to the
-# authorized user group
+# password file with a dummy 'password' password, and to the group
+# of authorized users
+../../modules/http/passwd-auth-conf tmp /oauth2/jane@example.com password
../../modules/http/group-auth-conf tmp jane@example.com
../../modules/server/server-conf tmp