const failable accessToken()

in modules/oauth/mod-oauth1.cpp [352:447]


const failable<int> accessToken(const list<value>& args, request_rec* r, const list<value>& appkeys, const 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 (isNull(ref) || isNull(cdr(ref)))
        return mkfailure<int>("Missing openauth_referrer parameter");
    const list<value> tok = assoc<value>("oauth1_access_token", args);
    if (isNull(tok) || isNull(cdr(tok)))
        return mkfailure<int>("Missing oauth1_access_token parameter");
    const list<value> cid = assoc<value>("oauth1_client_id", args);
    if (isNull(cid) || isNull(cdr(cid)))
        return mkfailure<int>("Missing oauth1_client_id parameter");
    const list<value> info = assoc<value>("oauth1_info", args);
    if (isNull(info) || isNull(cdr(info)))
        return mkfailure<int>("Missing oauth1_info parameter");
    const list<value> tv = assoc<value>("oauth_token", args);
    if (isNull(tv) || isNull(cdr(tv)))
        return mkfailure<int>("Missing oauth_token parameter");
    const list<value> vv = assoc<value>("oauth_verifier", args);
    if (isNull(vv) || isNull(cdr(vv)))
        return mkfailure<int>("Missing oauth_verifier parameter");

    // Lookup client app configuration
    const list<value> app = assoc<value>(cadr(cid), appkeys);
    if (isNull(app) || isNull(cdr(app)))
        return mkfailure<int>(string("client id not found: ") + (string)cadr(cid));
    const list<value> appkey = cadr(app);

    // Retrieve the request token from memcached
    const failable<value> sv = memcache::get(mklist<value>("tuscanyOAuth1Token", cadr(tv)), mc);
    if (!hasContent(sv))
        return mkfailure<int>(sv);

    // Build and sign access token request URI
    const string tokuri = httpd::unescape(cadr(tok)) + string("?") + http::queryString(mklist<value>(vv));
    const list<string> stokuri = sign("POST", tokuri, appkey, cadr(tv), content(sv));
    debug(stokuri, "modoauth1::access_token::stokuri");

    // Put the args into an oauth header
    string tokhdr = header(cadr(stokuri), emptyString, cadr(vv));

    // Send the access token request
    char* const ptokres = oauth_http_post2(c_str(car(stokuri)), "", c_str(tokhdr));
    if (ptokres == NULL)
        return mkfailure<int>("Couldn't post access_token request");
    const string tokres(ptokres);
    free(ptokres);
    debug(tokres, "modoauth1::access_token::res");
    const list<value> tokresargs = httpd::queryArgs(tokres);

    // Retrieve the access token
    const list<value> atv = assoc<value>("oauth_token", tokresargs);
    if (isNull(atv) || isNull(cdr(atv)))
        return mkfailure<int>("Couldn't retrieve oauth_token");
    const list<value> asv = assoc<value>("oauth_token_secret", tokresargs);
    if (isNull(asv) || isNull(cdr(asv)))
        return mkfailure<int>("Couldn't retrieve oauth_token_secret");
    debug(atv, "modoauth1::access_token::token");

    // Build and sign user profile request URI
    const string profuri = httpd::unescape(cadr(info));
    const list<string> sprofuri = sign("GET", profuri, appkey, cadr(atv), cadr(asv));
    debug(sprofuri, "modoauth1::access_token::sprofuri");

    // Put the args into an oauth header
    const string profhdr = header(cadr(sprofuri), emptyString, emptyString);

    // Send the user profile request
    char* const pprofres = oauth_http_get2(c_str(car(sprofuri)), NULL, c_str(profhdr));
    if (pprofres == NULL)
        return mkfailure<int>("Couldn't get user info");
    const string profres(pprofres);
    free(pprofres);
    debug(profres, "modoauth1::access_token::profres");

    // Retrieve the user info from the profile
    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), r, scopeattrs, apcs);
    if (!hasContent(authrc))
        return authrc;

    // Store user info in memcached keyed by session ID
    const value sid = string("OAuth1_") + (string)mkrand();
    const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth1", sid), content(userinfo), mc);
    if (!hasContent(prc))
        return mkfailure<int>(prc);

    // Send session ID to the client in a cookie
    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);
}