/* Copyright (c) 2009 Yahoo! Inc. All rights reserved. The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license */ package com.yahoo.social.utils { import com.yahoo.crypto.util.Base64; import com.yahoo.oauth.OAuthToken; import com.yahoo.social.methodgroups.AuthorizationRequest; import flash.net.SharedObject; import flash.net.SharedObjectFlushStatus; import flash.utils.ByteArray; /** * An implementation of IYahooSessionStore that uses a SharedObject to keep OAuth * request and access tokens cached on the users machine for later use. * @author zachg * * @example * * YahooSession.YAP_APPID = "your-appid"; * * var _session:YahooSession = new YahooSession(CONSUMER_KEY, CONSUMER_SECRET); * var _accessToken:OAuthToken = _session.sessionStore.getAccessToken(); * * if( _accessToken ) { * // try to set the token * var hasSession:Boolean = _session.setAccessToken(_accessToken); * * if(hasSession == false) { * _session.auth.addEventListener(YahooResultEvent.GET_ACCESS_TOKEN_SUCCESS, handleGetAccessToken); * _session.auth.getAccessToken(_accessToken); * } else { * doStuff(); * } * } else { * // start request token and user authorization flow. * } * * * function handleGetAccessToken(event:YahooResultEvent):void * { * _accessToken = event.data as OAuthToken; * * _session.setAccessToken(_accessToken); * _session.sessionStore.setAccessToken(_accessToken); * * doStuff(); * } * * function doStuff():void * { * // load profile, connections or updates * } * */ public class YahooSessionStore extends Object implements IYahooSessionStore { /** * @private * Storage for the sharedObject property. */ private var $sharedObject:SharedObject; /** * @private * Storage for the shareData property. */ private var $shareData:Boolean = false; /** * @private * Storage for the sharedObjectPath property */ private var $sharedObjectPath:String = "YahooSessionData"; /** * Class constructor * Creates */ public function YahooSessionStore() { super(); initSharedObject(); } /** * Determines Whether to share the auto-complete data with other applications * or keep it private to this application. * *

Please note that setting this to true will all applications in the domain * to access any information in the Shared Object. For instance, if a third party * application hosted on the same domain knows the name of the Shared Object * (which is by default "YahooSessionData"), they may be able to read and write to it.

* *

If you choose to set this to true, you should consider setting the * sharedObjectPath to a value only your applications are aware of, * especially a password-like value or some value returned from a server. * In this way, you make it difficult or impossible for a third party * to access this information.

* * @see #sharedObjectPath * @see flash.net.SharedObject * @default false * @return * */ public function get shareData():Boolean { return $shareData; } /** * @private */ public function set shareData(value:Boolean):void { $shareData = value; initSharedObject(); } /** * The name of the SharedObject in which to store session token entries. * @return * */ public function get sharedObjectPath():String { return $sharedObjectPath; } /** * @private * @param value * */ public function set sharedObjectPath(value:String):void { $sharedObjectPath = value; initSharedObject(); } /** * Sets the accessToken value of the SharedObject data and flushes the data. * @param session * @return * */ public function setAccessToken(token:OAuthToken):Boolean { $sharedObject.data.accessToken = (token && !token.empty) ? encodeToken(token) : null; return flush(); } /** * Reads the access token data and returns an OAuthToken object. * @return * */ public function getAccessToken():OAuthToken { var token:OAuthToken = null; // if the accessToken object is present in the cache // decode it and convert back into an OAuthToken if($sharedObject.data.accessToken) { var data:Object = decodeToken($sharedObject.data.accessToken); token = (data) ? AuthorizationRequest.toAccessToken(data) : null; } return token; } /** * Removes the access token from the SharedObject. * @return * */ public function clearAccessToken():Boolean { $sharedObject.data.accessToken = null; return flush(); } /** * * @param session * @return * */ public function setRequestToken(token:OAuthToken):Boolean { $sharedObject.data.requestToken = (token && !token.empty) ? encodeToken(token) : null; return flush(); } /** * Reads the request token data and returns an OAuthToken object. * @return * */ public function getRequestToken():OAuthToken { var token:OAuthToken = null; // if the requestToken object is present in the cache // decode it and convert back into an OAuthToken if($sharedObject.data.requestToken) { var data:Object = this.decodeToken($sharedObject.data.requestToken); token = (data) ? AuthorizationRequest.toRequestToken(data) : null; } return token; } /** * Removes the request token from the SharedObject. * @return * */ public function clearRequestToken():Boolean { $sharedObject.data.requestToken = null; return flush(); } /** * Removes the request and access tokens from the shared object by * purging all of the data and deleting the shared object from the disk. * @return * */ public function clearSessionToken():void { $sharedObject.clear(); } /** * Creates a Base64 encoded string representing the token provided. * * @param token * @return * */ protected function encodeToken(token:OAuthToken):String { // write the token into a byte array, then encode the bytes to base64 // this method ensures that dynamic properties of the token are included var bytes:ByteArray = new ByteArray() bytes.writeObject(token); bytes.position=0; return Base64.encodeByteArray(bytes); } /** * Decodes a Base64 encoded string returning a native object containing * the OAuth token variables. * * @param str * @return * */ protected function decodeToken(str:String):Object { // push the base64 decoded value into a byte array // then return the object var bytes:ByteArray = Base64.decodeToByteArray(str); bytes.position=0; return bytes.readObject(); } /** * Flushes the shared object. * @return Returns true if the flush was successfully completed. * */ protected function flush():Boolean { // confirm the shared object was sucessfully flushed. return ($sharedObject && $sharedObject.flush()==SharedObjectFlushStatus.FLUSHED); } /** * * @private */ private function initSharedObject():void { $sharedObject = SharedObject.getLocal(sharedObjectPath, $shareData?"/":null); } } }