My favorites | Sign in
Project Home Downloads Wiki Issues Source
Checkout   Browse   Changes  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://www.adobe.com/2006/mxml"
initialize="onInitialized()"
applicationComplete="onLoaded()">
<Script>
import flash.external.ExternalInterface;
import flash.net.navigateToURL;
import mx.controls.Alert;

private function onInitialized() : void {
// Load the cross domain policy file for each of the googleapis.com
// domains used. At the very least, we need the ones for the API (photos)
// and the one for AuthSub for ActionScript (accounts).
Security.loadPolicyFile('http://photos.googleapis.com/data/crossdomain.xml');
Security.loadPolicyFile('https://accounts.googleapis.com/crossdomain.xml');
}

private function onLoaded() : void {
// Once the application has loaded, check to see if an AuthSub token was
// placed into the current page's URL. If it was, the user has already
// authenticated, we can continue to connect to the the service itself.
// In a real application, the long-term cookie would also be stored and
// checked here, to remove the need for the user to authenticate for this
// application every time it is used.
var searchPortion : String = ExternalInterface.call('window.location.search.toString');

if (searchPortion.length > 0) {
// remove the ? from the token and extract the token.
searchPortion = searchPortion.substring(1);

// NOTE: Real applications should parse the URL properly.
if (searchPortion.indexOf('token=') == 0) {
getLongLivedToken(searchPortion.substring(6));
return;
}
}

// No token found; redirect the user to the AuthSub page. Note that this URL
// is on the google.com domain. We can contact the google.com domain because
// this isn't a request from within Flash, but rather a page redirect.
var getTokenPage : URLRequest = new URLRequest('https://www.google.com/accounts/AuthSubRequest');

// Construct the parameters of the AuthSub request. These are the same parameters
// as normal AuthSub, which can be found here: http://code.google.com/apis/accounts/docs/AuthSub.html#AuthSubRequest
var authSubParams : URLVariables = new URLVariables();
authSubParams['scope'] = 'http://photos.googleapis.com/data'; // photos API
authSubParams['session'] = 1; // single-use token
authSubParams['secure'] = 0; // non-secure apps
authSubParams['next'] = 'photos.swf'; // The URL of this app.

getTokenPage.data = authSubParams;
navigateToURL(getTokenPage, '_top');
}

private function getLongLivedToken(singleUseToken : String) : void {
// Construct a call to the AuthSub for ActionScript endpoint on accounts.googleapis.com.
// This call will exchange the single use token given to use by AuthSub for a long-term
// token that we can use to make requests to endpoints such as Photos.
var getTokenRequest : URLRequest = new URLRequest('https://accounts.googleapis.com/accounts/AuthSubSessionToken');

// Due to a bug in Flash, a URLRequest with a GET request will
// not properly send headers. We therefore use POST for this and *ALL*
// requests.
getTokenRequest.method = URLRequestMethod.POST;

// Due to a bug in Flash, a URLRequest without a valid parameter will
// not properly send headers. We therefore add a useless parameter to
// make this code work.
getTokenRequest.data = new URLVariables('pleaseignore=ignore');

// Add the AuthSub for ActionScript headers.
getTokenRequest.requestHeaders.push(new URLRequestHeader('Authorization', 'AuthSub token="' + singleUseToken + '"'));

// Create the loader to get the token itself. The loader will callback
// to the following event handlers if and when the server responds.
var getToken : URLLoader = new URLLoader();
getToken.addEventListener(Event.COMPLETE, onGetTokenResult);
getToken.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onGetTokenFailed);
getToken.addEventListener(IOErrorEvent.IO_ERROR, onGetTokenFailed);

try {
getToken.load(getTokenRequest);
} catch (e : Error) {
Alert.show('Some error occurred: ' + e);
}
}

private function onGetTokenResult(e : Event) : void {
// Load the parameters from the response.
var getToken : URLLoader = URLLoader(e.target);
var params : URLVariables = new URLVariables(getToken.data);

// Parse the session token from the result. Real applications
// might at this point store the token in a long-term cookie so
// that repeated usages of the application do not require this entire
// authentication process.
var sessionToken : String = params.Token;

// Trim the newline from the end of the session token.
sessionToken = sessionToken.substring(0, sessionToken.length - 1);

Alert.show('session token: [' + sessionToken + ']');

// Prepare a request to the photos API for the private album
// of the user.
var albumRequest : URLRequest = new URLRequest('http://photos.googleapis.com/data/feed/api/user/default');
albumRequest.data = new URLVariables('access=private&amp;v=2&amp;err=xml');

// Due to a bug in Flash, a URLRequest with a GET request will
// not properly send headers. We therefore use POST for this and *ALL*
// requests.
albumRequest.method = URLRequestMethod.POST;

var authsubHeader : String = 'AuthSub token="' + sessionToken + '"';

// Add the Authorization header which uses the session token.
albumRequest.requestHeaders.push(new URLRequestHeader('Authorization', authsubHeader));

// The X-HTTP-Method-Override header tells the Photos API to treat this request
// as a GET request, even though it is being conducted as a POST (due to the bug
// mentioned above). This is very important, as GData APIs will react differently
// to different HTTP request types.
albumRequest.requestHeaders.push(new URLRequestHeader('X-HTTP-Method-Override', 'GET'));

// We expect ATOM XML to be returned.
albumRequest.requestHeaders.push(new URLRequestHeader('Content-Type', 'application/atom+xml'));

var getAlbum : URLLoader = new URLLoader();
getAlbum.addEventListener(Event.COMPLETE, onGetAlbumResult);
getAlbum.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onGetAlbumFailed);
getAlbum.addEventListener(IOErrorEvent.IO_ERROR, onGetAlbumFailed);

try {
getAlbum.load(albumRequest);
} catch (e : Error) {
Alert.show('Some error occurred: ' + e);
}
}

private function onGetAlbumResult(e : Event) : void {
// Load the XML from the response.
var getAlbum : URLLoader = URLLoader(e.target);
Alert.show('Returned XML: ' + getAlbum.data);
}

private function onGetTokenFailed(e : ErrorEvent) : void {
Alert.show('Some error occurred: ' + e);
}

private function onGetAlbumFailed(e : ErrorEvent) : void {
Alert.show('Some error occurred: ' + e);
}

</Script>
</Application>

Change log

r199 by api.e...@google.com on Jan 29, 2010   Diff
Adding AuthSubAS sample app
Go to: 
Sign in to write a code review

Older revisions

All revisions of this file

File info

Size: 7252 bytes, 155 lines

File properties

svn:executable
*
Powered by Google Project Hosting