File: UsingAuthsub.html

package info (click to toggle)
gdata-sharp 2.2.0.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 12,092 kB
  • sloc: cs: 67,781; xml: 38,234; python: 163; makefile: 149; sh: 27
file content (248 lines) | stat: -rw-r--r-- 13,951 bytes parent folder | download | duplicates (2)
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>AuthSub in .NET</title>


</head>
<body>

<!-- Article Begins -->
<h1>Using AuthSub with the .NET Client Library</h1>

<em>Jeff Fisher, Google data APIs team
<br/>August 2007</em>

<ul>
  <li><a href="#introduction">Introduction: Why is AuthSub Important?</a></li>
  <li><a href="#handlingauth">Handling Authentication</a></li>
  <li><a href="#secureauthsub">Secure (Registered) AuthSub</a></li>
  <li><a href="#completecode">Complete Code Listing</a></li>

  <li><a href="#conclusion">Conclusion</a></li>
</ul>

<h3><a name="introduction">Introduction: Why is AuthSub Important?</a></h3>

<p class="para">The great thing about the Google data APIs ("GData" for short) is how they allow developers 
to build applications that interact with Google services. More specifically, they allow
you to access private user data for use in your application. The APIs enable you to
write applications to synchronize, import, export, and otherwise manage that data.
While the APIs grant you these powerful abilities, you have to remember to use
them responsibly. Since user data is private information, naturally you want to
access it in a secure manner. A key part of this is being able to authenticate
to Google's servers in a secure fashion.</p>

<p class="para">Let's say you have a great new web application that you want to have tied into the data stored in Google web services. Now you want to authenticate in order to access this private data. Why not just use something simple, like <a href="http://code.google.com/apis/accounts/AuthForInstalledApps.html">ClientLogin</a>? Well, that will do the trick, but then you are handling even <i>more</i> private data: the user's login credentials. ClientLogin requires your application to ask for the user's Google username and password. This is okay for a desktop application that is running on the user's personal machine, but is less than ideal for a web-based application. Besides the liability of handling these credentials on your own server, perhaps some of your more cautious users would be afraid that you might store their information. Another common concern from users is if they only wish to grant a program access to one particular service (like the events on their Google Calendar) but not to some other service (like their Google Documents). <a href="http://code.google.com/apis/accounts/AuthForWebApps.html">AuthSub</a> solves both of these problems by letting a user authenticate through Google's servers and allows your program to only request the access that it needs.</p>

<p class="para">Now that you've read enough about the theory behind AuthSub, it's time to move on to some coding! For this article, I chose to keep things simple and do everything inside of a single ASP page, but you should be able to easily integrate the techniques demonstrated here into your own application.</p>

<h3><a name="handlingauth">Handling Authentication</a></h3>

<p class="para">So what is needed to actually use AuthSub in your web application? First, there are some standard imports from the GData client library:</p>

<pre>
&lt;%@ Import Namespace="Google.GData.Client" %&gt;
&lt;%@ Import Namespace="Google.GData.Extensions" %&gt;
&lt;%@ Import Namespace="System.Net" %&gt;

</pre>

<p class="para">Now the first thing you have to do is send the user to a specially-crafted URL. This is what allows Google's servers to handle the authentication and then redirect the user back to your website. Fortunately, you don't have to generate this URL manually, as there are methods to do so for you. Let's look at an example:</p>

<pre>
authSubUrl = AuthSubUtil.getRequestUrl(target, scope, secure, session);
</pre>

<ul>
<li><strong>target</strong> This is a string containing the URL to your web application. This is where the user will be redirected to after authenticating.</li>
<li><strong>scope</strong> This string is determined by what API you are using. It corresponds to one of the feeds in a GData API. For example, the feed containing all the calendar information for a user is "http://www.google.com/calendar/feeds/default/private/full".</li> 

<li><strong>secure</strong> This is a boolean that tells the server you have <a href="http://code.google.com/apis/accounts/RegistrationForWebApps.html">registered with Google</a> and will cryptographically sign your requests to the server. This argument is usually false by default, especially when working in a test environment.</li> <li><strong>session</strong> This is another boolean that indicates that you would like a "session token" rather than a "one-time use token". The role of this argument will become more clear in a moment.</li>
</ul>

