Skip to content
This repository has been archived by the owner on May 14, 2024. It is now read-only.

Application Only OAuth #62

Open
pixeline opened this issue Jan 20, 2016 · 4 comments
Open

Application Only OAuth #62

pixeline opened this issue Jan 20, 2016 · 4 comments
Assignees

Comments

@pixeline
Copy link

I have a script that posts a story to one of my subreddits. At some point this script should be launched via a cronjob.

This is where I'm stuck: my script works inside a user context, but not without manual authorization, which is necessary for the cron workflow.

I've read this page on the reddit API wiki, but do not understand how to make it work using the php SDK.

@jcleblanc jcleblanc self-assigned this Jan 21, 2016
@jcleblanc
Copy link
Owner

This 2-legged OAuth scenario is not currently supported in the SDK. After looking through the requirements for getting this working, this should just require some alterations to the constructor to pass through a different grant_type (and a device id) in the initial request. That should produce back the access token needed. All user centric methods would still be available in the SDK, but they would fail with a 403 back from Reddit servers. This would probably be the easiest way of getting it working. Let me take a look once I can.

@pixeline
Copy link
Author

All user centric methods would still be available in the SDK, but they would fail with a 403 back from Reddit servers.

So you mean that even if it worked, the API would not allow to write the story to the subreddit ?

Thank you very much for your follow up.

@xcodewarrier
Copy link

Any updates on getting this working?

There are many third-party apps that allow the user to post without authenticating every time so this must be possible.

@slanktapper
Copy link

slanktapper commented May 20, 2016

I added the following. I had to create a prime.php page to auth and pull the initial access and refresh tokens but after that everything works.

To use permanent tokens you store the access token and refresh token somewhere. Then you make calls with the access token until it expires, when it expires you re auth but with refresh token and then update. Refresh token is not updated.

NOTE: duration=permanent and I tried my best to obfiscate my implementation and leave the needed info.

wtformatting...

public function __construct($db){
$this->db = $db;
$this->redirect = false;
if (isset($_GET['code']))
{
$this->getNewAccessToken($_GET["code"]);
}
else
{
$sql = "SELECT token_type,access_token,refresh_token,expire_time FROM TABLE WHERE id = 'CONTORLID' AND access_token != '';";
//access_token != '' is for priming when broken
//You need to have this a row for controlid already in the DB, this will not add.
$res = $this->db->query($sql);
if ($row = $res->fetch_assoc())
{
if($row['expire_time']<date("YmdHis"))
{
$this->refreshTokens($row['refresh_token']);
}
else
{
$this->access_token = $row['access_token'];
$this->token_type = $row['token_type'];
}
}
else
{
$state = rand();
$urlAuth = sprintf("%s?response_type=code&client_id=%s&redirect_uri=%s&scope=%s&state=%s&duration=permanent",
redditConfig::$ENDPOINT_OAUTH_AUTHORIZE,
redditConfig::$CLIENT_ID,
redditConfig::$ENDPOINT_OAUTH_REDIRECT,
redditConfig::$SCOPES,
$state);

//forward user to auth page
//Framework handles redirect otherwise use header
$this->redirect = "$urlAuth";
}
}

//set API endpoint
$this->apiHost = redditConfig::$ENDPOINT_OAUTH;

//set auth mode for requests
$this->auth_mode = 'oauth';
}

private function getNewAccessToken($code)
{
//construct POST object for access token fetch request
$postvals = sprintf("code=%s&redirect_uri=%s&grant_type=authorization_code",
$code,
redditConfig::$ENDPOINT_OAUTH_REDIRECT);

//get JSON access token object (with refresh_token parameter)
$token = self::runCurl(redditConfig::$ENDPOINT_OAUTH_TOKEN, $postvals, null, true);

//store token and type
if (isset($token['access_token']))
{
$this->saveToken($token);
}
else
{
var_dump($token);
}
}

private function refreshTokens($rfToken)
{
//construct POST object for access token fetch request
$postvals = sprintf("refresh_token=%s&redirect_uri=%s&grant_type=refresh_token",
$rfToken,
redditConfig::$ENDPOINT_OAUTH_REDIRECT);

//get JSON access token object (with refresh_token parameter)
$token = self::runCurl(redditConfig::$ENDPOINT_OAUTH_TOKEN, $postvals, null, true);

//store token and type
if (isset($token['access_token']))
{
$this->saveToken($token);
}
else
{
var_dump($token);
}
}

private function saveToken($token)
{
$this->access_token = $token['access_token'];
$this->token_type = $token['token_type'];

$dt = new DateTime();
$dt = $dt->add(new DateInterval("PT".$token['expires_in']."S"));
$expires = $dt->format("YmdHis");

if (isset($token['refresh_token']))
{
$upd = "UPDATE TABLE SET token_type=?,access_token=?,refresh_token=?,expire_time=? WHERE id='CONTROLID';";
if ($stmt = $this->db->prepare($upd))
{
$type = $token['token_type'];
$access = $token['access_token'];
$refrsh = $token['refresh_token'];
$stmt->bind_param('ssss',$type,$access,$refrsh,$expires);
$stmt->execute();
$stmt->close();
}
}
else
{
$upd = "UPDATE TABLE SET token_type=?,access_token=?,expire_time=? WHERE id='CONTROLID';";
if ($stmt = $this->db->prepare($upd))
{
$type = $token['token_type'];
$access = $token['access_token'];
$stmt->bind_param('sss',$type,$access,$expires);
$stmt->execute();
$stmt->close();
}
}
}
``
`

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants