added OAuth20Credentials class, some minor OAuth10Credentials fixes

This commit is contained in:
Guenter Obiltschnig 2014-11-11 12:10:53 +01:00
parent b0946115cf
commit fbcbf708aa
9 changed files with 402 additions and 14 deletions

View File

@ -33,7 +33,7 @@ objects = \
NTPClient NTPEventArgs NTPPacket \
RemoteSyslogChannel RemoteSyslogListener SMTPChannel \
WebSocket WebSocketImpl \
OAuth10Credentials
OAuth10Credentials OAuth20Credentials
target = PocoNet
target_version = $(LIBVERSION)

View File

@ -102,12 +102,12 @@ public:
/// Creates an empty OAuth10Credentials object.
OAuth10Credentials(const std::string& consumerKey, const std::string& consumerSecret);
/// Creates an HTTPCredentials object with the given consumer key and consumer secret.
/// Creates an OAuth10Credentials object with the given consumer key and consumer secret.
///
/// The token and tokenSecret will be left empty.
OAuth10Credentials(const std::string& consumerKey, const std::string& consumerSecret, const std::string& token, const std::string& tokenSecret);
/// Creates an HTTPCredentials object with the given consumer key and
/// Creates an OAuth10Credentials object with the given consumer key and
/// consumer secret, as well as token and token secret.
explicit OAuth10Credentials(const HTTPRequest& request);
@ -119,7 +119,7 @@ public:
/// not contain OAuth 1.0 credentials.
~OAuth10Credentials();
/// Destroys the HTTPCredentials.
/// Destroys the OAuth10Credentials.
void setConsumerKey(const std::string& consumerKey);
/// Sets the consumer key.
@ -195,6 +195,8 @@ public:
/// computed by createNonce() and the timestamp is taken
/// from the system time.
static const std::string SCHEME;
protected:
void signPlaintext(Poco::Net::HTTPRequest& request) const;
/// Signs the given HTTP request according to OAuth 1.0A PLAINTEXT signature method.

View File

@ -0,0 +1,121 @@
//
// OAuth20Credentials.h
//
// $Id$
//
// Library: Net
// Package: OAuth
// Module: OAuth20Credentials
//
// Definition of the OAuth20Credentials class.
//
// Copyright (c) 2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Net_OAuth20Credentials_INCLUDED
#define Net_OAuth20Credentials_INCLUDED
#include "Poco/Net/Net.h"
namespace Poco {
namespace Net {
class HTTPRequest;
class Net_API OAuth20Credentials
/// This class implements OAuth 2.0 authentication for HTTP requests,
/// via Bearer tokens in the Authorization header,
/// according to RFC 6749 and RFC 6750.
{
public:
OAuth20Credentials();
/// Creates an empty OAuth20Credentials object.
explicit OAuth20Credentials(const std::string& bearerToken);
/// Creates an OAuth20Credentials object with the given bearer token.
OAuth20Credentials(const std::string& bearerToken, const std::string& scheme);
/// Creates an OAuth20Credentials object with the given bearer token
/// and authorization scheme, which overrides the default scheme ("Bearer").
///
/// This is useful for services like GitHub, which use "token" as scheme.
explicit OAuth20Credentials(const HTTPRequest& request);
/// Creates an OAuth20Credentials object from a HTTPRequest object.
///
/// Extracts bearer token from the Authorization header, which
/// must use the "Bearer" authorization scheme.
///
/// Throws a NotAuthenticatedException if the request does
/// not contain a bearer token in the Authorization header.
OAuth20Credentials(const HTTPRequest& request, const std::string& scheme);
/// Creates an OAuth20Credentials object from a HTTPRequest object.
///
/// Extracts bearer token from the Authorization header, which must
/// use the given authorization scheme.
///
/// Throws a NotAuthenticatedException if the request does
/// not contain a bearer token in the Authorization header.
~OAuth20Credentials();
/// Destroys the HTTPCredentials.
void setBearerToken(const std::string& bearerToken);
/// Sets the bearer token.
const std::string& getBearerToken() const;
/// Returns the bearer token.
void setScheme(const std::string& scheme);
/// Sets the Authorization header scheme.
const std::string& getScheme() const;
/// Returns the Authorization header scheme.
void authenticate(HTTPRequest& request);
/// Adds an Authorization header containing the bearer token to
/// the HTTPRequest.
static const std::string SCHEME;
protected:
void extractBearerToken(const HTTPRequest& request);
/// Extracts the bearer token from the HTTPRequest.
private:
OAuth20Credentials(const OAuth20Credentials&);
OAuth20Credentials& operator = (const OAuth20Credentials&);
std::string _bearerToken;
std::string _scheme;
};
//
// inlines
//
inline const std::string& OAuth20Credentials::getBearerToken() const
{
return _bearerToken;
}
inline const std::string& OAuth20Credentials::getScheme() const
{
return _scheme;
}
} } // namespace Poco::Net
#endif // Net_OAuth20Credentials_INCLUDED

View File

