Merge lp:~mardy/signon-plugin-oauth2/packaging into lp:signon-plugin-oauth2
- packaging
- Merge into trunk
Proposed by
Alberto Mardegan
Status: | Merged |
---|---|
Approved by: | David Barth |
Approved revision: | 66 |
Merged at revision: | 64 |
Proposed branch: | lp:~mardy/signon-plugin-oauth2/packaging |
Merge into: | lp:signon-plugin-oauth2 |
Diff against target: |
783 lines (+562/-44) 8 files modified
common-vars.pri (+1/-1) debian/changelog (+8/-0) debian/control (+2/-1) src/oauth2data.h (+7/-0) src/oauth2plugin.cpp (+22/-16) src/oauth2plugin.h (+1/-1) tests/oauth2plugintest.cpp (+515/-25) tests/oauth2plugintest.h (+6/-0) |
To merge this branch: | bzr merge lp:~mardy/signon-plugin-oauth2/packaging |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
David Barth (community) | Approve | ||
Review via email: mp+234282@code.launchpad.net |
Commit message
New upstream release
- OAuth 2.0: follow the spec more closely, add Vimeo support
- Tests: increase test coverage
Description of the change
New upstream release
- OAuth 2.0: follow the spec more closely, add Vimeo support
- Tests: increase test coverage
To post a comment you must log in.
Revision history for this message
David Barth (dbarth) : | # |
review:
Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : | # |
review:
Needs Fixing
(continuous-integration)
- 66. By Alberto Mardegan
-
Require the very latest signond
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:66
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
review:
Needs Fixing
(continuous-integration)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'common-vars.pri' |
2 | --- common-vars.pri 2013-11-13 09:47:25 +0000 |
3 | +++ common-vars.pri 2014-09-12 09:09:50 +0000 |
4 | @@ -13,7 +13,7 @@ |
5 | # Project version |
6 | # remember to update debian/* files if you changes this |
7 | #----------------------------------------------------------------------------- |
8 | -PROJECT_VERSION = 0.19 |
9 | +PROJECT_VERSION = 0.20 |
10 | |
11 | #----------------------------------------------------------------------------- |
12 | # Library version |
13 | |
14 | === modified file 'debian/changelog' |
15 | --- debian/changelog 2014-05-13 07:07:20 +0000 |
16 | +++ debian/changelog 2014-09-12 09:09:50 +0000 |
17 | @@ -1,3 +1,11 @@ |
18 | +signon-plugin-oauth2 (0.20-0ubuntu1) UNRELEASED; urgency=medium |
19 | + |
20 | + * New upstream release |
21 | + - OAuth 2.0: follow the spec more closely, add Vimeo support |
22 | + - Tests: increase test coverage |
23 | + |
24 | + -- Alberto Mardegan <alberto.mardegan@canonical.com> Thu, 11 Sep 2014 12:55:35 +0300 |
25 | + |
26 | signon-plugin-oauth2 (0.19+14.10.20140513-0ubuntu1) utopic; urgency=low |
27 | |
28 | [ Ubuntu daily release ] |
29 | |
30 | === modified file 'debian/control' |
31 | --- debian/control 2014-05-09 19:27:46 +0000 |
32 | +++ debian/control 2014-09-12 09:09:50 +0000 |
33 | @@ -9,7 +9,7 @@ |
34 | libsignon-qt5-dev, |
35 | pkg-config, |
36 | qt5-default, |
37 | - signon-plugins-dev (>= 8.50-0ubuntu1), |
38 | + signon-plugins-dev (>> 8.57+14.10.20140827-0ubuntu1), |
39 | xvfb, |
40 | Standards-Version: 3.9.4 |
41 | Homepage: http://code.google.com/p/accounts-sso/ |
42 | @@ -23,6 +23,7 @@ |
43 | Depends: ${shlibs:Depends}, |
44 | ${misc:Depends}, |
45 | signon-ui, |
46 | +Breaks: account-plugin-google (<< 0.12) |
47 | Description: Single Signon oauth2 plugin |
48 | Oauth2 plugin for the Single Signon framework |
49 | |
50 | |
51 | === modified file 'src/oauth2data.h' |
52 | --- src/oauth2data.h 2012-07-17 13:09:22 +0000 |
53 | +++ src/oauth2data.h 2014-09-12 09:09:50 +0000 |
54 | @@ -57,6 +57,13 @@ |
55 | SIGNON_SESSION_DECLARE_PROPERTY(QString, ClientSecret); |
56 | |
57 | /*! |
58 | + * Set this to true if the server does not conform to the OAuth 2.0 |
59 | + * specification in that it does not support supplying client ID and |
60 | + * secret via basic HTTP authorization. |
61 | + */ |
62 | + SIGNON_SESSION_DECLARE_PROPERTY(bool, ForceClientAuthViaRequestBody); |
63 | + |
64 | + /*! |
65 | * redirection URI |
66 | */ |
67 | SIGNON_SESSION_DECLARE_PROPERTY(QString, RedirectUri); |
68 | |
69 | === modified file 'src/oauth2plugin.cpp' |
70 | --- src/oauth2plugin.cpp 2014-05-05 09:42:08 +0000 |
71 | +++ src/oauth2plugin.cpp 2014-09-12 09:09:50 +0000 |
72 | @@ -388,33 +388,27 @@ |
73 | if (url.hasQueryItem(AUTH_CODE)) { |
74 | QString code = url.queryItemValue(AUTH_CODE); |
75 | newUrl.addQueryItem(GRANT_TYPE, AUTHORIZATION_CODE); |
76 | - newUrl.addQueryItem(CLIENT_ID, d->m_oauth2Data.ClientId()); |
77 | - newUrl.addQueryItem(CLIENT_SECRET, d->m_oauth2Data.ClientSecret()); |
78 | newUrl.addQueryItem(AUTH_CODE, code); |
79 | newUrl.addQueryItem(REDIRECT_URI, d->m_oauth2Data.RedirectUri()); |
80 | - sendOAuth2PostRequest(newUrl.encodedQuery(), |
81 | + sendOAuth2PostRequest(newUrl, |
82 | GrantType::AuthorizationCode); |
83 | } |
84 | else if (url.hasQueryItem(USERNAME) && url.hasQueryItem(PASSWORD)) { |
85 | QString username = url.queryItemValue(USERNAME); |
86 | QString password = url.queryItemValue(PASSWORD); |
87 | newUrl.addQueryItem(GRANT_TYPE, USER_BASIC); |
88 | - newUrl.addQueryItem(CLIENT_ID, d->m_oauth2Data.ClientId()); |
89 | - newUrl.addQueryItem(CLIENT_SECRET, d->m_oauth2Data.ClientSecret()); |
90 | newUrl.addQueryItem(USERNAME, username); |
91 | newUrl.addQueryItem(PASSWORD, password); |
92 | - sendOAuth2PostRequest(newUrl.encodedQuery(), |
93 | + sendOAuth2PostRequest(newUrl, |
94 | GrantType::UserBasic); |
95 | } |
96 | else if (url.hasQueryItem(ASSERTION_TYPE) && url.hasQueryItem(ASSERTION)) { |
97 | QString assertion_type = url.queryItemValue(ASSERTION_TYPE); |
98 | QString assertion = url.queryItemValue(ASSERTION); |
99 | newUrl.addQueryItem(GRANT_TYPE, ASSERTION); |
100 | - newUrl.addQueryItem(CLIENT_ID, d->m_oauth2Data.ClientId()); |
101 | - newUrl.addQueryItem(CLIENT_SECRET, d->m_oauth2Data.ClientSecret()); |
102 | newUrl.addQueryItem(ASSERTION_TYPE, assertion_type); |
103 | newUrl.addQueryItem(ASSERTION, assertion); |
104 | - sendOAuth2PostRequest(newUrl.encodedQuery(), |
105 | + sendOAuth2PostRequest(newUrl, |
106 | GrantType::Assertion); |
107 | } |
108 | else if (url.hasQueryItem(REFRESH_TOKEN)) { |
109 | @@ -569,15 +563,11 @@ |
110 | TRACE() << refreshToken; |
111 | QUrl url; |
112 | url.addQueryItem(GRANT_TYPE, REFRESH_TOKEN); |
113 | - url.addQueryItem(CLIENT_ID, d->m_oauth2Data.ClientId()); |
114 | - if (!d->m_oauth2Data.ClientSecret().isEmpty()) { |
115 | - url.addQueryItem(CLIENT_SECRET, d->m_oauth2Data.ClientSecret()); |
116 | - } |
117 | url.addQueryItem(REFRESH_TOKEN, refreshToken); |
118 | - sendOAuth2PostRequest(url.encodedQuery(), GrantType::RefreshToken); |
119 | + sendOAuth2PostRequest(url, GrantType::RefreshToken); |
120 | } |
121 | |
122 | -void OAuth2Plugin::sendOAuth2PostRequest(const QByteArray &postData, |
123 | +void OAuth2Plugin::sendOAuth2PostRequest(QUrl &postData, |
124 | GrantType::e grantType) |
125 | { |
126 | Q_D(OAuth2Plugin); |
127 | @@ -589,10 +579,26 @@ |
128 | QNetworkRequest request(url); |
129 | request.setRawHeader(CONTENT_TYPE, CONTENT_APP_URLENCODED); |
130 | |
131 | + if (!d->m_oauth2Data.ClientSecret().isEmpty()) { |
132 | + if (d->m_oauth2Data.ForceClientAuthViaRequestBody()) { |
133 | + postData.addQueryItem(CLIENT_ID, d->m_oauth2Data.ClientId()); |
134 | + postData.addQueryItem(CLIENT_SECRET, d->m_oauth2Data.ClientSecret()); |
135 | + } else { |
136 | + QByteArray authorization = |
137 | + QUrl::toPercentEncoding(d->m_oauth2Data.ClientId()) + ":" + |
138 | + QUrl::toPercentEncoding(d->m_oauth2Data.ClientSecret()); |
139 | + QByteArray basicAuthorization = |
140 | + QByteArray("Basic ") + authorization.toBase64(); |
141 | + request.setRawHeader("Authorization", basicAuthorization); |
142 | + } |
143 | + } else { |
144 | + postData.addQueryItem(CLIENT_ID, d->m_oauth2Data.ClientId()); |
145 | + } |
146 | + |
147 | d->m_grantType = grantType; |
148 | |
149 | TRACE() << "Query string = " << postData; |
150 | - postRequest(request, postData); |
151 | + postRequest(request, postData.encodedQuery()); |
152 | } |
153 | |
154 | void OAuth2Plugin::storeResponse(const OAuth2PluginTokenData &response) |
155 | |
156 | === modified file 'src/oauth2plugin.h' |
157 | --- src/oauth2plugin.h 2013-01-22 14:30:08 +0000 |
158 | +++ src/oauth2plugin.h 2014-09-12 09:09:50 +0000 |
159 | @@ -72,7 +72,7 @@ |
160 | bool respondWithStoredToken(const QVariantMap &token, |
161 | const QStringList &scopes); |
162 | void refreshOAuth2Token(const QString &refreshToken); |
163 | - void sendOAuth2PostRequest(const QByteArray &postData, |
164 | + void sendOAuth2PostRequest(QUrl &postData, |
165 | GrantType::e grantType); |
166 | void storeResponse(const OAuth2PluginTokenData &response); |
167 | const QVariantMap parseJSONReply(const QByteArray &reply); |
168 | |
169 | === modified file 'tests/oauth2plugintest.cpp' |
170 | --- tests/oauth2plugintest.cpp 2014-05-05 09:42:08 +0000 |
171 | +++ tests/oauth2plugintest.cpp 2014-09-12 09:09:50 +0000 |
172 | @@ -21,6 +21,10 @@ |
173 | * 02110-1301 USA |
174 | */ |
175 | |
176 | +#include <QNetworkAccessManager> |
177 | +#include <QNetworkReply> |
178 | +#include <QPointer> |
179 | +#include <QTimer> |
180 | #include <QtTest/QtTest> |
181 | |
182 | #include "plugin.h" |
183 | @@ -36,6 +40,91 @@ |
184 | #define TEST_START qDebug("\n\n\n\n ----------------- %s ----------------\n\n", __func__); |
185 | #define TEST_DONE qDebug("\n\n ----------------- %s DONE ----------------\n\n", __func__); |
186 | |
187 | +class TestNetworkReply: public QNetworkReply |
188 | +{ |
189 | + Q_OBJECT |
190 | + |
191 | +public: |
192 | + TestNetworkReply(QObject *parent = 0): |
193 | + QNetworkReply(parent), |
194 | + m_offset(0) |
195 | + {} |
196 | + |
197 | + void setError(NetworkError errorCode, const QString &errorString) { |
198 | + QNetworkReply::setError(errorCode, errorString); |
199 | + } |
200 | + |
201 | + void setRawHeader(const QByteArray &headerName, const QByteArray &value) { |
202 | + QNetworkReply::setRawHeader(headerName, value); |
203 | + } |
204 | + |
205 | + void setContentType(const QString &contentType) { |
206 | + setRawHeader("Content-Type", contentType.toUtf8()); |
207 | + } |
208 | + |
209 | + void setStatusCode(int statusCode) { |
210 | + setAttribute(QNetworkRequest::HttpStatusCodeAttribute, statusCode); |
211 | + } |
212 | + |
213 | + void setContent(const QByteArray &content) { |
214 | + m_content = content; |
215 | + m_offset = 0; |
216 | + |
217 | + open(ReadOnly | Unbuffered); |
218 | + setHeader(QNetworkRequest::ContentLengthHeader, QVariant(content.size())); |
219 | + |
220 | + QTimer::singleShot(0, this, SIGNAL(readyRead())); |
221 | + QTimer::singleShot(10, this, SLOT(finish())); |
222 | + } |
223 | + |
224 | +public Q_SLOTS: |
225 | + void finish() { setFinished(true); Q_EMIT finished(); } |
226 | + |
227 | +protected: |
228 | + void abort() Q_DECL_OVERRIDE {} |
229 | + qint64 bytesAvailable() const Q_DECL_OVERRIDE { |
230 | + return m_content.size() - m_offset + QIODevice::bytesAvailable(); |
231 | + } |
232 | + |
233 | + bool isSequential() const Q_DECL_OVERRIDE { return true; } |
234 | + qint64 readData(char *data, qint64 maxSize) Q_DECL_OVERRIDE { |
235 | + if (m_offset >= m_content.size()) |
236 | + return -1; |
237 | + qint64 number = qMin(maxSize, m_content.size() - m_offset); |
238 | + memcpy(data, m_content.constData() + m_offset, number); |
239 | + m_offset += number; |
240 | + return number; |
241 | + } |
242 | + |
243 | +private: |
244 | + QByteArray m_content; |
245 | + qint64 m_offset; |
246 | +}; |
247 | + |
248 | +class TestNetworkAccessManager: public QNetworkAccessManager |
249 | +{ |
250 | + Q_OBJECT |
251 | + |
252 | +public: |
253 | + TestNetworkAccessManager(): QNetworkAccessManager() {} |
254 | + |
255 | + void setNextReply(TestNetworkReply *reply) { m_nextReply = reply; } |
256 | + |
257 | +protected: |
258 | + QNetworkReply *createRequest(Operation op, const QNetworkRequest &request, |
259 | + QIODevice *outgoingData = 0) Q_DECL_OVERRIDE { |
260 | + Q_UNUSED(op); |
261 | + m_lastRequest = request; |
262 | + m_lastRequestData = outgoingData->readAll(); |
263 | + return m_nextReply; |
264 | + } |
265 | + |
266 | +public: |
267 | + QPointer<TestNetworkReply> m_nextReply; |
268 | + QNetworkRequest m_lastRequest; |
269 | + QByteArray m_lastRequestData; |
270 | +}; |
271 | + |
272 | void OAuth2PluginTest::initTestCase() |
273 | { |
274 | TEST_START |
275 | @@ -56,6 +145,8 @@ |
276 | void OAuth2PluginTest::init() |
277 | { |
278 | m_testPlugin = new Plugin(); |
279 | + m_response = SignOn::SessionData(); |
280 | + m_error = SignOn::Error(-1); |
281 | } |
282 | |
283 | //finnish each test by deleting plugin |
284 | @@ -506,18 +597,169 @@ |
285 | TEST_DONE |
286 | } |
287 | |
288 | +void OAuth2PluginTest::testPluginWebserverUserActionFinished_data() |
289 | +{ |
290 | + QTest::addColumn<QString>("urlResponse"); |
291 | + QTest::addColumn<int>("errorCode"); |
292 | + QTest::addColumn<QString>("postUrl"); |
293 | + QTest::addColumn<QString>("postContents"); |
294 | + QTest::addColumn<int>("replyStatusCode"); |
295 | + QTest::addColumn<QString>("replyContentType"); |
296 | + QTest::addColumn<QString>("replyContents"); |
297 | + QTest::addColumn<QVariantMap>("response"); |
298 | + |
299 | + QVariantMap response; |
300 | + |
301 | + QTest::newRow("empty data") << |
302 | + "" << |
303 | + int(Error::NotAuthorized) << |
304 | + "" << "" << 0 << "" << "" << QVariantMap(); |
305 | + |
306 | + QTest::newRow("no query data") << |
307 | + "http://localhost/resp.html" << |
308 | + int(Error::NotAuthorized) << |
309 | + "" << "" << 0 << "" << "" << QVariantMap(); |
310 | + |
311 | + QTest::newRow("permission denied") << |
312 | + "http://localhost/resp.html?error=user_denied" << |
313 | + int(Error::NotAuthorized) << |
314 | + "" << "" << 0 << "" << "" << QVariantMap(); |
315 | + |
316 | + QTest::newRow("invalid data") << |
317 | + "http://localhost/resp.html?sdsdsds=access.grant." << |
318 | + int(Error::NotAuthorized) << |
319 | + "" << "" << 0 << "" << "" << QVariantMap(); |
320 | + |
321 | + QTest::newRow("reply code, http error 401") << |
322 | + "http://localhost/resp.html?code=c0d3" << |
323 | + int(Error::OperationFailed) << |
324 | + "https://localhost/access_token" << |
325 | + "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
326 | + int(401) << |
327 | + "application/json" << |
328 | + "something else" << |
329 | + QVariantMap(); |
330 | + |
331 | + QTest::newRow("reply code, empty reply") << |
332 | + "http://localhost/resp.html?code=c0d3" << |
333 | + int(Error::NotAuthorized) << |
334 | + "https://localhost/access_token" << |
335 | + "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
336 | + int(200) << |
337 | + "application/json" << |
338 | + "something else" << |
339 | + QVariantMap(); |
340 | + |
341 | + QTest::newRow("reply code, no content type") << |
342 | + "http://localhost/resp.html?code=c0d3" << |
343 | + int(Error::OperationFailed) << |
344 | + "https://localhost/access_token" << |
345 | + "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
346 | + int(200) << |
347 | + "" << |
348 | + "something else" << |
349 | + QVariantMap(); |
350 | + |
351 | + QTest::newRow("reply code, unsupported content type") << |
352 | + "http://localhost/resp.html?code=c0d3" << |
353 | + int(Error::OperationFailed) << |
354 | + "https://localhost/access_token" << |
355 | + "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
356 | + int(200) << |
357 | + "image/jpeg" << |
358 | + "something else" << |
359 | + QVariantMap(); |
360 | + |
361 | + response.clear(); |
362 | + response.insert("AccessToken", "t0k3n"); |
363 | + response.insert("ExpiresIn", int(3600)); |
364 | + response.insert("RefreshToken", QString()); |
365 | + QTest::newRow("reply code, valid token") << |
366 | + "http://localhost/resp.html?code=c0d3" << |
367 | + int(-1) << |
368 | + "https://localhost/access_token" << |
369 | + "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
370 | + int(200) << |
371 | + "application/json" << |
372 | + "{ \"access_token\":\"t0k3n\", \"expires_in\": 3600 }" << |
373 | + response; |
374 | + |
375 | + response.clear(); |
376 | + QTest::newRow("reply code, facebook, no token") << |
377 | + "http://localhost/resp.html?code=c0d3" << |
378 | + int(Error::NotAuthorized) << |
379 | + "https://localhost/access_token" << |
380 | + "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
381 | + int(200) << |
382 | + "text/plain" << |
383 | + "expires=3600" << |
384 | + response; |
385 | + |
386 | + response.clear(); |
387 | + response.insert("AccessToken", "t0k3n"); |
388 | + response.insert("ExpiresIn", int(3600)); |
389 | + response.insert("RefreshToken", QString()); |
390 | + QTest::newRow("reply code, facebook, valid token") << |
391 | + "http://localhost/resp.html?code=c0d3" << |
392 | + int(-1) << |
393 | + "https://localhost/access_token" << |
394 | + "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
395 | + int(200) << |
396 | + "text/plain" << |
397 | + "access_token=t0k3n&expires=3600" << |
398 | + response; |
399 | + |
400 | + response.clear(); |
401 | + response.insert("AccessToken", "t0k3n"); |
402 | + response.insert("ExpiresIn", int(3600)); |
403 | + response.insert("RefreshToken", QString()); |
404 | + QTest::newRow("username-password, valid token") << |
405 | + "http://localhost/resp.html?username=us3r&password=s3cr3t" << |
406 | + int(-1) << |
407 | + "https://localhost/access_token" << |
408 | + "grant_type=user_basic&username=us3r&password=s3cr3t" << |
409 | + int(200) << |
410 | + "application/json" << |
411 | + "{ \"access_token\":\"t0k3n\", \"expires_in\": 3600 }" << |
412 | + response; |
413 | + |
414 | + response.clear(); |
415 | + response.insert("AccessToken", "t0k3n"); |
416 | + response.insert("ExpiresIn", int(3600)); |
417 | + response.insert("RefreshToken", QString()); |
418 | + QTest::newRow("assertion, valid token") << |
419 | + "http://localhost/resp.html?assertion_type=http://oauth.net/token/1.0" |
420 | + "&assertion=oauth1t0k3n" << |
421 | + int(-1) << |
422 | + "https://localhost/access_token" << |
423 | + "grant_type=assertion&assertion_type=http://oauth.net/token/1.0&assertion=oauth1t0k3n" << |
424 | + int(200) << |
425 | + "application/json" << |
426 | + "{ \"access_token\":\"t0k3n\", \"expires_in\": 3600 }" << |
427 | + response; |
428 | +} |
429 | + |
430 | void OAuth2PluginTest::testPluginWebserverUserActionFinished() |
431 | { |
432 | TEST_START |
433 | |
434 | + QFETCH(QString, urlResponse); |
435 | + QFETCH(int, errorCode); |
436 | + QFETCH(QString, postUrl); |
437 | + QFETCH(QString, postContents); |
438 | + QFETCH(int, replyStatusCode); |
439 | + QFETCH(QString, replyContentType); |
440 | + QFETCH(QString, replyContents); |
441 | + QFETCH(QVariantMap, response); |
442 | + |
443 | SignOn::UiSessionData info; |
444 | OAuth2PluginData data; |
445 | - data.setHost("https://localhost"); |
446 | + data.setHost("localhost"); |
447 | data.setAuthPath("authorize"); |
448 | data.setTokenPath("access_token"); |
449 | data.setClientId("104660106251471"); |
450 | data.setClientSecret("fa28f40b5a1f8c1d5628963d880636fbkjkjkj"); |
451 | - data.setRedirectUri("http://localhost/connect/login_success.html"); |
452 | + data.setRedirectUri("http://localhost/resp.html"); |
453 | |
454 | QObject::connect(m_testPlugin, SIGNAL(result(const SignOn::SessionData&)), |
455 | this, SLOT(result(const SignOn::SessionData&)),Qt::QueuedConnection); |
456 | @@ -527,33 +769,281 @@ |
457 | this, SLOT(uiRequest(const SignOn::UiSessionData&)),Qt::QueuedConnection); |
458 | QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); |
459 | |
460 | + TestNetworkAccessManager *nam = new TestNetworkAccessManager; |
461 | + m_testPlugin->m_networkAccessManager = nam; |
462 | + TestNetworkReply *reply = new TestNetworkReply(this); |
463 | + reply->setStatusCode(replyStatusCode); |
464 | + if (!replyContentType.isEmpty()) { |
465 | + reply->setContentType(replyContentType); |
466 | + } |
467 | + reply->setContent(replyContents.toUtf8()); |
468 | + nam->setNextReply(reply); |
469 | + |
470 | m_testPlugin->process(data, QString("web_server")); |
471 | m_loop.exec(); |
472 | qDebug() << "Data = " << m_uiResponse.UrlResponse(); |
473 | QCOMPARE(m_uiResponse.UrlResponse(), QString("UI request received")); |
474 | |
475 | - //empty data |
476 | - m_testPlugin->userActionFinished(info); |
477 | - m_loop.exec(); |
478 | - QCOMPARE(m_error.type(), int(Error::NotAuthorized)); |
479 | - |
480 | - //invalid data |
481 | - info.setUrlResponse(QString("http://www.facebook.com/connect/login_success.html")); |
482 | - m_testPlugin->userActionFinished(info); |
483 | - m_loop.exec(); |
484 | - QCOMPARE(m_error.type(), int(Error::NotAuthorized)); |
485 | - |
486 | - //Permission denied |
487 | - info.setUrlResponse(QString("http://www.facebook.com/connect/login_success.html?error=user_denied")); |
488 | - m_testPlugin->userActionFinished(info); |
489 | - m_loop.exec(); |
490 | - QCOMPARE(m_error.type(), int(Error::NotAuthorized)); |
491 | - |
492 | - //invalid data |
493 | - info.setUrlResponse(QString("http://www.facebook.com/connect/login_success.html?sdsdsds=access.grant.")); |
494 | - m_testPlugin->userActionFinished(info); |
495 | - m_loop.exec(); |
496 | - QCOMPARE(m_error.type(), int(Error::NotAuthorized)); |
497 | + if (!urlResponse.isEmpty()) { |
498 | + info.setUrlResponse(urlResponse); |
499 | + } |
500 | + |
501 | + m_testPlugin->userActionFinished(info); |
502 | + m_loop.exec(); |
503 | + |
504 | + QCOMPARE(m_error.type(), errorCode); |
505 | + QCOMPARE(nam->m_lastRequest.url(), QUrl(postUrl)); |
506 | + QCOMPARE(QString::fromUtf8(nam->m_lastRequestData), postContents); |
507 | + qDebug() << "got response" << m_response.toMap(); |
508 | + qDebug() << "expected" << response; |
509 | + QCOMPARE(m_response.toMap(), response); |
510 | + |
511 | + delete nam; |
512 | + |
513 | + TEST_DONE |
514 | +} |
515 | + |
516 | +void OAuth2PluginTest::testOAuth2Errors_data() |
517 | +{ |
518 | + QTest::addColumn<QString>("replyContents"); |
519 | + QTest::addColumn<int>("expectedErrorCode"); |
520 | + |
521 | + QTest::newRow("incorrect_client_credentials") << |
522 | + "{ \"error\": \"incorrect_client_credentials\" }" << |
523 | + int(Error::InvalidCredentials); |
524 | + |
525 | + QTest::newRow("redirect_uri_mismatch") << |
526 | + "{ \"error\": \"redirect_uri_mismatch\" }" << |
527 | + int(Error::InvalidCredentials); |
528 | + |
529 | + QTest::newRow("bad_authorization_code") << |
530 | + "{ \"error\": \"bad_authorization_code\" }" << |
531 | + int(Error::InvalidCredentials); |
532 | + |
533 | + QTest::newRow("invalid_client_credentials") << |
534 | + "{ \"error\": \"invalid_client_credentials\" }" << |
535 | + int(Error::InvalidCredentials); |
536 | + |
537 | + QTest::newRow("unauthorized_client") << |
538 | + "{ \"error\": \"unauthorized_client\" }" << |
539 | + int(Error::NotAuthorized); |
540 | + |
541 | + QTest::newRow("invalid_assertion") << |
542 | + "{ \"error\": \"invalid_assertion\" }" << |
543 | + int(Error::InvalidCredentials); |
544 | + |
545 | + QTest::newRow("unknown_format") << |
546 | + "{ \"error\": \"unknown_format\" }" << |
547 | + int(Error::InvalidQuery); |
548 | + |
549 | + QTest::newRow("authorization_expired") << |
550 | + "{ \"error\": \"authorization_expired\" }" << |
551 | + int(Error::InvalidCredentials); |
552 | + |
553 | + QTest::newRow("multiple_credentials") << |
554 | + "{ \"error\": \"multiple_credentials\" }" << |
555 | + int(Error::InvalidQuery); |
556 | + |
557 | + QTest::newRow("invalid_user_credentials") << |
558 | + "{ \"error\": \"invalid_user_credentials\" }" << |
559 | + int(Error::InvalidCredentials); |
560 | +} |
561 | + |
562 | +void OAuth2PluginTest::testOAuth2Errors() |
563 | +{ |
564 | + TEST_START |
565 | + |
566 | + QFETCH(QString, replyContents); |
567 | + QFETCH(int, expectedErrorCode); |
568 | + |
569 | + SignOn::UiSessionData info; |
570 | + OAuth2PluginData data; |
571 | + data.setHost("localhost"); |
572 | + data.setAuthPath("authorize"); |
573 | + data.setTokenPath("access_token"); |
574 | + data.setClientId("104660106251471"); |
575 | + data.setClientSecret("fa28f40b5a1f8c1d5628963d880636fbkjkjkj"); |
576 | + data.setRedirectUri("http://localhost/resp.html"); |
577 | + |
578 | + QObject::connect(m_testPlugin, SIGNAL(result(const SignOn::SessionData&)), |
579 | + this, SLOT(result(const SignOn::SessionData&)), |
580 | + Qt::QueuedConnection); |
581 | + QObject::connect(m_testPlugin, SIGNAL(error(const SignOn::Error & )), |
582 | + this, SLOT(pluginError(const SignOn::Error &)), |
583 | + Qt::QueuedConnection); |
584 | + QObject::connect(m_testPlugin, SIGNAL(userActionRequired(const SignOn::UiSessionData&)), |
585 | + this, SLOT(uiRequest(const SignOn::UiSessionData&)), |
586 | + Qt::QueuedConnection); |
587 | + QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); |
588 | + |
589 | + TestNetworkAccessManager *nam = new TestNetworkAccessManager; |
590 | + m_testPlugin->m_networkAccessManager = nam; |
591 | + TestNetworkReply *reply = new TestNetworkReply(this); |
592 | + reply->setStatusCode(401); |
593 | + reply->setContentType("application/json"); |
594 | + reply->setContent(replyContents.toUtf8()); |
595 | + nam->setNextReply(reply); |
596 | + |
597 | + m_testPlugin->process(data, QString("web_server")); |
598 | + m_loop.exec(); |
599 | + |
600 | + info.setUrlResponse("http://localhost/resp.html?code=c0d3"); |
601 | + m_testPlugin->userActionFinished(info); |
602 | + m_loop.exec(); |
603 | + |
604 | + QCOMPARE(m_error.type(), expectedErrorCode); |
605 | + |
606 | + delete nam; |
607 | + |
608 | + TEST_DONE |
609 | +} |
610 | + |
611 | +void OAuth2PluginTest::testRefreshToken() |
612 | +{ |
613 | + TEST_START |
614 | + |
615 | + SignOn::UiSessionData info; |
616 | + OAuth2PluginData data; |
617 | + data.setHost("localhost"); |
618 | + data.setAuthPath("authorize"); |
619 | + data.setTokenPath("access_token"); |
620 | + data.setClientId("104660106251471"); |
621 | + data.setClientSecret("fa28f40b5a1f8c1d5628963d880636fbkjkjkj"); |
622 | + data.setRedirectUri("http://localhost/resp.html"); |
623 | + |
624 | + /* Pretend that we have stored an expired access token, but have a refresh |
625 | + * token */ |
626 | + QVariantMap tokens; |
627 | + QVariantMap token; |
628 | + token.insert("Token", QLatin1String("tokenfromtest")); |
629 | + token.insert("timestamp", QDateTime::currentDateTime().toTime_t() - 10000); |
630 | + token.insert("Expiry", 1000); |
631 | + token.insert("refresh_token", QString("r3fr3sh")); |
632 | + tokens.insert(data.ClientId(), QVariant::fromValue(token)); |
633 | + data.m_data.insert("Tokens", tokens); |
634 | + |
635 | + QObject::connect(m_testPlugin, SIGNAL(result(const SignOn::SessionData&)), |
636 | + this, SLOT(result(const SignOn::SessionData&)), |
637 | + Qt::QueuedConnection); |
638 | + QObject::connect(m_testPlugin, SIGNAL(error(const SignOn::Error & )), |
639 | + this, SLOT(pluginError(const SignOn::Error &)), |
640 | + Qt::QueuedConnection); |
641 | + QObject::connect(m_testPlugin, SIGNAL(userActionRequired(const SignOn::UiSessionData&)), |
642 | + this, SLOT(uiRequest(const SignOn::UiSessionData&)), |
643 | + Qt::QueuedConnection); |
644 | + QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); |
645 | + |
646 | + TestNetworkAccessManager *nam = new TestNetworkAccessManager; |
647 | + m_testPlugin->m_networkAccessManager = nam; |
648 | + TestNetworkReply *reply = new TestNetworkReply(this); |
649 | + reply->setStatusCode(200); |
650 | + reply->setContentType("application/json"); |
651 | + reply->setContent("{ \"access_token\":\"n3w-t0k3n\", \"expires_in\": 3600 }"); |
652 | + nam->setNextReply(reply); |
653 | + |
654 | + m_testPlugin->process(data, QString("web_server")); |
655 | + m_loop.exec(); |
656 | + |
657 | + QCOMPARE(m_error.type(), -1); |
658 | + QCOMPARE(nam->m_lastRequest.url(), QUrl("https://localhost/access_token")); |
659 | + QCOMPARE(QString::fromUtf8(nam->m_lastRequestData), |
660 | + QString("grant_type=refresh_token&refresh_token=r3fr3sh")); |
661 | + |
662 | + QVariantMap expectedResponse; |
663 | + expectedResponse.insert("AccessToken", "n3w-t0k3n"); |
664 | + expectedResponse.insert("ExpiresIn", 3600); |
665 | + expectedResponse.insert("RefreshToken", QString()); |
666 | + qDebug() << "got response" << m_response.toMap(); |
667 | + qDebug() << "expected" << expectedResponse; |
668 | + QCOMPARE(m_response.toMap(), expectedResponse); |
669 | + |
670 | + delete nam; |
671 | + |
672 | + TEST_DONE |
673 | +} |
674 | + |
675 | +void OAuth2PluginTest::testClientAuthentication_data() |
676 | +{ |
677 | + QTest::addColumn<QString>("clientSecret"); |
678 | + QTest::addColumn<bool>("forceAuthViaRequestBody"); |
679 | + QTest::addColumn<QString>("postContents"); |
680 | + QTest::addColumn<QString>("postAuthorization"); |
681 | + |
682 | + QTest::newRow("no secret, std auth") << |
683 | + "" << false << |
684 | + "grant_type=authorization_code&code=c0d3" |
685 | + "&redirect_uri=http://localhost/resp.html&client_id=104660106251471" << |
686 | + ""; |
687 | + QTest::newRow("no secret, auth in body") << |
688 | + "" << true << |
689 | + "grant_type=authorization_code&code=c0d3" |
690 | + "&redirect_uri=http://localhost/resp.html&client_id=104660106251471" << |
691 | + ""; |
692 | + |
693 | + QTest::newRow("with secret, std auth") << |
694 | + "s3cr3t" << false << |
695 | + "grant_type=authorization_code&code=c0d3&redirect_uri=http://localhost/resp.html" << |
696 | + "Basic MTA0NjYwMTA2MjUxNDcxOnMzY3IzdA=="; |
697 | + QTest::newRow("with secret, auth in body") << |
698 | + "s3cr3t" << true << |
699 | + "grant_type=authorization_code&code=c0d3" |
700 | + "&redirect_uri=http://localhost/resp.html" |
701 | + "&client_id=104660106251471&client_secret=s3cr3t" << |
702 | + ""; |
703 | +} |
704 | + |
705 | +void OAuth2PluginTest::testClientAuthentication() |
706 | +{ |
707 | + TEST_START |
708 | + |
709 | + QFETCH(QString, clientSecret); |
710 | + QFETCH(bool, forceAuthViaRequestBody); |
711 | + QFETCH(QString, postContents); |
712 | + QFETCH(QString, postAuthorization); |
713 | + |
714 | + SignOn::UiSessionData info; |
715 | + OAuth2PluginData data; |
716 | + data.setHost("localhost"); |
717 | + data.setAuthPath("authorize"); |
718 | + data.setTokenPath("access_token"); |
719 | + data.setClientId("104660106251471"); |
720 | + data.setClientSecret(clientSecret); |
721 | + data.setRedirectUri("http://localhost/resp.html"); |
722 | + data.setForceClientAuthViaRequestBody(forceAuthViaRequestBody); |
723 | + |
724 | + QObject::connect(m_testPlugin, SIGNAL(result(const SignOn::SessionData&)), |
725 | + this, SLOT(result(const SignOn::SessionData&)), |
726 | + Qt::QueuedConnection); |
727 | + QObject::connect(m_testPlugin, SIGNAL(error(const SignOn::Error & )), |
728 | + this, SLOT(pluginError(const SignOn::Error &)), |
729 | + Qt::QueuedConnection); |
730 | + QObject::connect(m_testPlugin, SIGNAL(userActionRequired(const SignOn::UiSessionData&)), |
731 | + this, SLOT(uiRequest(const SignOn::UiSessionData&)), |
732 | + Qt::QueuedConnection); |
733 | + QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); |
734 | + |
735 | + TestNetworkAccessManager *nam = new TestNetworkAccessManager; |
736 | + m_testPlugin->m_networkAccessManager = nam; |
737 | + TestNetworkReply *reply = new TestNetworkReply(this); |
738 | + reply->setStatusCode(200); |
739 | + reply->setContentType("application/json"); |
740 | + reply->setContent("{ \"access_token\":\"t0k3n\", \"expires_in\": 3600 }"); |
741 | + nam->setNextReply(reply); |
742 | + |
743 | + m_testPlugin->process(data, QString("web_server")); |
744 | + m_loop.exec(); |
745 | + |
746 | + info.setUrlResponse("http://localhost/resp.html?code=c0d3"); |
747 | + m_testPlugin->userActionFinished(info); |
748 | + m_loop.exec(); |
749 | + |
750 | + QCOMPARE(m_error.type(), -1); |
751 | + QCOMPARE(nam->m_lastRequest.url(), QUrl("https://localhost/access_token")); |
752 | + QCOMPARE(QString::fromUtf8(nam->m_lastRequestData), postContents); |
753 | + QCOMPARE(QString::fromUtf8(nam->m_lastRequest.rawHeader("Authorization")), |
754 | + postAuthorization); |
755 | + |
756 | + delete nam; |
757 | |
758 | TEST_DONE |
759 | } |
760 | @@ -561,4 +1051,4 @@ |
761 | //end test cases |
762 | |
763 | QTEST_MAIN(OAuth2PluginTest) |
764 | - |
765 | +#include "oauth2plugintest.moc" |
766 | |
767 | === modified file 'tests/oauth2plugintest.h' |
768 | --- tests/oauth2plugintest.h 2013-06-04 05:04:43 +0000 |
769 | +++ tests/oauth2plugintest.h 2014-09-12 09:09:50 +0000 |
770 | @@ -56,7 +56,13 @@ |
771 | void testPluginProcess(); |
772 | void testPluginHmacSha1Process(); |
773 | void testPluginUseragentUserActionFinished(); |
774 | + void testPluginWebserverUserActionFinished_data(); |
775 | void testPluginWebserverUserActionFinished(); |
776 | + void testOAuth2Errors_data(); |
777 | + void testOAuth2Errors(); |
778 | + void testRefreshToken(); |
779 | + void testClientAuthentication_data(); |
780 | + void testClientAuthentication(); |
781 | |
782 | private: |
783 | Plugin *m_testPlugin; |
FAILED: Continuous integration, rev:65 jenkins. qa.ubuntu. com/job/ signon- plugin- oauth2- ci/13/ jenkins. qa.ubuntu. com/job/ signon- plugin- oauth2- utopic- amd64-ci/ 4/console jenkins. qa.ubuntu. com/job/ signon- plugin- oauth2- utopic- armhf-ci/ 4/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/signon- plugin- oauth2- ci/13/rebuild
http://