1# OAuth 1.0 and 2.0 for Qt
2
3This library encapsulates the OAuth 1.0 and 2.0 client authentication flows, and the sending of authenticated HTTP requests.
4
5The primary target is Qt Quick applications on embedded devices.
6
7Notes to contributors:
8
9   * Please follow the coding style of the existing source
10   * Code contributions are released under Simplified BSD License, as specified in LICENSE. Do not contribute if this license does not suit your code
11
12## Classes
13
14Class | Header | Purpose
15:-- | :-- | :--
16O0AbstractStore | o0abstractstore.h | Base class of persistent stores
17O0BaseAuth | o0baseauth.h | Base class of OAuth authenticators
18O0SettingsStore | o0settingsstore.h | QSettings-based persistent store
19o0keyChainStore | o0keychainstore.h | Settings stored through the system keychain [keychain](https://github.com/frankosterfeld/qtkeychain)
20O0SimpleCrypt | o0simplecrypt.h | Simple encryption and decryption by Andre Somers
21O1 | o1.h | Generic OAuth 1.0 authenticator
22O1Dropbox | o1dropbox.h | Dropbox OAuth specialization
23O1Flickr | o1flickr.h | Flickr OAuth specialization
24O1Freshbooks | o1freshbooks.h | Freshbooks OAuth specialization
25O1Requestor | o1requestor.h | Makes authenticated OAuth 1.0 requests: GET, POST or PUT, handles timeouts
26O1RequestParameter | o1.h | An extra request parameter participating in request signing
27O1Twitter | o1twitter.h | Twitter OAuth specialization
28O1SmugMug | o1smugmug.h | SmugMug OAuth specialization
29O2 | o2.h | Generic OAuth 2.0 authenticator
30O2Facebook | o2facebook.h | Facebook OAuth specialization
31O2Gft | o2gft.h | Google Fusion Tables OAuth specialization
32O2Google | o2google.h | Google Oauth specialization [scopes](https://developers.google.com/identity/protocols/googlescopes)
33O2Hubic | o2hubic.h | Hubic OAuth specialization
34O2Reply | o2reply.h | A network request/reply that can time out
35O2ReplyServer | o2replyserver.h | HTTP server to process authentication responses
36O2Requestor | o2requestor.h | Makes authenticated OAuth 2.0 requests (GET, POST or PUT), handles timeouts and token expiry
37O2Skydrive | o2skydrive.h | OneDrive OAuth specialization
38O2SurveyMonkey | o2surveymonkey.h | SurveyMonkey OAuth specialization
39OXTwitter | oxtwitter.h | Twitter XAuth specialization
40O2Uber | o2uber.h | Uber OAuth specialization
41
42## Installation
43
44Clone the Github repository, then add all files in *src* to your Qt project, by including *src/src.pri*.
45
46## Basic Usage
47
48This example assumes a hypothetical Twitter client that will post tweets. Twitter is using OAuth 1.0.
49
50### Setup
51
52Include the required header files, and have some member variables that will be used for authentication and sending requests:
53
54    #include "o1twitter.h"
55    #include "o1requestor.h"
56    O1Twitter *o1;
57
58### Initialization
59
60Instantiate one of the authenticator classes, like O1Twitter, set your application ID and application secret, and install the signal handlers:
61
62    o1 = new O1Twitter(this);
63    o1->setClientId(MY_CLIENT_ID);
64    o1->setClientSecret(MY_CLIENT_SECRET);
65    connect(o1, SIGNAL(linkedChanged()), this, SLOT(onLinkedChanged()));
66    connect(o1, SIGNAL(linkingFailed()), this, SLOT(onLinkingFailed()));
67    connect(o1, SIGNAL(linkingSucceeded()), this, SLOT(onLinkingSucceeded()));
68    connect(o1, SIGNAL(openBrowser(QUrl)), this, SLOT(onOpenBrowser(QUrl)));
69    connect(o1, SIGNAL(closeBrowser()), this, SLOT(onCloseBrowser()));
70
71**Note:** For browserless Twitter authentication, you can use the OXTwitter specialized class which can do Twitter XAuth. You will need to additionally provide your Twitter login credentials (username & password) before calling *link()*.
72
73### Handling Signals
74
75O2 is an asynchronous library. It will send signals at various stages of authentication and request processing.
76
77To handle these signals, implement the following slots in your code:
78
79    void onLinkedChanged() {
80        // Linking (login) state has changed.
81        // Use o1->linked() to get the actual state
82    }
83
84    void onLinkingFailed() {
85        // Login has failed
86    }
87
88    void onLinkingSucceeded() {
89        // Login has succeeded
90    }
91
92    void onOpenBrowser(const QUrl *url) {
93        // Open a web browser or a web view with the given URL.
94        // The user will interact with this browser window to
95        // enter login name, password, and authorize your application
96        // to access the Twitter account
97    }
98
99    void onCloseBrowser() {
100        // Close the browser window opened in openBrowser()
101    }
102
103### Logging In
104
105To log in (e.g. to link your application to the OAuth service), call the link() method:
106
107    o1->link();
108
109This initiates the authentication sequence. Your signal handlers above will be called at various stages. Lastly, if linking succeeds, onLinkingSucceeded() will be called.
110
111### Logging Out
112
113To log out, call the unlink() method:
114
115    o1->unlink();
116
117Logging out always succeeds, and requires no user interaction.
118
119### Sending Authenticated Requests
120
121Once linked, you can start sending authenticated requests to the service. We start with a simple example of sending a text-only tweet or as it's known in Twitter docs, a 'status update'.
122
123First we need a Qt network manager and an O1 requestor object:
124
125    QNetworkAccessManager *manager = new QNetworkAccessManager(this);
126    O1Requestor *requestor = new O1Requestor(manager, o1, this);
127
128Next, create parameters for posting the update:
129
130    QByteArray paramName("status");
131    QByteArray tweetText("My first tweet!");
132
133    QList<O1RequestParameter> requestParams = QList<O1RequestParameter>();
134    requestParams << O1RequestParameter(paramName, tweetText);
135
136    QByteArray postData = O1::createQueryParams(requestParams);
137
138    // Using Twitter's REST API ver 1.1
139    QUrl url = QUrl("https://api.twitter.com/1.1/statuses/update.json");
140
141    QNetworkRequest request(url);
142    request.setHeader(QNetworkRequest::ContentTypeHeader, O2_MIME_TYPE_XFORM);
143
144Finally we authenticate and send the request using the O1 requestor object:
145
146    QNetworkReply *reply = requestor->post(request, reqestParams, postData);
147
148Continuing with the example, we will now send a tweet containing an image as well as a message.
149
150We create an HTTP request containing the image and the message, in the format specified by Twitter:
151
152    QString imagePath("/tmp/image.jpg");
153    QString message("My tweet with an image!");
154
155    QFileInfo fileInfo(imagePath);
156    QFile file(imagePath);
157    file.open(QIODevice::ReadOnly);
158
159    QString boundary("7d44e178b0439");
160    QByteArray data(QString("--" + boundary + "\r\n").toAscii());
161    data += "Content-Disposition: form-data; name=\"media[]\"; filename=\"" + fileInfo.fileName() + "\"\r\n";
162    data += "Content-Transfer-Encoding: binary\r\n";
163    data += "Content-Type: application/octet-stream\r\n\r\n";
164    data += file.readAll();
165    file.close();
166    data += QString("\r\n--") + boundary + "\r\n";
167    data += "Content-Disposition: form-data; name=\"status\"\r\n";
168    data += "Content-Transfer-Encoding: binary\r\n";
169    data += "Content-Type: text/plain; charset=utf-8\r\n\r\n";
170    data += message.toUtf8();
171    data += QString("\r\n--") + boundary + "--\r\n";
172
173    QNetworkRequest request;
174    // Using Twitter's REST API ver 1.1
175    request.setUrl(QUrl("https://api.twitter.com/1.1/statuses/update_with_media.json"));
176    request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data; boundary=" + boundary);
177    request.setHeader(QNetworkRequest::ContentLengthHeader, data.length());
178
179    QNetworkReply *reply = requestor->post(request, QList<O1RequestParameter>(), data);
180
181That's it. Tweets using the O2 library!
182
183### Storing OAuth Tokens
184
185O2 provides simple storage classes for writing OAuth tokens in a peristent location. Currently, a QSettings based backing store **O2SettingsStore** is provided in O2. O2SettingsStore keeps all token values in an encrypted form. You have to specify the encryption key to use while constructing the object:
186
187    O0SettingsStore settings = new O0SettingsStore("myencryptionkey");
188    // Set the store before starting OAuth, i.e before calling link()
189    o1->setStore(settings);
190    ...
191
192You can also create it with your customized QSettings object. O2SettingsStore will then use that QSettings object for storing the tokens:
193
194    O0SettingsStore settings = new O0SettingsStore(mySettingsObject, "myencryptionkey");
195
196Once set, O2SettingsStore takes ownership of the QSettings object.
197
198**Note:** If you do not specify a storage object to use, O2 will create one by default (which QSettings based), and use it. In such a case, a default encryption key is used for encrypting the data. *This is not a secure solution: prefer storing the tokens in a Keychain or Wallet based facility instead*.
199
200**Note:** If using O2SettingsStore, make sure organization name, domain and application name are set:
201
202```
203QCoreApplication::setOrganizationName("MySoft");
204QCoreApplication::setOrganizationDomain("mysoft.com");
205QCoreApplication::setApplicationName("Star Runner");
206```
207
208### Extra OAuth Tokens
209
210Some OAuth service providers provide additional information in the access token response. Eg: Twitter returns 2 additional tokens in it's access token response - *screen_name* and *user_id*.
211
212O2 provides all such tokens via the property - *extraTokens*. You can query this property after a successful OAuth exchange, i.e after the *linkingSucceeded()* signal has been emitted.
213
214## More Examples
215
216The *examples* folder contains complete example applications:
217
218Name | Description
219:-- | :--
220facebookdemo | Command line application authenticating with Facebook
221sialis | QT Quick Twitter client using OAuth 1
222twitterdemo | Command line client for authenticating with Twitter and posting status updates. Uses OAuth 1 or Twitter XAuth
223
224## Change Log
225
226### 0.1.0
227
228* Persist the extra tokens, too
229* Add Qt Quick Twitter client example
230
231
232
233
234