@ -16,7 +16,6 @@
#include "Poco/Net/OAuth10Credentials.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/HTMLForm.h"
#include "Poco/Net/NetException.h"
#include "Poco/Net/HTTPAuthenticationParams.h"
@ -28,6 +27,7 @@
#include "Poco/NumberParser.h"
#include "Poco/NumberFormatter.h"
#include "Poco/Format.h"
#include "Poco/String.h"
#include <map>
#include <sstream>
@ -36,6 +36,9 @@ namespace Poco {
namespace Net {
const std::string OAuth10Credentials::SCHEME = "OAuth";
OAuth10Credentials::OAuth10Credentials()
{
}
@ -64,7 +67,7 @@ OAuth10Credentials::OAuth10Credentials(const Poco::Net::HTTPRequest& request)
std::string authScheme;
std::string authParams;
request.getCredentials(authScheme, authParams);
if (authScheme == "OAuth")
if (icompare(authScheme, SCHEME) == 0)
{
HTTPAuthenticationParams params(authParams);
std::string consumerKey = params.get("oauth_consumer_key", "");
@ -158,7 +161,7 @@ bool OAuth10Credentials::verify(const HTTPRequest& request, const Poco::URI& uri
std::string authScheme;
std::string authParams;
request.getCredentials(authScheme, authParams);
if (authScheme == "OAuth")
if (icompare(authScheme, SCHEME) == 0)
{
HTTPAuthenticationParams oauthParams(authParams);
@ -190,13 +193,13 @@ bool OAuth10Credentials::verify(const HTTPRequest& request, const Poco::URI& uri
URI::decode(signatureEnc, signature);
std::string refSignature;
if (method == "PLAINTEXT")
if (icompare(method, "PLAINTEXT") == 0)
{
refSignature = percentEncode(_consumerSecret);
refSignature += '&';
refSignature += percentEncode(_tokenSecret);
}
else if (method == "HMAC-SHA1")
else if (icompare(method, "HMAC-SHA1") == 0)
{
URI uriWithoutQuery(uri);
uriWithoutQuery.setQuery("");
@ -226,7 +229,7 @@ void OAuth10Credentials::signPlaintext(Poco::Net::HTTPRequest& request) const
signature += '&';
signature += percentEncode(_tokenSecret);
std::string authorization("OAuth");
std::string authorization(SCHEME);
if (!_realm.empty())
{
Poco::format(authorization, " realm=\"%s\",", _realm);
@ -244,7 +247,7 @@ void OAuth10Credentials::signPlaintext(Poco::Net::HTTPRequest& request) const
}
authorization += ", oauth_version=\"1.0\"";
request.set("Authorization", authorization);
request.set(HTTPRequest::AUTHORIZATION, authorization);
}
@ -262,7 +265,7 @@ void OAuth10Credentials::signHMACSHA1(Poco::Net::HTTPRequest& request, const std
}
std::string signature(createSignature(request, uri, params, nonce, timestamp));
std::string authorization("OAuth");
std::string authorization(SCHEME);
if (!_realm.empty())
{
Poco::format(authorization, " realm=\"%s\",", _realm);
@ -282,7 +285,7 @@ void OAuth10Credentials::signHMACSHA1(Poco::Net::HTTPRequest& request, const std
}
authorization += ", oauth_version=\"1.0\"";
request.set("Authorization", authorization);
request.set(HTTPRequest::AUTHORIZATION, authorization);
}

View File

@ -0,0 +1,107 @@
//
// OAuth20Credentials.cpp
//
// $Id$
//
// Library: Net
// Package: OAuth
// Module: OAuth20Credentials
//
// Copyright (c) 2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/OAuth20Credentials.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/NetException.h"
#include "Poco/String.h"
namespace Poco {
namespace Net {
const std::string OAuth20Credentials::SCHEME = "Bearer";
OAuth20Credentials::OAuth20Credentials():
_scheme(SCHEME)
{
}
OAuth20Credentials::OAuth20Credentials(const std::string& bearerToken):
_bearerToken(bearerToken),
_scheme(SCHEME)
{
}
OAuth20Credentials::OAuth20Credentials(const std::string& bearerToken, const std::string& scheme):
_bearerToken(bearerToken),
_scheme(scheme)
{
}
OAuth20Credentials::OAuth20Credentials(const HTTPRequest& request):
_scheme(SCHEME)
{
extractBearerToken(request);
}
OAuth20Credentials::OAuth20Credentials(const HTTPRequest& request, const std::string& scheme):
_scheme(scheme)
{
extractBearerToken(request);
}
OAuth20Credentials::~OAuth20Credentials()
{
}
void OAuth20Credentials::setBearerToken(const std::string& bearerToken)
{
_bearerToken = bearerToken;
}
void OAuth20Credentials::setScheme(const std::string& scheme)
{
_scheme = scheme;
}
void OAuth20Credentials::authenticate(HTTPRequest& request)
{
std::string auth(_scheme);
auth += ' ';
auth += _bearerToken;
request.set(HTTPRequest::AUTHORIZATION, auth);
}
void OAuth20Credentials::extractBearerToken(const HTTPRequest& request)
{
if (request.hasCredentials())
{
std::string authScheme;
std::string authInfo;
request.getCredentials(authScheme, authInfo);
if (icompare(authScheme, _scheme) == 0)
{
_bearerToken = authInfo;
}
else throw NotAuthenticatedException("No bearer token in Authorization header", authScheme);
}
else throw NotAuthenticatedException("No Authorization header found");
}
} } // namespace Poco::Net

View File

@ -28,7 +28,7 @@ objects = \
NTPClientTest NTPClientTestSuite \
WebSocketTest WebSocketTestSuite \
SyslogTest \
OAuth10CredentialsTest OAuthTestSuite
OAuth10CredentialsTest OAuth20CredentialsTest OAuthTestSuite
target = testrunner
target_version = 1

View File

@ -0,0 +1,109 @@
//
// OAuth20CredentialsTest.cpp
//
// $Id$
//
// Copyright (c) 2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "OAuth20CredentialsTest.h"
#include "CppUnit/TestCaller.h"
#include "CppUnit/TestSuite.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/OAuth20Credentials.h"
#include "Poco/Net/NetException.h"
using Poco::Net::HTTPRequest;
using Poco::Net::OAuth20Credentials;
using Poco::Net::NotAuthenticatedException;
OAuth20CredentialsTest::OAuth20CredentialsTest(const std::string& name): CppUnit::TestCase(name)
{
}
OAuth20CredentialsTest::~OAuth20CredentialsTest()
{
}
void OAuth20CredentialsTest::testAuthorize()
{
OAuth20Credentials creds("s3cr3tt0k3n");
HTTPRequest request(HTTPRequest::HTTP_GET, "/");
creds.authenticate(request);
std::string auth = request.get("Authorization");
assert (auth == "Bearer s3cr3tt0k3n");
}
void OAuth20CredentialsTest::testAuthorizeCustomScheme()
{
OAuth20Credentials creds("s3cr3tt0k3n", "token");
HTTPRequest request(HTTPRequest::HTTP_GET, "/");
creds.authenticate(request);
std::string auth = request.get("Authorization");
assert (auth == "token s3cr3tt0k3n");
}
void OAuth20CredentialsTest::testExtract()
{
HTTPRequest request(HTTPRequest::HTTP_GET, "/");
request.set("Authorization", "Bearer s3cr3tt0k3n");
OAuth20Credentials creds(request);
assert (creds.getBearerToken() == "s3cr3tt0k3n");
}
void OAuth20CredentialsTest::testExtractCustomScheme()
{
HTTPRequest request(HTTPRequest::HTTP_GET, "/");
request.set("Authorization", "token s3cr3tt0k3n");
OAuth20Credentials creds(request, "token");
assert (creds.getBearerToken() == "s3cr3tt0k3n");
}
void OAuth20CredentialsTest::testExtractNoCreds()
{
HTTPRequest request(HTTPRequest::HTTP_GET, "/");
try
{
OAuth20Credentials creds(request);
fail("no credentials - must throw");
}
catch (NotAuthenticatedException&)
{
}
}
void OAuth20CredentialsTest::setUp()
{
}
void OAuth20CredentialsTest::tearDown()
{
}
CppUnit::Test* OAuth20CredentialsTest::suite()
{
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("OAuth20CredentialsTest");
CppUnit_addTest(pSuite, OAuth20CredentialsTest, testAuthorize);
CppUnit_addTest(pSuite, OAuth20CredentialsTest, testAuthorizeCustomScheme);
CppUnit_addTest(pSuite, OAuth20CredentialsTest, testExtract);
CppUnit_addTest(pSuite, OAuth20CredentialsTest, testExtractCustomScheme);
CppUnit_addTest(pSuite, OAuth20CredentialsTest, testExtractNoCreds);
return pSuite;
}

View File

@ -0,0 +1,44 @@
//
// OAuth20CredentialsTest.h
//
// $Id$
//
// Definition of the OAuth20CredentialsTest class.
//
// Copyright (c) 2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef OAuth20CredentialsTest_INCLUDED
#define OAuth20CredentialsTest_INCLUDED
#include "Poco/Net/Net.h"
#include "CppUnit/TestCase.h"
class OAuth20CredentialsTest: public CppUnit::TestCase
{
public:
OAuth20CredentialsTest(const std::string& name);
~OAuth20CredentialsTest();
void testAuthorize();
void testAuthorizeCustomScheme();
void testExtract();
void testExtractCustomScheme();
void testExtractNoCreds();
void setUp();
void tearDown();
static CppUnit::Test* suite();
private:
};
#endif // OAuth20CredentialsTest_INCLUDED

View File

@ -12,6 +12,7 @@
#include "OAuthTestSuite.h"
#include "OAuth10CredentialsTest.h"
#include "OAuth20CredentialsTest.h"
CppUnit::Test* OAuthTestSuite::suite()
@ -19,6 +20,7 @@ CppUnit::Test* OAuthTestSuite::suite()
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("OAuthTestSuite");
pSuite->addTest(OAuth10CredentialsTest::suite());
pSuite->addTest(OAuth20CredentialsTest::suite());
return pSuite;
}