====== OAuth Key Exchange ======
In addition to users manually creating Zotero API keys from the zotero.org account settings, Zotero supports [[http://oauth.net/|OAuth]] 1.0a for API key exchange.
===== Registering Your Application =====
In order to start using OAuth to create API keys on behalf of users, you must [[/oauth/apps|register your application with Zotero]] to obtain a Client Key and Client Secret for use during all future OAuth handshakes between your application/website and zotero.org. Note that after you obtain an API key for a particular user these client credentials are not required for further Zotero API requests.
===== Requesting Specific Permissions =====
You can request specific permissions be allowed for your app by sending values to the new key form as GET values in the URL during the OAuth exchange.
The possible values to pre-populate for a user are:
* name (the description for the key)
* library_access (1 or 0 - allow read access to personal library items)
* notes_access (1 or 0 - allow read access to personal library notes)
* write_access (1 or 0 - allow write access to personal library)
* all_groups (none, read, or write - allow level of access to all current and future groups)
* identity=1 Don't create a key. Instead, use OAuth exchange only to get the user's identity information in order to do things that require no special permissions.
===== Using OAuth Handshake for Key Exchange =====
The OAuth endpoints for access to the Zotero API are as follow:
* Temporary Credential Request: ''https://www.zotero.org/oauth/request''
* Token Request URI: ''https://www.zotero.org/oauth/access''
* Resource Owner Authorization URI: ''https://www.zotero.org/oauth/authorize''
Rather than using OAuth to sign each request, OAuth should be used to obtain a key for subsequent requests. The key will be valid indefinitely, unless it is revoked by the user manually, so keys should be considered sensitive. Note, however, that the Zotero API uses exclusively HTTPS requests, so ordinary traffic will not expose the key.
In addition to receiving the token, API consumers using OAuth will need to retrieve the user's user ID from the response parameters returned by Zotero.org.
==== Example (PHP) ====
This PHP script demonstrates an implementation the application side of the OAuth handshake with zotero.org, using the API key thus obtained to make a request to the Zotero API.
/** Note that this example uses the PHP OAuth extension http://php.net/manual/en/book.oauth.php
* but there are various PHP libraries that provide similar functionality.
*
* OAuth acts over multiple pages, so we save variables we need to remember in $state in a temp file
*
* The OAuth handshake has 3 steps:
* 1: Make a request to the provider to get a temporary token
* 2: Redirect user to provider with a reference to the temporary token. The provider will ask them to authorize it
* 3: When the user is sent back by the provider and the temporary token is authorized, exchange it for a permanent
* token then save the permanent token for use in all future requests on behalf of this user.
*
* So an OAuth consumer needs to deal with 3 states which this example covers:
* State 0: We need to start a fresh OAuth handshake for a user to authorize us to get their information.
* We get a request token from the provider and send the user off to authorize it
* State 1: The provider just sent the user back after they authorized the request token
* We use the request token + secret we stored for this user and the verifier the provider just sent back to
* exchange the request token for an access token.
* State 2: We have an access token stored for this user from a past handshake, so we use that to make data requests
* to the provider.
**/
//initialize some variables to start with.
//clientkey, clientSecret, and callbackurl should correspond to http://www.zotero.org/oauth/apps
$clientKey = '9c6221a6ccae7639711a';
$clientSecret = '39091046dc9cf4dc3b61';
$callbackUrl = 'http://localhost/oauthtestentry.php';
//the endpoints are specific to the OAuth provider, in this case Zotero
$request_token_endpoint = 'https://www.zotero.org/oauth/request';
$access_token_endpoint = 'https://www.zotero.org/oauth/access';
$zotero_authorize_endpoint = 'https://www.zotero.org/oauth/authorize';
//Functions to save state to temp file between requests, DB should replace this functionality
function read_state(){
return unserialize(file_get_contents('/tmp/oauthteststate'));
}
function write_state($state){
file_put_contents('/tmp/oauthteststate', serialize($state));
}
function save_request_token($request_token_info, $state){
// Make sure the request token has all the information we need
if(isset($request_token_info['oauth_token']) && isset($request_token_info['oauth_token_secret'])){
// save the request token for when the user comes back
$state['request_token_info'] = $request_token_info;
$state['oauthState'] = 1;
write_state($state);
}
else{
die("Request token did not return all the information we need.");
}
}
function get_request_token($state){
if($_GET['oauth_token'] != $state['request_token_info']['oauth_token']){
die("Could not find referenced OAuth request token");
}
else{
return $state['request_token_info'];
}
}
function save_access_token($access_token_info, $state){
if(!isset($access_token_info['oauth_token']) || !isset($access_token_info['oauth_token_secret'])){
//Something went wrong with the access token request and we didn't get the information we need
throw new Exception("OAuth access token did not contain expected information");
}
//we got the access token, so save it for future use
$state['oauthState'] = 2;
$state['access_token_info'] = $access_token_info;
write_state($state); //save the access token for all subsequent resquests, in Zotero's case the token and secret are just the same Zotero API key
}
function get_access_token($state){
if(empty($state['access_token_info'])){
die("Could not retrieve access token from storage.");
}
return $state['access_token_info'];
}
//Initialize our environment
//check if there is a transaction in progress
//for testing purpose, start with a fresh state to perform a new handshake
if(empty($_GET['reset']) && file_exists('/tmp/oauthteststate')){
$state = read_state();
}
else{
$state = array();
$state['localUser'] = 'localUserInformation';
$state['oauthState'] = 0; //we do not have an oauth transaction in process yet
write_state($state);
}
// If we are in state=1 there should be an oauth_token, if not go back to 0
if($state['oauthState'] == 1 && !isset($_GET['oauth_token'])){
$state['oauthState'] = 0;
}
//Make sure we have OAuth installed depending on what library you're using
if(!class_exists('OAuth')){
die("Class OAuth does not exist. Make sure PHP OAuth extension is installed and enabled.");
}
//set up a new OAuth object initialized with client credentials and methods accepted by the provider
$oauth = new OAuth($clientKey, $clientSecret, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_FORM);
$oauth->enableDebug(); //get feedback if something goes wrong. Should not be used in production
//Handle different parts of the OAuth handshake depending on what state we're in
switch($state['oauthState']){
case 0:
// State 0 - Get request token from Zotero and redirect user to Zotero to authorize
try{
$request_token_info = $oauth->getRequestToken($request_token_endpoint, $callbackUrl);
}
catch(OAuthException $E){
echo "Problem getting request token
Among the most interesting of Plutarch’s religious writings is one entitled On the Delays in the Divine Vengeance. As might be expected from the name, it deals with a problem closely akin to that which ages before had been made the subject of such sublime imagery and such inconclusive reasoning by the author of the Book of Job. What troubled the Hebrew poet was the apparently undeserved suffering of the just. What the Greek moralist feels himself called on to explain is the apparent prosperity and impunity of the wicked. He will not for a moment admit that crime remains unavengeful; his object is to show why the retribution does not follow directly on the deed. And, in order to account for this, he adduces a number of very ingenious reasons. By acting deliberately rather than in blind anger, the gods wish to read us a useful lesson in patience and forbearance. Sometimes their object is to give the sinner an opportunity for repentance and amendment; or else they may be holding him in reserve for the performance of some beneficial work. At other times, their justice is delayed only that it may be manifested by some signal and striking form of retribution. In many cases, the final stroke has been preceded by long years of secret torment; and even where no suffering seems to be inflicted, the pangs of remorse may furnish a sufficient expiation. Or again, vengeance may be reserved for a future generation. Some persons hold that to267 visit the sins of the fathers on the children is unjust, but in this they are profoundly mistaken. Members of the same family and citizens of the same state are connected as parts of one organic whole; sharing in the benefits which accrue from the good deeds of their predecessors, it is right that they should also share in the responsibility for their crimes. Moreover, the posterity of the wicked inherit a sinful disposition which, as the gods can clearly foresee, would betray itself in overt acts were they not cut off in their youth. And it is equally an error to suppose that the original wrongdoers remain unaffected by the retribution which befalls their descendants. On the contrary, they witness it from the next world, where it adds poignancy to their remorse, and entails on them fresh penalties over and above those which they have already been doomed to suffer. This preference of pure abstract speculation to beneficent290 action may be traced to the influence of Aristotle. Some of the most enthusiastic expressions used by Plotinus in speaking of his supreme principle seem to have been suggested by the Metaphysics and the last book of the Nicomachean Ethics. The self-thinking thought of the Stagirite does not, indeed, take the highest rank with him. But it is retained in his system, and is only relegated to a secondary place because, for reasons which we shall explain hereafter, it does not fulfil equally well with Plato’s Idea of Good, the condition of absolute and indivisible unity, without which a first principle could not be conceived by any Greek philosopher. But this apparent return to the standpoint of the Republic really involves a still wider departure from its animating spirit. In other words, Plotinus differs from Aristotle as Aristotle himself had differed from Plato; he shares the same speculative tendency, and carries it to a greater extreme. "Yes?" she answered, and stroked the head of the fawn. She dropped beside him and tried to hold him down. "He did not know I was coming here," she pleaded. "It was a mistake, Jack! Will you wait until I tell you? Will you wait?" She was clinging around his neck and would not be shaken off. He dragged her in the dust, trying to get free himself. Feeling entirely at ease, he climbed into the car, with a copy of the Cincinnati Gazette, which he had bought of a newsboy, lighted his pipe, put on his spectacles, and settled down to a labored, but thorough perusal of the paper, beginning at the head-lines on the upper left-hand corner, and taking in every word, advertisements and all, as systematically as he would weed a garden-bed or milk a cow. The Deacon never did anything slip-shod, especially when he had to pay 10 cents for a copy of the Cincinnati Gazette. He was going to get his full money's worth, and if it was not in the news and editorials, he would take it out of the advertisements and patent medicine testimonials. He was just going through a convincing testimonial to the manifold virtues of Spalding's Prepared Glue, when there was a bump, the sound of coupling, and his car began to move off. Little Sammy Woggles came out presently to get some wood. Shorty called him to him. There was something fascinatingly mysterious in his tones and actions to that youth, who devoured dime novels on the sly. "GREAT Jehosephat, how hungry I am," suddenly ejaculated Shorty, stopping his cheering, as the thunder of the guns died away into an occasional shot after the rebels galloping back to the distant woods on the ridge from which they had emerged. "It isn't funny, Albin," Dodd said woodenly. "It isn't a game." "Who fill their pockets at Scott's Float, "No—I d?an't say it. I did write 'em. But it's all your fault that I did—so you've no right to miscall me." Alice Jury said nothing, and Reuben began to feel vaguely uncomfortable. What queer eyes she had!—they seemed to bore into him like nails. He suddenly rose to his feet. "Where's master?" "Now, lads, to your homes," cried Turner, as they hurried on, "every man of ye. Go by different roads, and you will not be suspected. There is not a man they can swear to but myself. Now, brave hearts, farewell! We may not meet together again: but all the harm I wish ye is, that Calverley and I may soon meet; and if ever he plagues free man or bond among ye after that, say Wat Turner is a coward—Away! Tom Merritt," said he, drawing the mason aside, "do you think of leaving Winchcombe?—you know there are always busy tongues." HoME美女护士性交不雅照
ENTER NUMBET 0017
";
echo $E->lastResponse; echo "
";
die;
}
save_request_token($request_token_info, $state);
// Send the user off to the provider to authorize your request token
// This could also be a link the user follows
$redirectUrl = "{$zotero_authorize_endpoint}?oauth_token={$request_token_info['oauth_token']}";
header('Location: ' . $redirectUrl);
break;
case 1:
// State 1 - Handle callback from Zotero and get and store an access token
// Make sure the token we got sent back matches the one we have
// In practice we would look up the stored token and whatever local user information we have tied to it
$request_token_info = get_request_token($state);
//if we found the temp token, try to exchange it for a permanent one
try{
//set the token we got back from the provider and the secret we saved previously for the exchange.
$oauth->setToken($_GET['oauth_token'], $request_token_info['oauth_token_secret']);
//make the exchange request to the provider's given endpoint
$access_token_info = $oauth->getAccessToken($access_token_endpoint);
save_access_token($access_token_info, $state);
}
catch(Exception $e){
//Handle error getting access token
die("Caught exception on access token request");
}
// Continue on to authorized state outside switch
break;
case 2:
//get previously stored access token if we didn't just get it from a handshack
$access_token_info = get_access_token($state);
break;
}
// State 2 - Authorized. We have an access token stored already which we can use for requests on behalf of this user
echo "Have access token for user.";
//zotero will send the userID associated with the key along too
$zoteroUserID = $access_token_info['userID'];
//Now we can use the token secret the same way we already used a Zotero API key
$zoteroApiKey = $access_token_info['oauth_token_secret'];
$feed = file_get_contents("https://api.zotero.org/users/{$zoteroUserID}/items?limit=1&key={$zoteroApiKey}");
var_dump($state);
echo "" . htmlentities($feed) . "
";
/** OAuth support for all api requests may be added in the future
* but for now secure https provides similar benefits anyway
*/
gdic.net.cn
www.k-led.net.cn
www.taike8.com.cn
wanwo8.net.cn
decan3.com.cn
www.luqie4.net.cn
jcb213.com.cn
www.yaoya9.com.cn
yeyin5.com.cn
www.akv628.com.cn