Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
dev:oauth [2011/01/20 17:22] – fcheslack | dev:oauth [2017/11/12 19:53] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== OAuth Key Exchange ====== | + | < |
+ | in the process of updating the documentation for | ||
+ | <a href=" | ||
+ | may be outdated in the meantime. Thanks for your understanding.</ | ||
- | In addition to users manually creating Zotero API keys from the zotero.org account settings, Zotero supports [[http:// | ||
- | ===== Registering Your Application ===== | + | See [[dev/web_api/oauth]]. |
- | + | ||
- | In order to start using OAuth to create API keys on behalf of users, you must [[https:// | + | |
- | + | ||
- | ===== Using OAuth Handshake for Key Exchange ===== | + | |
- | + | ||
- | Below is an example php file implementing the application side of the OAuth handshake with zotero.org and using the key obtained to make a request to the Zotero API. | + | |
- | + | ||
- | + | ||
- | <?php | + | |
- | /** Note that this example uses the php OAuth extension http:// | + | |
- | * 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 | + | |
- | * | + | |
- | * 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. | + | |
- | **/ | + | |
- | // | + | |
- | // | + | |
- | $clientKey = ' | + | |
- | $clientSecret = ' | + | |
- | $callbackUrl = ' | + | |
- | //the endpoints are specific to the OAuth provider, in this case Zotero | + | |
- | $request_token_endpoint = ' | + | |
- | $access_token_endpoint = ' | + | |
- | $zotero_authorize_endpoint = ' | + | |
- | //Functions to save state to temp file between requests, DB should replace this functionality | + | |
- | function read_state(){ | + | |
- | return unserialize(file_get_contents('/ | + | |
- | } | + | |
- | function write_state($state){ | + | |
- | file_put_contents('/ | + | |
- | } | + | |
- | function save_request_token($request_token_info, | + | |
- | // Make sure the request token has all the information we need | + | |
- | if(isset($request_token_info[' | + | |
- | // save the request token for when the user comes back | + | |
- | $state[' | + | |
- | $state[' | + | |
- | write_state($state); | + | |
- | } | + | |
- | else{ | + | |
- | die(" | + | |
- | } | + | |
- | } | + | |
- | function get_request_token($state){ | + | |
- | if($_GET[' | + | |
- | die(" | + | |
- | } | + | |
- | else{ | + | |
- | return $state[' | + | |
- | } | + | |
- | } | + | |
- | function save_access_token($access_token_info, | + | |
- | if(!isset($access_token_info[' | + | |
- | //Something went wrong with the access token request and we didn't get the information we need | + | |
- | throw new Exception(" | + | |
- | } | + | |
- | //we got the access token, so save it for future use | + | |
- | $state[' | + | |
- | $state[' | + | |
- | write_state($state); | + | |
- | } | + | |
- | function get_access_token($state){ | + | |
- | if(empty($state[' | + | |
- | die(" | + | |
- | } | + | |
- | return $state[' | + | |
- | } | + | |
- | // | + | |
- | //check if there is a transaction in progress | + | |
- | //for testing purpose, start with a fresh state to perform a new handshake | + | |
- | if(empty($_GET[' | + | |
- | $state = read_state(); | + | |
- | } | + | |
- | else{ | + | |
- | $state = array(); | + | |
- | $state[' | + | |
- | $state[' | + | |
- | write_state($state); | + | |
- | } | + | |
- | // If we are in state=1 there should be an oauth_token, | + | |
- | if($state[' | + | |
- | $state[' | + | |
- | } | + | |
- | //Make sure we have OAuth installed depending on what library you're using | + | |
- | if(!class_exists(' | + | |
- | die(" | + | |
- | } | + | |
- | //set up a new OAuth object initialized with client credentials and methods accepted by the provider | + | |
- | $oauth = new OAuth($clientKey, | + | |
- | $oauth-> | + | |
- | //Handle different parts of the OAuth handshake depending on what state we're in | + | |
- | switch($state[' | + | |
- | case 0: | + | |
- | // State 0 - Get request token from Zotero and redirect user to Zotero to authorize | + | |
- | try{ | + | |
- | $request_token_info = $oauth-> | + | |
- | } | + | |
- | catch(OAuthException $E){ | + | |
- | echo " | + | |
- | echo $E-> | + | |
- | die; | + | |
- | } | + | |
- | save_request_token($request_token_info, | + | |
- | + | ||
- | // Send the user off to the provider to authorize your request token | + | |
- | // This could also be a link the user follows | + | |
- | $redirectUrl = " | + | |
- | header(' | + | |
- | 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-> | + | |
- | //make the exchange request to the provider' | + | |
- | $access_token_info = $oauth-> | + | |
- | save_access_token($access_token_info, | + | |
- | } | + | |
- | catch(Exception $e){ | + | |
- | //Handle error getting access token | + | |
- | die(" | + | |
- | } | + | |
- | // 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[' | + | |
- | //Now we can use the token secret the same way we already used a Zotero API key | + | |
- | $zoteroApiKey = $access_token_info[' | + | |
- | $feed = file_get_contents(" | + | |
- | var_dump($state); | + | |
- | echo "< | + | |
- | /** OAuth support for all api requests may be added in the future | + | |
- | * but for now secure https provides similar benefits anyway | + | |
- | */ | + | |
- | ?> | + |