<p class="para">After the user clicks in the generated URL, they will be taken to a Google Accounts page which allows them to sign in to their Google account. They will then be redirected back to the web page you specified in the "target" variable, but with a query parameter "token" which contains a one-time use token. Normally, this token can be used exactly once. That is to say, it can be used to perform one action on a given feed. However, if you specified the "session" parameter as true, it can be exchanged for a "session token" that can be reused until the user ends the session. You can do this in the following manner:</p>

<pre>

String token = Request.QueryString["token"];
Session["token"] = AuthSubUtil.exchangeForSessionToken(token, null).ToString();
</pre>

<p class="para">Here you extract the token from the query parameter and exchange it for a "session token". Then, so that it could be saved for later use, you can chose to store it in the automatic <code>Session</code> array of .NET. Naturally, you could also choose to store the token within a database. The next step is to use this token to make an authenticated request:</p>

<pre>
GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "My-Cool-Application");
authFactory.Token = (String) Session["token"];
CalendarService service = new CalendarService(authFactory.ApplicationName);
service.RequestFactory = authFactory;
</pre>

<p class="para">Here you set up a CalendarService object to interact with the Google Calendar API using AuthSub for authentication. Note the "cl" used in the constructor for <code>GAuthSubRequestFactory</code> is the service name for Calendar. You can consult <a href="http://code.google.com/support/bin/answer.py?answer=62712&amp;topic=10364">the documentation</a> for other service names.</p>

<h3><a name="secureauthsub">Secure (Registered) AuthSub</a></h3>

<p class="para">If you choose to <a href="http://code.google.com/apis/accounts/RegistrationForWebApps.html">register your web application</a>, then you can enable an additional level of security while using AuthSub. This allows you to digitally sign all requests made by your code, making it so someone can't use AuthSub tokens issued to you unless they have your private key. The first step is making sure you are generating the correct AuthSub link when calling <code>AuthSubUtil.getRequestUrl</code> by setting the "secure" argument to true. There are two other code changes you will need to make:</p>


<pre>
String token = Request.QueryString["token"];
Session["token"] = AuthSubUtil.exchangeForSessionToken(token, rsaKey).ToString();

...

authFactory.PrivateKey = rsaKey;
</pre>

<p class="para">First, notice instead of <code>null</code>, you now pass the variable "rsaKey" to the <code>exchangeForSessionToken</code> method. This same variable is also used to set a property of our <code>GAuthSubRequestFactory</code> when setting up the connection to the service. The "rsaKey" variable is an <code>RSACryptoServiceProvider</code> corresponding to the private key component of the x509 certificate that you registered with Google.</p>

<p class="para">Generating an RSA private key and self-signed certificate can be a little confusing, especially since the .NET framework doesn't understand keys or certificates stored in the PEM format. The following commands show how to generate a private key and public certificate using the <a href="http://www.openssl.org/">OpenSSL</a> suite of tools:</p>

<pre>
openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj \
  '/C=US/ST=CA/L=Mountain View/CN=www.example.com' -keyout \
  test_key.pem -out test_cert.pem

openssl pkcs12 -export -in test_cert.pem -inkey test_key.pem \
  -out test_cert.pfx -name "Testing Certificate"
</pre>

<p class="para">The first step generates a private key and a public X509 certificate both in PEM format called "test_key.pem" and "test_cert.pem", respectively. Note the certificate is set to be registered to "www.example.com" based in Mountain View, CA, US. Substitute the proper values for your company here. The "test_cert.pem" file contains the information you need to submit on the <a href="http://code.google.com/apis/accounts/RegistrationForWebApps.html">AuthSub registration page</a>.</p>

<p class="para">The second step generates a PFX file from your private key and certificate. This file can be imported into the .NET client library to digitally sign requests made to the GData APIs. The following code shows how you can import the private key from the PFX file into a web application:</p>


<pre>
protected AsymmetricAlgorithm getRsaKey()
{

  X509Certificate2 cert = new X509Certificate2("C:/MyAspSite/test_cert.pfx","");
  RSACryptoServiceProvider privateKey = cert.PrivateKey as RSACryptoServiceProvider;

  return privateKey;
}
</pre>

<p class="para">The <code>getRsaKey()</code> function defined by this snippet can be used in place of the "rsaKey" variable shown above when used to authenticate to the APIs. Naturally, the file path should be replaced with the appropriate location of the PFX file you generated.</p>


<h3><a name="completecode">Complete Code Listing</a></h3>

<p class="para">The easiest way to show how to use the methods demonstrated in the previous section is with a live example. The following sample code is a simple ASP page that uses AuthSub to authenticate the user, then prints out the events of their Google Calendar.</p>

<pre>
&lt;%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %&gt;

&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

&lt;%@ Import Namespace="Google.GData.Client" %&gt;
&lt;%@ Import Namespace="Google.GData.Extensions" %&gt;
&lt;%@ Import Namespace="Google.GData.Calendar" %&gt;
&lt;%@ Import Namespace="System.Net" %&gt;

&lt;script runat="server"&gt;
    void PrintCalendar() {

        GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "TesterApp");
        authFactory.Token = (String) Session["token"];
        CalendarService service = new CalendarService(authFactory.ApplicationName);
        service.RequestFactory = authFactory;

        EventQuery query = new EventQuery();

        query.Uri = new Uri("http://www.google.com/calendar/feeds/default/private/full");

        try
        {
            EventFeed calFeed = service.Query(query);
            foreach (Google.GData.Calendar.EventEntry entry in calFeed.Entries)
            {
                Response.Write("Event: " + entry.Title.Text + "&lt;br/&gt;");
            }
        }
        catch (GDataRequestException gdre)
        {
            HttpWebResponse response = (HttpWebResponse)gdre.Response;
            
            //bad auth token, clear session and refresh the page
            if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                Session.Clear();
                Response.Redirect(Request.Url.AbsolutePath, true);
            }
            else
            {
                Response.Write("Error processing request: " + gdre.ToString());
            }
        }
    }

&lt;/script&gt;


&lt;html xmlns="http://www.w3.org/1999/xhtml" &gt;
&lt;head runat="server"&gt;
    &lt;title&gt;Test Site&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;

    &lt;form id="form1" runat="server"&gt;
    &lt;h1&gt;AuthSub Sample Page&lt;/h1&gt;
    &lt;div&gt;
    &lt;%
        GotoAuthSubLink.Visible = false;
        
        if (Session["token"] != null)
        {
            PrintCalendar();
        }
        else if (Request.QueryString["token"] != null)
        {
            String token = Request.QueryString["token"];
            Session["token"] = AuthSubUtil.exchangeForSessionToken(token, null).ToString();
            Response.Redirect(Request.Url.AbsolutePath, true);
        }
        else //no auth data, print link
        {
            GotoAuthSubLink.Text = "Login to your Google Account";
            GotoAuthSubLink.Visible = true;
            GotoAuthSubLink.NavigateUrl = AuthSubUtil.getRequestUrl(Request.Url.ToString(),
                "http://www.google.com/calendar/feeds/",false,true);
        }
        
     %&gt;
    &lt;asp:HyperLink ID="GotoAuthSubLink" runat="server"/&gt;

    &lt;/div&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>


<h3><a name="conclusion">Conclusion</a></h3>

<p class="para">AuthSub allows your web application to access data stored
in a user's Google account in a secure and controlled manner. Using the .NET
client library makes it easy to integrate your ASP-based website with Google
services. This article is meant to get you started, but there are additional
resources that you are encouraged to consult: </p>

<ul>
  <li>
<a href="http://code.google.com/apis/accounts/AuthForWebApps.html">AuthSub documentation</a></li>
<li>
<a href="http://code.google.com/apis/gdata/authsub.html">AuthSub with
  GData Client Libraries Guide</a></li>
<li>
<a href="http://groups.google.com/group/Google-Accounts-API">Accounts API
  developer forum</a></li>
</ul>




<!-- Article Ends -->

</body>
</html>