diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..0a2df9277 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: ['https://www.paypal.com/paypalme/algr453'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.gitignore b/.gitignore index a9a50de0e..5c3b031d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,15 @@ - # Eclipse specific settings - .classpath .project .settings # IntelliJ Idea settings - .idea -scribe.iml +*.iml -# Binaries +# Netbeans settings +nb-configuration.xml +nbproject -target \ No newline at end of file +# Binaries +target diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c966b9e63..000000000 --- a/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -# kickstart travis. -language: java - -# need to override travis 'install' since it will try gpg sign and fail. -install: mvn clean package -DskipTests=true diff --git a/LICENSE.txt b/LICENSE.txt index 53b46da96..6085098bc 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 000000000..b90ef2e5f --- /dev/null +++ b/README.md @@ -0,0 +1,180 @@ +# Welcome to the home of ScribeJava, the simple OAuth client Java lib! + +[![Donate](https://www.paypalobjects.com/en_US/RU/i/btn/btn_donateCC_LG.gif)](https://github.com/scribejava/scribejava/blob/master/donate.md) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.scribejava/scribejava/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.scribejava/scribejava) + + +# Why use ScribeJava? + +### Dead Simple + +Who said OAuth/OAuth2 was difficult? Configuring ScribeJava is __so easy your grandma can do it__! check it out: + +```java +OAuthService service = new ServiceBuilder(YOUR_CLIENT_ID) + .apiSecret(YOUR_CLIENT_SECRET) + .build(LinkedInApi20.instance()); +``` + +That **single line** (added newlines for readability) is the only thing you need to configure ScribeJava with LinkedIn's OAuth API for example. + +Working executable examples are [here](https://github.com/scribejava/scribejava/tree/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples) +Common usage: [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20Example.java) + +### Threadsafe + +Hit ScribeJava as hard and with many threads as you like. + +### Java 7 compatible + +That's it. You can use it in old environments and in android apps. +note: To compile from sources you will need Java 9 or newer + +### Async and other HTTP clients + +ScribeJava support out-of-box several HTTP clients: + * ning async http client 1.9.x (maven module scribejava-httpclient-ning) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FacebookAsyncNingExample.java) + * Async Http Client asynchttpclient 2.x (maven module scribejava-httpclient-ahc) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20AsyncAHCExample.java) + * OkHttp (maven module scribejava-httpclient-okhttp) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/GitHubAsyncOkHttpExample.java) + * Apache HttpComponents HttpClient (maven module scribejava-httpclient-apache) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FacebookAsyncApacheExample.java) + * Armeria HTTP client (required >= java 8) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20ArmeriaExample.java) + * any externally created HTTP client [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteExternalHttpExample.java) + + just add corresponding maven modules to your pom + +### Supports many flows and additional features + + * [RFC 6749](https://tools.ietf.org/html/rfc6749) The OAuth 2.0 Authorization Framework, [Authorization Code Authorization Grant](https://tools.ietf.org/html/rfc6749#section-4.1), [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20Example.java) + * [RFC 6749](https://tools.ietf.org/html/rfc6749) The OAuth 2.0 Authorization Framework, [Resource Owner Password Credentials Authorization Grant](https://tools.ietf.org/html/rfc6749#section-4.3) + * [RFC 6749](https://tools.ietf.org/html/rfc6749) The OAuth 2.0 Authorization Framework, [Client Credentials Authorization Grant](https://tools.ietf.org/html/rfc6749#section-4.4), [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteClientCredentialsGrantExample.java) + * [RFC 6749](https://tools.ietf.org/html/rfc6749) The OAuth 2.0 Authorization Framework, [Refreshing an Access Token](https://tools.ietf.org/html/rfc6749#section-6), [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20Example.java#L77) + * [RFC 6750](https://tools.ietf.org/html/rfc6750) The OAuth 2.0 Authorization Framework: Bearer Token Usage + * [RFC 7636](https://tools.ietf.org/html/rfc7636) Proof Key for Code Exchange by OAuth Public Clients (PKCE), [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20WithPKCEExample.java) + * [RFC 7009](https://tools.ietf.org/html/rfc7009) OAuth 2.0 Token Revocation, [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20RevokeExample.java) + * [RFC 8628](https://tools.ietf.org/html/rfc8628) OAuth 2.0 Device Authorization Grant [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20DeviceAuthorizationGrantExample.java) + * [RFC 5849](https://tools.ietf.org/html/rfc5849) The OAuth 1.0 Protocol, [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TwitterExample.java) + +### Supports all (50+) major 1.0a and 2.0 OAuth APIs out-of-the-box + +* Asana (https://asana.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/AsanaExample.java) +* Automatic (https://www.automatic.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/AutomaticExample.java) +* AWeber (http://www.aweber.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/AWeberExample.java) +* Box (https://www.box.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Box20Example.java) +* Dataporten (https://docs.dataporten.no/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/DataportenExample.java) +* Digg (http://digg.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/DiggExample.java) +* Discord (https://discordapp.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/DiscordExample.java) +* Доктор на работе (https://www.doktornarabote.ru/) +* Dropbox (https://www.dropbox.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/DropboxExample.java) +* Etsy (https://www.etsy.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/EtsyExample.java) +* Facebook (https://www.facebook.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FacebookExample.java), [example with Async Apache HTTP client](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FacebookAsyncApacheExample.java), [example with Async Ning HTTP client](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FacebookAsyncNingExample.java) +* Fitbit (https://www.fitbit.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FitbitApi20Example.java) +* Flickr (https://www.flickr.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FlickrExample.java) +* Foursquare (https://foursquare.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Foursquare2Example.java), [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FoursquareExample.java) +* Frappe (https://github.com/frappe/frappe) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FrappeExample.java) +* Freelancer (https://www.freelancer.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FreelancerExample.java) +* Genius (http://genius.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/GeniusExample.java) +* GitHub (https://github.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/GitHubExample.java), [example with OkHttp HTTP client](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/GitHubAsyncOkHttpExample.java) +* Google (https://www.google.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20Example.java), [example with Async Http Client](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20AsyncAHCExample.java), [example Revoke](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20RevokeExample.java), [example with PKCEE](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20WithPKCEExample.java) +* HeadHunter ХэдХантер (https://hh.ru/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/HHExample.java) +* HiOrg-Server (https://www.hiorg-server.de/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/HiOrgServerExample.java) +* Imgur (http://imgur.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/ImgurExample.java) +* Instagram (https://www.instagram.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/InstagramExample.java) +* Kaixin 开心网 (http://www.kaixin001.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Kaixin20Example.java) +* Kakao (https://kakao.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/KakaoExample.java) +* Keycloak (https://www.keycloak.org/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/KeycloakExample.java) +* LinkedIn (https://www.linkedin.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LinkedIn20Example.java), [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LinkedInExample.java), [example with custom scopes](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LinkedInExampleWithScopes.java) +* Mail.Ru (https://mail.ru/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MailruExample.java), [example with Async Ning HTTP Client](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MailruAsyncExample.java) +* MediaWiki (https://www.mediawiki.org/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MediaWikiExample.java) +* Meetup (https://www.meetup.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Meetup20Example.java), [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MeetupExample.java) +* Microsoft Azure Active Directory (Azure AD) (http://azure.microsoft.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MicrosoftAzureActiveDirectoryExample.java) +* Microsoft Azure Active Directory (Azure AD) 2.0 (http://azure.microsoft.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MicrosoftAzureActiveDirectory20Example.java) +* Microsoft Live (https://login.live.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LiveExample.java) +* Misfit (http://misfit.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MisfitExample.java) +* NAVER (http://www.naver.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/NaverExample.java) +* Odnoklassniki Одноклассники (http://ok.ru/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/OdnoklassnikiExample.java) +* Polar (https://www.polar.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/PolarAPIExample.java) +* Pinterest (https://www.pinterest.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/PinterestExample.java) +* 500px (https://500px.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Px500Example.java) +* Renren (http://renren.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/RenrenExample.java) +* Salesforce (https://www.salesforce.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SalesforceExample.java), [example with Async Ning HTTP Client](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SalesforceNingAsyncExample.java) +* Sina (http://www.sina.com.cn/ http://weibo.com/login.php) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SinaWeibo2Example.java), [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SinaWeiboExample.java) +* Skyrock (http://skyrock.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SkyrockExample.java) +* Slack (https://slack.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SlackExample.java) +* StackExchange (http://stackexchange.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/StackExchangeExample.java) +* The Things Network (v1-staging and v2-preview) (https://www.thethingsnetwork.org/) [example v1](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TheThingsNetworkV1StagingExample.java), [example v2 preview](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TheThingsNetworkV2PreviewExample.java) +* Trello (https://trello.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TrelloExample.java) +* Tumblr (https://www.tumblr.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TumblrExample.java) +* TUT.BY (http://www.tut.by/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TutByExample.java) +* Twitter (https://twitter.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TwitterExample.java) +* uCoz (https://www.ucoz.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/UcozExample.java) +* Viadeo (http://viadeo.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/ViadeoExample.java) +* VK ВКонтакте (http://vk.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteExample.java), [example Client Credentials Grant](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteClientCredentialsGrantExample.java), [example with External HTTP Client](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteExternalHttpExample.java) +* Wunderlist (https://www.wunderlist.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/WunderlistExample.java) +* Xero (https://www.xero.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/XeroExample.java) +* XING (https://www.xing.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/XingExample.java) +* Yahoo (https://www.yahoo.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Yahoo20Example.java), [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/YahooExample.java) +* check the [examples folder](https://github.com/scribejava/scribejava/tree/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples) + +### Small and modular + +ScribeJava's code is small (about 1k LOC) and simple to understand. No smart-ass or "clever" hacks here. +You can use only 'core' or 'with apis' maven modules + +### Android-Ready + +Works out of the box with android(TM) applications. + +### Stable & bulletproof + +Good test coverage to keep you safe from harm. + +When something bad actually happens, ScribeJava's meaningful error messages will tell you exactly what went wrong, when and where. + +### Pull it from Maven Central! + +You can pull ScribeJava from the central maven repository, just add these to your __pom.xml__ file: + +```xml + + com.github.scribejava + scribejava-apis + 8.3.3 + +``` + +And in case you need just core classes (that's it, without any external API (FB, VK, GitHub, Google etc) specific code), you could pull just 'core' artifact. +```xml + + com.github.scribejava + scribejava-core + 8.3.3 + +``` + +## How can I help ScribeJava + +First of all, Pull Requests are welcome, the second option is [donations](https://github.com/scribejava/scribejava/blob/master/donate.md). + +## When will ScribeJava support XXX (new RFC, custom functionality, new API etc.) + +When you will send the pull request. That's the way for a majority of changes here. +Or you can ask someone to make the paid job for you. +In some cases, when I'm interested in changes (technically or financially), I can implement the request myself. + +## Paid consulting +If you or your business depends on the Scribejava and you need any specific improvement or new feature not currently implemented in the Scribejava, consider contacting me about a paid job. + +## Getting started in less than 2 minutes + +Check the [Getting Started](https://github.com/scribejava/scribejava/wiki/getting-started) page and start rocking! Please Read the [FAQ](https://github.com/scribejava/scribejava/wiki/faq) before creating an issue :) + +Some useful info and answers you can find on the [wiki](https://github.com/scribejava/scribejava/wiki) + +Also, remember to read the [fantastic tutorial](http://akoskm.github.io/2015/07/31/twitter-sign-in-for-web-apps.html) that [@akoskm](https://twitter.com/akoskm) wrote to easily integrate a server side app with an API (twitter in this case). + +## Questions? + +Feel free to drop us an email or create issue right here on github.com + +## Forks + +If you have a useful fork that should be listed there please contact us diff --git a/README.textile b/README.textile deleted file mode 100644 index a20bccaa7..000000000 --- a/README.textile +++ /dev/null @@ -1,95 +0,0 @@ -h2. Welcome to the home of Scribe, the simple OAuth Java lib! - -!https://secure.travis-ci.org/fernandezpablo85/scribe-java.png?branch=master(travis-ci-status)! - -h1. Why use Scribe? - -h3. Dead Simple - -Who said OAuth was difficult? Configuring scribe is __so easy your grandma can do it__! check it out: - -@OAuthService service = new ServiceBuilder()@ - @.provider(LinkedInApi.class)@ - @.apiKey(YOUR_API_KEY)@ - @.apiSecret(YOUR_API_SECRET)@ - @.build();@ - -That **single line** (added newlines for readability) is the only thing you need to configure scribe with LinkedIn's OAuth API for example. - -h3. Threadsafe - -Hit Scribe as hard and with many threads as you like. - -h3. Supports all major 1.0a and 2.0 OAuth APIs out-of-the-box - -* Google - -* Facebook - -* Yahoo - -* LinkedIn - -* Twitter - -* Foursquare - -* Evernote - -* Vimeo - -* Yammer - -* Windows Live - -* and many more! check the "examples folder":http://github.com/fernandezpablo85/scribe-java/tree/master/src/test/java/org/scribe/examples - -h3. Small and modular - -Scribe's code is small (about 1k LOC) and simple to understand. No smart-ass or "clever" hacks here. - -h3. Android-Ready - -Works out of the box with android(TM) applications. - -h3. Stable & bulletproof - -Good test coverage to keep you safe from harm. - -When something bad actually happens, Scribe's meaningful error messages will tell you exactly what went wrong, when and where. - -h3. Pull it from Maven! (new) - -You can pull scribe from a maven repository, just add this to your __pom.xml__ file: - -@@ - @org.scribe@ - @scribe@ - @1.3.2@ -@@ - -h1. Getting started in less than 2 minutes - -Check the "Getting Started":http://wiki.github.com/fernandezpablo85/scribe-java/getting-started page and start rocking! - -h1. Please Read the "FAQ":http://wiki.github.com/fernandezpablo85/scribe-java/faq before creating an issue :) - -h1. Questions? - -Feel free to drop me an email, but there's already a "StackOverflow":http://stackoverflow.com tag for "scribe":http://stackoverflow.com/questions/tagged/scribe you should use. I'm subscribed to it so I'll pick the question immediately. - -Note that it really helps to run scribe on "debug mode":https://github.com/fernandezpablo85/scribe-java/wiki/debug-mode (since 1.3.0), to get additional info. To do this simply call the @.debug()@ method on the @ServiceBuilder@. - -h1. Forks - -Looking for a scribe variation? check the "Fork List":https://github.com/fernandezpablo85/scribe-java/wiki/Forks - -If you have a useful fork that should be listed there please contact me (see About me). - -h1. About me - -"LinkedIn profile":http://www.linkedin.com/in/fernandezpablo85 - -Email me: fernandezpablo85 at gmail.com - -Follow me: "@fernandezpablo":http://twitter.com/fernandezpablo diff --git a/bundle b/bundle deleted file mode 100755 index bae51557d..000000000 --- a/bundle +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -mvn source:jar javadoc:jar package gpg:sign repository:bundle-create -Dgpg.passphrase=$1 \ No newline at end of file diff --git a/changelog b/changelog new file mode 100644 index 000000000..e962e073b --- /dev/null +++ b/changelog @@ -0,0 +1,341 @@ +[8.3.3] + * update dependencies, including security updates in libraries + +[8.3.2] + * minor fixes and enhances + * update dependencies + * while using async HTTP client, you could miss some Throwables, now they will be thrown + +[8.3.1] + * fix java.lang.NoClassDefFoundError for non-java8 runtimes (e.g. Android 7.1.1) + (thanks to https://github.com/ChristopherGittner) + +[8.3.0] + * add Instagram (https://www.instagram.com/) API (thanks to https://github.com/faent) + * add getErrorMessage method to FacebookAccessTokenErrorResponse. Should be used instead of general getMessage method + from the parent Exception + +[8.2.0] + * add ScopeBuilder to easily specify multiple scopes while requesting OAuth2.0 Access Tokens + * make Base64 en/de-coding not dependent from java8 implementation (use three optional implementation + (internal java 8+, Apache Commons Codec, JAXB) detected in runtime) (thanks to https://github.com/CodingFabian) + * implement possibility to add extra parameters to Access Token Request + (AccessTokenRequestParams#*ExtraParameters methods), https://github.com/scribejava/scribejava/issues/980 + (thanks to https://github.com/pmorch) + +[8.1.0] + * add raw Response (with HTTP response code and body) as member to the OAuth2AccessTokenErrorResponse + * add possibility to set "" (empty string) as apiSecret + * add Slack API (https://slack.com/) (thanks to https://github.com/petrkopotev) + +[8.0.0] + * add Kakao API (https://kakao.com/) (thanks to https://github.com/v0o0v) + * support chunks in JDKHttpClient's Multipart (thanks to https://github.com/eos1d3) + * add support for OAuth 2.0 Device Authorization Grant (RFC 8628) (thanks to https://github.com/rebarbora-mckvak) + * update Google API URLs + +[7.1.1] + * add Proxy support (via config's option) to internal JDKHttpClient (thanks to https://github.com/bjournaud) + * fix typo (change "Verfier" to "Verifier") (thanks to https://github.com/afkbrb) + * fix Multipart support in JDKHttpClient (thanks to https://github.com/eos1d3) + +[7.0.0] + * Add Polar API (https://www.polar.com/) (thanks to https://github.com/vidi42) + * make Response accept resources to autoclose and autoclose it (thanks to https://github.com/drei01) + * fix url encoding in POST payload (it's needed for 'application/x-www-form-urlencoded' Content-Type) + + unit tests (thanks to https://github.com/max904-github) + * Add Armeria HTTP client (thanks to https://github.com/max904-github) + +[6.9.0] + * Add Xero API (https://www.xero.com/) (thanks to https://github.com/SidneyAllen) + +[6.8.1] + * make Response implements Closeable (thanks to https://github.com/omaric) + * fix Type resolution for builder pattern in ServiceBuilderOAuth10a (thanks to https://github.com/mgyucht) + * fix no Content-length errors (thanks to https://github.com/mikita-herasiutsin and https://github.com/iankurverma) + +[6.8.0] + * Add debug output to OAuth2Service (thanks to https://github.com/rbarbey) + * Add Dropbox API (https://www.dropbox.com/) (thanks to https://github.com/petrkopotev) + +[6.7.0] + * Add OAuth2 support for Meetup.com (thanks to https://github.com/stevedes77) + * upgrade okhttp to 4.0.1 and security fix for jackson-databind 2.9.9.1 + +[6.6.3] + * fix NPE for OpenId providers + +[6.6.2] + * add PMD checks on compile + * add all OAuth error codes from supported RFCs (incl. "invalid_token") (thanks to https://github.com/echorebel) + * Update LinkedIn Example to API v2 (thanks to https://github.com/peternees) + * switch to jackson dependency to parse json responses (thanks to https://github.com/galimru) + +[6.5.1] + * cleanup deprecates methods + +[6.5.0] + * separate OAuth1.0a and OAuth2.0 ServiceBuilders, + introduce AuthorizationUrlBuilder (along with deprecation of AuthorizationUrlWithPKCE) + add possibility to provide different scopes for each Access Token request + * upgrade Facebook API from v2.11 to v3.2 + * upgrade VkontakteApi from 5.73 to 5.92 + +[6.4.1] + * support TLS 1.3 in JDK 11 for Salesforce + * fix NPE in Apache HTTP client in case of empty body in HTTP response (e.g. with 204 response code) + (thanks to https://github.com/SainagNeelamPatnaik) + * separate OAuth1.0a and OAuth2.0 classes + +[6.3.0] + * fix Muplipart request model and implement it for a jdk HTTP client (thanks to https://github.com/NTPape) + * remove any Google+ mention (switch to clean Google OAuth2) (thanks to https://github.com/fvasco) + * fix Microsoft Azure AD v1.0 and v2.0 (thanks to https://github.com/kenpusney and https://github.com/oscararias) + * add new API Asana (https://asana.com/) (thanks to https://github.com/joestazak) + * state param should be used only for authorization url generation, for v2 only, for Authorization Code Grant only, + and it should be set per request, not per created OAuthService + +[6.2.0] + * add new API Microsoft Azure Active Directory (Azure AD) 2.0 + (thanks to https://github.com/rzukow and https://github.com/dgrudenic) + +[6.1.0] + * add new API Keycloak (https://www.keycloak.org/) (thanks to https://github.com/JureZelic) + * add new API Discord (https://discordapp.com/) (thanks to https://github.com/Jokuni) + +[6.0.0] + * make redirect_uri optional while Access Token requesting on OAuth 2.0 (thanks to https://github.com/computerlove) + * switch to java 9+ (from java 7 only) for compilation. Runtime is still java 7+. + Complement README with links and RFC descriptions. + * switch OAuth2 Bearer Token Usage from enum OAuth2SignatureType to interface BearerSignature to be extensible + * add new API Wunderlist (https://www.wunderlist.com/) (thanks to https://github.com/M-F-K) + +[5.6.0] + * remove support for obsolete NetEase (http://www.163.com/) and sohu 搜狐 (http://www.sohu.com/) + (thanks to https://github.com/zawn) + * add Multipart functionality to JDK Http Client (thanks to https://github.com/eos1d3) + * switch OAuth2 ClientAuthenticationType from enum to interface ClientAuthentication to be extensible according to + https://tools.ietf.org/html/rfc6749#section-2.3.2 (thanks to https://github.com/zawn) + * add RuntimeException processing in async http clients (delivered to onError callbacks) + (thanks to https://github.com/jochen314) + * check 200 status code from response in OAuth2AccessTokenExtractor (thanks to https://github.com/jochen314) + * fix case sensitive Http Headers comparison and sending Content-Type header along with content-type + (thanks to https://github.com/marnix) + * add HiOrg-Server (https://www.hiorg-server.de/) API (thanks to https://github.com/MartinBoehmer) + +[5.5.0] + * fix error parsing for Fitbit (thanks to https://github.com/danmana) + * optimize debug log performance impact on prod in OAuth1 and fix + NoClassDefFoundError on Android device with SDK 18 and lower (thanks to https://github.com/arcao) + * add new API - MediaWiki (https://www.mediawiki.org/) (thanks to https://github.com/lucaswerkmeister) + +[5.4.0] + * fix missing support for scope for refresh_token grant_type (thanks to https://github.com/tlxtellef) + * add email field to VKOAuth2AccessToken (thanks to https://github.com/grouzen) + * add new API - Automatic (https://www.automatic.com/) (thanks to https://github.com/ramsrib) + * add new API - Fitbit (https://www.fitbit.com/) + (thanks to https://github.com/JustinLawler and https://github.com/alexthered) + * deprecate OAuthConfig + * OAuth1.0: send "oob" instead of null callback while requesting RequestToken (thanks to https://github.com/Rafaelsk) + +[5.3.0] + * fix Salesforce API (thanks to https://github.com/jhorowitz-firedrum) + * remove 'final' from methods in OAuth[10a|20]Service to allow mocking it + * fix Pinterest API (thanks to https://github.com/sschwieb) + * add Yahoo2 API (thanks to https://github.com/javatestcase) + * fix Tumblr urls, convert to https (thanks to https://github.com/highthunder) + * fix: allow spaces in scope param in OAuth2Accesstoken response + * add required param version to VK ВКонтакте (http://vk.com/) urls + +[5.2.0-java7again] + * allow 'null' as callback. It's an optional parameter. Remove "oob" as default + (thanks to https://github.com/massongit) + * java7 compatible again! + +[5.1.0] + * drop optional dependency on Apache commons-codec + * add API - Dataporten (https://docs.dataporten.no/) (thanks to https://github.com/xibriz) + * add API - Microsoft Azure Active Directory (Azure AD) (thanks to https://github.com/kaushalmall) + * fix LinkedInApi20 (thanks to https://github.com/jhorowitz-firedrum) + +[5.0.0] + * drop Java 7 backward compatibility support, become Java 8 only (was reverted in v5.2.0-java7again) + * add JSON token extractor for OAuth 1.0a (thanks to https://github.com/evstropovv) + * add new API - uCoz (https://www.ucoz.com/) (thanks to https://github.com/evstropovv) + * add PKCE (RFC 7636) support (Proof Key for Code Exchange by OAuth Public Clients) + (thanks for suggesting to https://github.com/dieseldjango) + * switch to use HTTP Basic Authorization by default in requests with need of + (2.3. Client Authentication) https://tools.ietf.org/html/rfc6749#section-2.3 Can be overrided in API class + * add support for client_credentials grant type (thanks to https://github.com/vivin) + * add support for RFC 7009 OAuth 2.0 Token Revocation (thanks to https://github.com/vivin) + * add OAuth2Service signRequest method accepting just String, not OAuth2 Access Token Object. + Remove signRequest from abstract OAuthService. 2.0 and 1.0a will be a bit more different now. + * drop toString method from *Tokens to prevent leak of sensible data (token ans secrets) + (thanks to https://github.com/rcaa) + * add Apache HttpComponents HttpClient support in separate module (thanks to https://github.com/sschwieb) + * add support for appsecret_proof in Facebook + * update Facebook v2.8 -> v2.11 + (version can be configured while constructing OAuthService - use FacebookApi.customVersion("2.11")) + +[4.2.0] + * DELETE in JdkClient permits, but not requires payload (thanks to https://github.com/miguelD73) + * add new API - Frappe (https://github.com/frappe/frappe) (thanks to https://github.com/revant) + * add new API - Etsy (https://www.etsy.com/) (thanks to https://github.com/efekocabas) + +[4.1.2] + * LinkedIn use Header to sign OAuth2 requests + * upgrade ServiceBuilder to check apiKey preconditions compile-time (not run-time) + * update Live API (thanks to https://github.com/typhoon17) + +[4.1.1] + * omit the client_secret parameter if it is an empty string while refreshing token + (thanks to https://github.com/KungfuPancake) + * allow perms to be specified in Flickr Api (read, write, or delete) (thanks to https://github.com/rogerhu) + * OdnoklassnikiService should consider params in a body while signing the request + (thanks to https://github.com/MrNeuronix) + * do not open OutputStream for output while sending empty body in HTTP requests in the default JDK Http client + +[4.1.0] + * make client_secret optional in OAuth2 while requesting AccessToken + (if set to null, it's not required by OAuth2 specs) + * move OAuth1 SignatureType from ServiceBuilder to API + * add body for PATCH HTTP method + * make addOAuthParams appendSignature methods protected in OAuth10aService (to override them in case of need) + (thanks to https://github.com/vivin) + +[4.0.0] + * Remove OAuthRequestAsync, just OAuthRequest. Request should know about sync vs async. + Move default Http engine to JDKHttpClient. + * introduce SignatureType for OAuth2.0 to implement Bearer signing for the requests + * switch Google, GitHub, Facebook OAuth2.0 oauth requests signing to more secured recommended variant + (GET-param -> header Bearer) + * introduce custom nonstandard Facebook AccessTokenErrorResponse + +[3.4.1] + * Drop deprecated methods + * Move doktornarabote.ru urls to https (thanks to https://github.com/ezibrov) + +[3.4.0] + * uncouple OAuthRequest and Service. OAuthRequest shouldn't know anything about OAuthservice. + You don't need OAuthService to create OAuthRequest anymore. Async request should be sent via OAuthService method. + * add support for byte[] and File (async only) payload in OAuth Requests (thanks to https://github.com/keijohyttinen) + * add support for HTTP verbs (thanks to https://github.com/keijohyttinen) + * add OkHttp http client support (thanks to https://github.com/arcao) + * add default HTTP client configs + (to use like 'new ServiceBuilder().httpClientConfig(OkHttpHttpClientConfig.defaultConfig())') + * you can use your own impl of AsyncHttpClient + +[3.3.0] + * update Facebook v2.6 -> v2.8 + * add The Things Network API (v1-staging and v2-preview) (thanks to https://github.com/jpmeijers) + * add Box (thanks to https://github.com/MclaughlinSteve) + * fix: OAuth20Service::refreshAccessToken should use RefreshTokenEndpoint, not AccessTokenEndpoint + (thanks to https://github.com/vivin) + * move signRequest method to OAuthService (common for OAuth1 and OAuth2) (thanks to https://github.com/apomelov) + * drop deprecated setConnectionKeepAlive method + +[3.2.0] + * Add Naver API (thanks to chooco) + * handle OAuth2 error response for Issuing an Access Token (thanks to juherr) + +[3.1.0] + * fix OdnoklassnikiServiceImpl signature, params for hash must be sorted in lexicographic order, + see http://new.apiok.ru/dev/methods/ + * add posibility to use externally created http client + * make ScribeJava compilable under jdk7 (checkstyle downgraded for jdk 1.7) + * add travis CI (check [oracle|open]jdk7 oraclejdk8) + +[3.0.0] + * create abstract HTTP Client layer to support different HTTP clients as plugins + (AHC and Ning support becames maven submodules) + * remove changing global JVM property http.keepAlive, deprecate controlling this property inside of ScribeJava + (thanks to wldaunfr and rockihack) + +[2.8.1] + * add Salesforce sandbox API support + +[2.8.0] + * add Salesforce API + * update Linked In API + +[2.7.3] + * FIX: ScribeJava shouldn't require all async http client provider to be on the classpath if using only one of them + +[2.7.2] + * FIX: ScribeJava shouldn't require any async http client provider to be on the classpath (neither ning neither AHC) + +[2.7.1] + * do not hide checked IOException in unchecked IllegalArgumentException + +[2.7.0] + * make http async client implementation be more pluggable + * add async-http-client 2.0 support (thanks to Sai Chandrasekharan https://github.com/saichand) + * add Misfit (http://misfit.com/) API + * implement async version getting Request Token for OAuth 1.0a + +[2.6.0] + * simplify async/sync usages + * add optional "User-Agent" config option to use while making http calls + * refactor usage of grant_type [authorization_code|refresh_token|password|etc] + * add Genius.com API authentication (OAuth2) + * fix GitHub API + * standardize authorization url generation for OAuth2 + * update Facebook to v2.6 + * cleanup: drop old APIs without Examples and with outdated domains + +[2.5.3] + * fix - do not send two Content-Type header in async requests + * improve OK example + +[2.5.2] + * add Google Async Exmaple (with bugfix for it to work) + * add OSGI manifest metadata + * apiSecret is not mandatory parameter in config + (to use on client sides and other flows without need of the API secret) + * implement OAuth2 Authorization Response parsing in the OAuth20Service + (to extract code and state from url, useful for Android) + * update ok.ru API urls, add 'state' support, add refresh token to the example + +[2.4.0] + * APIs 2.0 can define different endpoints for access token and for refresh token (the same urls by default) + * mark Facebook doesn't support refresh token by throwing UnsupportedOperationException + * make JSON Access Token Extractor be the default for OAuth 2.0 (according to RFC 6749) + * drop Google OAuth 1.0 support (OAuth 1.0 was officially deprecated by Google) + * add response_type parameter to the ServiceBuilder/OAuthConfig to use not only "code" for authorization code + * remove Verifier object, we just need Strings, 'code' for OAuth2 and 'oauthVerifier' for OAuth1 + * default HTTP verb for OAuth 2.0 Access Token EndPoint is POST (http://tools.ietf.org/html/rfc6749#section-3.2) + * send missed headers in async version (as in sync) + * support 'password' grant_type for OAuth 2.0 + +[2.3.0] + * Stack Exchange authentication via OAuth 2.0 (stackoverflow.com, askubuntu.com, etc.). + * Support response in gzip. + * differentiate OAuth1 Access token, OAuth 1 Request Token and OAuth 2 Access token, make them conforms RFCs + * OAuth 1 APIs can choose whether to pass empty oauth_token param in requests + * Support refresh tokens for OAuth2 (very thanks to P. Daniel Tyreus https://github.com/pdtyreus) + +[2.2.2] + * make all APIs to be extentable (have protected constructors, useful for testing) + +[2.2.1] + * Update Facebook API v2.2 -> v2.5 + * Update hh.ru urls + +[2.2.0] + * Let GoogleApi20 supports OOB + * Updated Imgur API to OAuth2 + * force not to instantiate stateless APIs. Use provided singletons + * reduce OAuthService abstraction for OAuth1 and OAuth2. Separate OAuth(1|2)Services + +[2.1.0] + * add Pinterest API + +[2.0.1] + * small code enhancements + +[2.0] + * merge back SubScribe fork to the ScribeJava + +for previous changes see +v1-changelog - changelog for 1.x version +v2pre-changelog - changelog for SubScribe fork diff --git a/checkstyle.xml b/checkstyle.xml new file mode 100644 index 000000000..f7efbad65 --- /dev/null +++ b/checkstyle.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/donate.md b/donate.md new file mode 100644 index 000000000..99d3686dc --- /dev/null +++ b/donate.md @@ -0,0 +1,12 @@ +You can now help ScribeJava not only by Pull Requests. + +You can use [https://www.paypal.com/paypalme/algr453](https://www.paypal.com/paypalme/algr453) directly. + +Thanks in advance! + +ps.If you can't for any reason use above method, let me know, we will find the way out. + +Hall of fame "Donors" (in alphabetical order, if you don't want to be here, just put a note along with the donation):
+1.Douglas Ross from USA
+2.Ian Strachan
+3.Your name can be here. diff --git a/pmd.xml b/pmd.xml new file mode 100644 index 000000000..5d93d340b --- /dev/null +++ b/pmd.xml @@ -0,0 +1,124 @@ + + + + + This ruleset defines the PMD rules for project "ScribeJava". + + + + + + + true + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index dbee18cf6..b484b6a71 100644 --- a/pom.xml +++ b/pom.xml @@ -1,85 +1,305 @@ - - 4.0.0 - org.scribe - scribe - jar - 1.3.2 - Scribe OAuth Library - The best OAuth library out there - http://github.com/fernandezpablo85/scribe-java + + 4.0.0 + com.github.scribejava + scribejava + pom + 8.3.4-SNAPSHOT + ScribeJava OAuth Library + The best OAuth library out there + https://github.com/scribejava/scribejava - - org.sonatype.oss - oss-parent - 5 - + + org.sonatype.oss + oss-parent + 9 + - - - fernandezpablo85 - Pablo Fernandez - fernandezpablo85@gmail.com - -3 - - - diegossilveira - Diego Silveira - diegossilveira@gmail.com - -3 - - + + scribejava-core + scribejava-java8 + scribejava-apis + scribejava-httpclient-ahc + scribejava-httpclient-ning + scribejava-httpclient-okhttp + scribejava-httpclient-apache + scribejava-httpclient-armeria + - - - MIT - http://github.com/fernandezpablo85/scribe-java/blob/master/LICENSE.txt - - + + + MIT + https://github.com/scribejava/scribejava/blob/master/LICENSE.txt + + - - scm:http://github.com/fernandezpablo85/scribe-java.git - scm:http://github.com/fernandezpablo85/scribe-java.git - http://github.com/fernandezpablo85/scribe-java.git - + + scm:git:https://github.com/scribejava/scribejava + scm:git:https://github.com/scribejava/scribejava + https://github.com/scribejava/scribejava + HEAD + - - - commons-codec - commons-codec - 1.4 - - - - junit - junit - 4.8.1 - test - - - - - - - maven-compiler-plugin - - 1.5 - 1.5 - - - - org.apache.maven.plugins - maven-gpg-plugin - - - sign-artifacts - verify - - sign - - - - - - - + + + kullfar + Stanislav Gromov + kullfar@gmail.com + + all + + +3 + + + + + + com.fasterxml.jackson.core + jackson-databind + 2.14.0 + + + junit + junit + 4.13.2 + test + + + com.squareup.okhttp3 + mockwebserver + 4.10.0 + test + + + + + + + org.apache.felix + maven-bundle-plugin + 5.1.8 + + + bundle-manifest + process-classes + + manifest + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.2.0 + + + com.puppycrawl.tools + checkstyle + 10.4 + + + + + org.apache.maven.plugins + maven-release-plugin + 2.5.3 + + true + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + org.apache.maven.plugins + maven-clean-plugin + 3.2.0 + + + org.apache.maven.plugins + maven-install-plugin + 3.0.1 + + + + + + maven-compiler-plugin + 3.10.1 + + UTF-8 + ${java.release} + true + + -Xlint:-options + + + + + maven-deploy-plugin + 3.0.0 + + + default-deploy + deploy + + deploy + + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.0 + + UTF-8 + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.4.1 + + ${java.home}/bin/javadoc + UTF-8 + -html5 + all,-missing + + + + attach-javadoc + + jar + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + validate + validate + + + ${basedir}/src + + checkstyle.xml + UTF-8 + true + + + check + + + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.19.0 + + + net.sourceforge.pmd + pmd-core + ${pmdVersion} + + + net.sourceforge.pmd + pmd-java + ${pmdVersion} + + + net.sourceforge.pmd + pmd-javascript + ${pmdVersion} + + + net.sourceforge.pmd + pmd-jsp + ${pmdVersion} + + + + 1.${java.release} + false + + ../pmd.xml + + true + true + true + + + + + check + + + + + + + + + 7 + 6.51.0 + + + + + release-sign-artifacts + + + performRelease + true + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.0.1 + + + sign-artifacts + verify + + sign + + + + + + + + + diff --git a/scribejava-apis/pom.xml b/scribejava-apis/pom.xml new file mode 100644 index 000000000..4e51bb8b5 --- /dev/null +++ b/scribejava-apis/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + + + com.github.scribejava + scribejava + 8.3.4-SNAPSHOT + ../pom.xml + + + com.github.scribejava + scribejava-apis + ScribeJava APIs + jar + + + + com.github.scribejava + scribejava-core + ${project.version} + + + com.github.scribejava + scribejava-httpclient-ahc + ${project.version} + test + + + com.github.scribejava + scribejava-httpclient-ning + ${project.version} + test + + + com.github.scribejava + scribejava-httpclient-okhttp + ${project.version} + test + + + com.github.scribejava + scribejava-httpclient-apache + ${project.version} + test + + + com.github.scribejava + scribejava-httpclient-armeria + ${project.version} + test + + + io.netty + netty-resolver + 4.1.84.Final + test + + + + + + + org.apache.felix + maven-bundle-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/AWeberApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/AWeberApi.java new file mode 100644 index 000000000..9ad3a185a --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/AWeberApi.java @@ -0,0 +1,37 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; + +public class AWeberApi extends DefaultApi10a { + + private static final String AUTHORIZE_URL = "https://auth.aweber.com/1.0/oauth/authorize"; + private static final String REQUEST_TOKEN_ENDPOINT = "https://auth.aweber.com/1.0/oauth/request_token"; + private static final String ACCESS_TOKEN_ENDPOINT = "https://auth.aweber.com/1.0/oauth/access_token"; + + protected AWeberApi() { + } + + private static class InstanceHolder { + + private static final AWeberApi INSTANCE = new AWeberApi(); + } + + public static AWeberApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return ACCESS_TOKEN_ENDPOINT; + } + + @Override + public String getRequestTokenEndpoint() { + return REQUEST_TOKEN_ENDPOINT; + } + + @Override + public String getAuthorizationBaseUrl() { + return AUTHORIZE_URL; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/Asana20Api.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/Asana20Api.java new file mode 100644 index 000000000..5e769aab8 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/Asana20Api.java @@ -0,0 +1,27 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; + +public class Asana20Api extends DefaultApi20 { + + protected Asana20Api() { + } + + private static class InstanceHolder { + private static final Asana20Api INSTANCE = new Asana20Api(); + } + + public static Asana20Api instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://app.asana.com/-/oauth_token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://app.asana.com/-/oauth_authorize"; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/AutomaticAPI.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/AutomaticAPI.java new file mode 100644 index 000000000..58c82e040 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/AutomaticAPI.java @@ -0,0 +1,44 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +public class AutomaticAPI extends DefaultApi20 { + + private static final String AUTHORIZE_URL = "https://accounts.automatic.com/oauth/authorize"; + private static final String REFRESH_TOKEN_ENDPOINT = "https://accounts.automatic.com/oauth/refresh_token"; + private static final String ACCESS_TOKEN_ENDPOINT = "https://accounts.automatic.com/oauth/access_token"; + + protected AutomaticAPI() { + } + + private static class InstanceHolder { + + private static final AutomaticAPI INSTANCE = new AutomaticAPI(); + } + + public static AutomaticAPI instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return ACCESS_TOKEN_ENDPOINT; + } + + @Override + public String getRefreshTokenEndpoint() { + return REFRESH_TOKEN_ENDPOINT; + } + + @Override + protected String getAuthorizationBaseUrl() { + return AUTHORIZE_URL; + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/BoxApi20.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/BoxApi20.java new file mode 100644 index 000000000..91a4b7c16 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/BoxApi20.java @@ -0,0 +1,38 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; + +/** + * Box.com Api + */ +public class BoxApi20 extends DefaultApi20 { + + + protected BoxApi20() { + } + + private static class InstanceHolder { + private static final BoxApi20 INSTANCE = new BoxApi20(); + } + + public static BoxApi20 instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://api.box.com/oauth2/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://account.box.com/api/oauth2/authorize"; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/DataportenApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/DataportenApi.java new file mode 100644 index 000000000..5e7ad9ceb --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/DataportenApi.java @@ -0,0 +1,27 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; + +public class DataportenApi extends DefaultApi20 { + + protected DataportenApi() { + } + + private static class InstanceHolder { + private static final DataportenApi INSTANCE = new DataportenApi(); + } + + public static DataportenApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://auth.dataporten.no/oauth/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://auth.dataporten.no/oauth/authorization"; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/DiggApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/DiggApi.java new file mode 100644 index 000000000..c7e8e1bd1 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/DiggApi.java @@ -0,0 +1,35 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; + +public class DiggApi extends DefaultApi10a { + + private static final String AUTHORIZATION_URL = "http://digg.com/oauth/authorize"; + private static final String BASE_URL = "http://services.digg.com/oauth/"; + + protected DiggApi() { + } + + private static class InstanceHolder { + private static final DiggApi INSTANCE = new DiggApi(); + } + + public static DiggApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getRequestTokenEndpoint() { + return BASE_URL + "request_token"; + } + + @Override + public String getAccessTokenEndpoint() { + return BASE_URL + "access_token"; + } + + @Override + public String getAuthorizationBaseUrl() { + return AUTHORIZATION_URL; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/DiscordApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/DiscordApi.java new file mode 100644 index 000000000..0583b6dc5 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/DiscordApi.java @@ -0,0 +1,32 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; + +public class DiscordApi extends DefaultApi20 { + + private DiscordApi() { + } + + private static class InstanceHolder { + private static final DiscordApi INSTANCE = new DiscordApi(); + } + + public static DiscordApi instance() { + return DiscordApi.InstanceHolder.INSTANCE; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://discordapp.com/api/oauth2/authorize"; + } + + @Override + public String getRevokeTokenEndpoint() { + return "https://discordapp.com/api/oauth2/token/revoke"; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://discordapp.com/api/oauth2/token"; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/DoktornaraboteApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/DoktornaraboteApi.java new file mode 100644 index 000000000..1fcac7108 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/DoktornaraboteApi.java @@ -0,0 +1,27 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; + +public class DoktornaraboteApi extends DefaultApi20 { + + protected DoktornaraboteApi() { + } + + private static class InstanceHolder { + private static final DoktornaraboteApi INSTANCE = new DoktornaraboteApi(); + } + + public static DoktornaraboteApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://auth.doktornarabote.ru/OAuth/Token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://auth.doktornarabote.ru/OAuth/Authorize"; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/DropboxApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/DropboxApi.java new file mode 100644 index 000000000..8bbd646f5 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/DropboxApi.java @@ -0,0 +1,31 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; + +/** + * Dropbox.com Api + */ +public class DropboxApi extends DefaultApi20 { + + protected DropboxApi() { + } + + private static class InstanceHolder { + + private static final DropboxApi INSTANCE = new DropboxApi(); + } + + public static DropboxApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://api.dropbox.com/oauth2/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://www.dropbox.com/oauth2/authorize"; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/EtsyApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/EtsyApi.java new file mode 100644 index 000000000..00ca72918 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/EtsyApi.java @@ -0,0 +1,52 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; + +public class EtsyApi extends DefaultApi10a { + + private static final String AUTHORIZE_URL = "https://www.etsy.com/oauth/signin"; + private static final String ACCESS_TOKEN_URL = "https://openapi.etsy.com/v2/oauth/access_token"; + private static final String REQUEST_TOKEN_URL = "https://openapi.etsy.com/v2/oauth/request_token"; + + private final String scopeAsString; + + private EtsyApi() { + scopeAsString = null; + } + + private EtsyApi(String... scopes) { + final StringBuilder builder = new StringBuilder(); + for (String scope : scopes) { + builder.append("%20").append(scope); + } + scopeAsString = "?scope=" + builder.substring(3); + } + + private static class InstanceHolder { + + private static final EtsyApi INSTANCE = new EtsyApi(); + } + + public static EtsyApi instance() { + return InstanceHolder.INSTANCE; + } + + public static EtsyApi instance(String... scopes) { + return scopes == null || scopes.length == 0 ? instance() : new EtsyApi(scopes); + } + + @Override + public String getAccessTokenEndpoint() { + return ACCESS_TOKEN_URL; + } + + @Override + public String getRequestTokenEndpoint() { + return scopeAsString == null ? REQUEST_TOKEN_URL : REQUEST_TOKEN_URL + scopeAsString; + } + + @Override + public String getAuthorizationBaseUrl() { + return AUTHORIZE_URL; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/FacebookApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/FacebookApi.java new file mode 100644 index 000000000..d688248d6 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/FacebookApi.java @@ -0,0 +1,78 @@ +package com.github.scribejava.apis; + +import java.io.OutputStream; + +import com.github.scribejava.apis.facebook.FacebookAccessTokenJsonExtractor; +import com.github.scribejava.apis.facebook.FacebookService; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +public class FacebookApi extends DefaultApi20 { + + private final String version; + + protected FacebookApi() { + this("3.2"); + } + + protected FacebookApi(String version) { + this.version = version; + } + + private static class InstanceHolder { + + private static final FacebookApi INSTANCE = new FacebookApi(); + } + + public static FacebookApi instance() { + return InstanceHolder.INSTANCE; + } + + public static FacebookApi customVersion(String version) { + return new FacebookApi(version); + } + + @Override + public Verb getAccessTokenVerb() { + return Verb.GET; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://graph.facebook.com/v" + version + "/oauth/access_token"; + } + + @Override + public String getRefreshTokenEndpoint() { + throw new UnsupportedOperationException("Facebook doesn't support refreshing tokens"); + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://www.facebook.com/v" + version + "/dialog/oauth"; + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return FacebookAccessTokenJsonExtractor.instance(); + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } + + @Override + public FacebookService createService(String apiKey, String apiSecret, String callback, String defaultScope, + String responseType, OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, + HttpClient httpClient) { + return new FacebookService(this, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, + userAgent, httpClientConfig, httpClient); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/FitbitApi20.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/FitbitApi20.java new file mode 100644 index 000000000..f6e163978 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/FitbitApi20.java @@ -0,0 +1,38 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.apis.fitbit.FitBitJsonTokenExtractor; +import com.github.scribejava.core.builder.api.DefaultApi20; + + +/** + * Fitbit's OAuth2 client's implementation + * source: https://dev.fitbit.com/docs/oauth2/ + */ +public class FitbitApi20 extends DefaultApi20 { + + protected FitbitApi20() { + } + + private static class InstanceHolder { + private static final FitbitApi20 INSTANCE = new FitbitApi20(); + } + + public static FitbitApi20 instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://api.fitbit.com/oauth2/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://www.fitbit.com/oauth2/authorize"; + } + + @Override + public FitBitJsonTokenExtractor getAccessTokenExtractor() { + return FitBitJsonTokenExtractor.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/FlickrApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/FlickrApi.java new file mode 100644 index 000000000..eedb89890 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/FlickrApi.java @@ -0,0 +1,64 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; + +/** + * OAuth API for Flickr. + * + * @see Flickr API + */ +public class FlickrApi extends DefaultApi10a { + + private static final String AUTHORIZE_URL = "https://www.flickr.com/services/oauth/authorize"; + + public enum FlickrPerm { + READ, WRITE, DELETE + }; + + /** + * read, write, or delete (delete includes read/write) + */ + private final String permString; + + protected FlickrApi() { + permString = null; + } + + protected FlickrApi(FlickrPerm perm) { + permString = perm.name().toLowerCase(); + } + + private static class InstanceHolder { + + private static final FlickrApi INSTANCE = new FlickrApi(); + } + + public static FlickrApi instance() { + return InstanceHolder.INSTANCE; + } + + public static FlickrApi instance(FlickrPerm perm) { + return perm == null ? instance() : new FlickrApi(perm); + } + + /** + * {@inheritDoc} + */ + @Override + public String getAccessTokenEndpoint() { + return "https://www.flickr.com/services/oauth/access_token"; + } + + @Override + public String getAuthorizationBaseUrl() { + return permString == null ? AUTHORIZE_URL : AUTHORIZE_URL + "?perms=" + permString; + } + + /** + * {@inheritDoc} + */ + @Override + public String getRequestTokenEndpoint() { + return "https://www.flickr.com/services/oauth/request_token"; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/Foursquare2Api.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/Foursquare2Api.java new file mode 100644 index 000000000..a90547f3a --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/Foursquare2Api.java @@ -0,0 +1,40 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; + +public class Foursquare2Api extends DefaultApi20 { + + protected Foursquare2Api() { + } + + private static class InstanceHolder { + private static final Foursquare2Api INSTANCE = new Foursquare2Api(); + } + + public static Foursquare2Api instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public Verb getAccessTokenVerb() { + return Verb.GET; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://foursquare.com/oauth2/access_token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://foursquare.com/oauth2/authenticate"; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/FoursquareApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/FoursquareApi.java new file mode 100644 index 000000000..d10a184db --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/FoursquareApi.java @@ -0,0 +1,34 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; + +public class FoursquareApi extends DefaultApi10a { + + private static final String AUTHORIZATION_URL = "http://foursquare.com/oauth/authorize"; + + protected FoursquareApi() { + } + + private static class InstanceHolder { + private static final FoursquareApi INSTANCE = new FoursquareApi(); + } + + public static FoursquareApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "http://foursquare.com/oauth/access_token"; + } + + @Override + public String getRequestTokenEndpoint() { + return "http://foursquare.com/oauth/request_token"; + } + + @Override + public String getAuthorizationBaseUrl() { + return AUTHORIZATION_URL; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/FrappeApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/FrappeApi.java new file mode 100644 index 000000000..ec4cc61f4 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/FrappeApi.java @@ -0,0 +1,42 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.apis.openid.OpenIdJsonTokenExtractor; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.model.OAuth2AccessToken; + +public class FrappeApi extends DefaultApi20 { + + private final String serverURL; + private final String accessTokenEndpoint; + private final String authorizationBaseUrl; + + protected FrappeApi(String serverURL) { + this.serverURL = serverURL; + this.accessTokenEndpoint = serverURL + "/api/method/frappe.integrations.oauth2.get_token"; + this.authorizationBaseUrl = serverURL + "/api/method/frappe.integrations.oauth2.authorize"; + } + + public static FrappeApi instance(String serverUrl) { + return new FrappeApi(serverUrl); + } + + public String getServerURL() { + return serverURL; + } + + @Override + public String getAccessTokenEndpoint() { + return accessTokenEndpoint; + } + + @Override + protected String getAuthorizationBaseUrl() { + return authorizationBaseUrl; + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return OpenIdJsonTokenExtractor.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/FreelancerApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/FreelancerApi.java new file mode 100644 index 000000000..33844d193 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/FreelancerApi.java @@ -0,0 +1,83 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; +import com.github.scribejava.core.builder.api.OAuth1SignatureType; +import com.github.scribejava.core.model.Verb; + +public class FreelancerApi extends DefaultApi10a { + + private static final String AUTHORIZATION_URL = "http://www.freelancer.com/users/api-token/auth.php"; + + protected FreelancerApi() { + } + + private static class InstanceHolder { + private static final FreelancerApi INSTANCE = new FreelancerApi(); + } + + public static FreelancerApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public OAuth1SignatureType getSignatureType() { + return OAuth1SignatureType.QUERY_STRING; + } + + @Override + public String getAccessTokenEndpoint() { + return "http://api.freelancer.com/RequestAccessToken/requestAccessToken.xml?"; + } + + @Override + public String getRequestTokenEndpoint() { + return "http://api.freelancer.com/RequestRequestToken/requestRequestToken.xml"; + } + + @Override + public Verb getAccessTokenVerb() { + return Verb.GET; + } + + @Override + public Verb getRequestTokenVerb() { + return Verb.GET; + } + + @Override + public String getAuthorizationBaseUrl() { + return AUTHORIZATION_URL; + } + + public static class Sandbox extends FreelancerApi { + + private static final String SANDBOX_AUTHORIZATION_URL + = "http://www.sandbox.freelancer.com/users/api-token/auth.php"; + + private Sandbox() { + } + + private static class InstanceHolder { + private static final Sandbox INSTANCE = new Sandbox(); + } + + public static Sandbox instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getRequestTokenEndpoint() { + return "http://api.sandbox.freelancer.com/RequestRequestToken/requestRequestToken.xml"; + } + + @Override + public String getAccessTokenEndpoint() { + return "http://api.sandbox.freelancer.com/RequestAccessToken/requestAccessToken.xml?"; + } + + @Override + public String getAuthorizationBaseUrl() { + return SANDBOX_AUTHORIZATION_URL; + } + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/GeniusApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/GeniusApi.java new file mode 100644 index 000000000..03eae859c --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/GeniusApi.java @@ -0,0 +1,28 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; + +public class GeniusApi extends DefaultApi20 { + + protected GeniusApi() { + } + + private static class InstanceHolder { + + private static final GeniusApi INSTANCE = new GeniusApi(); + } + + public static GeniusApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://api.genius.com/oauth/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://api.genius.com/oauth/authorize"; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/GitHubApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/GitHubApi.java new file mode 100644 index 000000000..ada35c1b3 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/GitHubApi.java @@ -0,0 +1,41 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.OAuth2AccessTokenExtractor; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.Verb; + +public class GitHubApi extends DefaultApi20 { + + protected GitHubApi() { + } + + private static class InstanceHolder { + private static final GitHubApi INSTANCE = new GitHubApi(); + } + + public static GitHubApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public Verb getAccessTokenVerb() { + return Verb.POST; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://github.com/login/oauth/access_token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://github.com/login/oauth/authorize"; + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return OAuth2AccessTokenExtractor.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/GoogleApi20.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/GoogleApi20.java new file mode 100644 index 000000000..e3de4c746 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/GoogleApi20.java @@ -0,0 +1,53 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.apis.google.GoogleDeviceAuthorizationJsonExtractor; +import com.github.scribejava.apis.openid.OpenIdJsonTokenExtractor; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.DeviceAuthorizationJsonExtractor; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.model.OAuth2AccessToken; + +public class GoogleApi20 extends DefaultApi20 { + + protected GoogleApi20() { + } + + private static class InstanceHolder { + + private static final GoogleApi20 INSTANCE = new GoogleApi20(); + } + + public static GoogleApi20 instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://oauth2.googleapis.com/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://accounts.google.com/o/oauth2/v2/auth"; + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return OpenIdJsonTokenExtractor.instance(); + } + + @Override + public String getRevokeTokenEndpoint() { + return "https://oauth2.googleapis.com/revoke"; + } + + @Override + public String getDeviceAuthorizationEndpoint() { + return "https://oauth2.googleapis.com/device/code"; + } + + @Override + public DeviceAuthorizationJsonExtractor getDeviceAuthorizationExtractor() { + return GoogleDeviceAuthorizationJsonExtractor.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/HHApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/HHApi.java new file mode 100644 index 000000000..61476eaef --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/HHApi.java @@ -0,0 +1,35 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +public class HHApi extends DefaultApi20 { + + protected HHApi() { + } + + private static class InstanceHolder { + + private static final HHApi INSTANCE = new HHApi(); + } + + public static HHApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://hh.ru/oauth/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://hh.ru/oauth/authorize"; + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/HiOrgServerApi20.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/HiOrgServerApi20.java new file mode 100644 index 000000000..a69673a25 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/HiOrgServerApi20.java @@ -0,0 +1,44 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; + +/** + * OAuth2 API for HiOrg-Server + * + * @see HiOrg-Server OAuth API documentation + */ +public class HiOrgServerApi20 extends DefaultApi20 { + + private final String version; + + protected HiOrgServerApi20() { + this("v1"); + } + + protected HiOrgServerApi20(String version) { + this.version = version; + } + + private static class InstanceHolder { + + private static final HiOrgServerApi20 INSTANCE = new HiOrgServerApi20(); + } + + public static HiOrgServerApi20 instance() { + return InstanceHolder.INSTANCE; + } + + public static HiOrgServerApi20 customVersion(String version) { + return new HiOrgServerApi20(version); + } + + @Override + public String getAccessTokenEndpoint() { + return "https://www.hiorg-server.de/api/oauth2/" + version + "/token.php"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://www.hiorg-server.de/api/oauth2/" + version + "/authorize.php"; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/ImgurApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/ImgurApi.java new file mode 100644 index 000000000..845fd95cb --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/ImgurApi.java @@ -0,0 +1,70 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.apis.imgur.ImgurOAuthService; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.ParameterList; + +import java.io.OutputStream; +import java.util.Map; + +public class ImgurApi extends DefaultApi20 { + + protected ImgurApi() { + } + + private static class InstanceHolder { + + private static final ImgurApi INSTANCE = new ImgurApi(); + } + + public static ImgurApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://api.imgur.com/oauth2/token"; + } + + @Override + public String getAuthorizationUrl(String responseType, String apiKey, String callback, String scope, String state, + Map additionalParams) { + final ParameterList parameters = new ParameterList(additionalParams); + parameters.add(OAuthConstants.RESPONSE_TYPE, isOob(callback) ? "pin" : "code"); + parameters.add(OAuthConstants.CLIENT_ID, apiKey); + + if (callback != null) { + parameters.add(OAuthConstants.REDIRECT_URI, callback); + } + + if (scope != null) { + parameters.add(OAuthConstants.SCOPE, scope); + } + + if (state != null) { + parameters.add(OAuthConstants.STATE, state); + } + + return parameters.appendTo("https://api.imgur.com/oauth2/authorize"); + } + + @Override + protected String getAuthorizationBaseUrl() { + throw new UnsupportedOperationException("use getAuthorizationUrl instead"); + } + + @Override + public ImgurOAuthService createService(String apiKey, String apiSecret, String callback, String defaultScope, + String responseType, OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, + HttpClient httpClient) { + return new ImgurOAuthService(this, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, + userAgent, httpClientConfig, httpClient); + } + + public static boolean isOob(String callback) { + return OAuthConstants.OOB.equals(callback); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/InstagramApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/InstagramApi.java new file mode 100644 index 000000000..85e408113 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/InstagramApi.java @@ -0,0 +1,59 @@ +package com.github.scribejava.apis; + +import java.io.OutputStream; +import com.github.scribejava.apis.instagram.InstagramAccessTokenJsonExtractor; +import com.github.scribejava.apis.instagram.InstagramService; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +public class InstagramApi extends DefaultApi20 { + + public static final String LONG_LIVED_ACCESS_TOKEN_ENDPOINT = "https://graph.instagram.com/access_token"; + + private static class InstanceHolder { + + private static final InstagramApi INSTANCE = new InstagramApi(); + } + + public static InstagramApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://api.instagram.com/oauth/access_token"; + } + + @Override + public String getRefreshTokenEndpoint() { + return "https://graph.instagram.com/refresh_access_token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://api.instagram.com/oauth/authorize"; + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return InstagramAccessTokenJsonExtractor.instance(); + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } + + @Override + public InstagramService createService(String apiKey, String apiSecret, String callback, String defaultScope, + String responseType, OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, + HttpClient httpClient) { + return new InstagramService(this, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, + userAgent, httpClientConfig, httpClient); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/KaixinApi20.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/KaixinApi20.java new file mode 100644 index 000000000..b94e8e1a3 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/KaixinApi20.java @@ -0,0 +1,43 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; + +/** + * Kaixin(http://www.kaixin001.com/) open platform api based on OAuth 2.0. + */ +public class KaixinApi20 extends DefaultApi20 { + + protected KaixinApi20() { + } + + private static class InstanceHolder { + private static final KaixinApi20 INSTANCE = new KaixinApi20(); + } + + public static KaixinApi20 instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public Verb getAccessTokenVerb() { + return Verb.GET; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://api.kaixin001.com/oauth2/access_token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "http://api.kaixin001.com/oauth2/authorize"; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/KakaoApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/KakaoApi.java new file mode 100644 index 000000000..6587fe32f --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/KakaoApi.java @@ -0,0 +1,35 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +public class KakaoApi extends DefaultApi20 { + + protected KakaoApi() { + } + + private static class InstanceHolder { + + private static final KakaoApi INSTANCE = new KakaoApi(); + } + + public static KakaoApi instance() { + return KakaoApi.InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://kauth.kakao.com/oauth/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://kauth.kakao.com/oauth/authorize"; + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/KeycloakApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/KeycloakApi.java new file mode 100644 index 000000000..ed713b4d0 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/KeycloakApi.java @@ -0,0 +1,63 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.apis.openid.OpenIdJsonTokenExtractor; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.model.OAuth2AccessToken; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +public class KeycloakApi extends DefaultApi20 { + + private static final ConcurrentMap INSTANCES = new ConcurrentHashMap<>(); + + private final String baseUrlWithRealm; + + protected KeycloakApi(String baseUrlWithRealm) { + this.baseUrlWithRealm = baseUrlWithRealm; + } + + public static KeycloakApi instance() { + return instance("http://localhost:8080/", "master"); + } + + public static KeycloakApi instance(String baseUrl, String realm) { + final String defaultBaseUrlWithRealm = composeBaseUrlWithRealm(baseUrl, realm); + + //java8: switch to ConcurrentMap::computeIfAbsent + KeycloakApi api = INSTANCES.get(defaultBaseUrlWithRealm); + if (api == null) { + api = new KeycloakApi(defaultBaseUrlWithRealm); + final KeycloakApi alreadyCreatedApi = INSTANCES.putIfAbsent(defaultBaseUrlWithRealm, api); + if (alreadyCreatedApi != null) { + return alreadyCreatedApi; + } + } + return api; + } + + protected static String composeBaseUrlWithRealm(String baseUrl, String realm) { + return baseUrl + (baseUrl.endsWith("/") ? "" : "/") + "auth/realms/" + realm; + } + + @Override + public String getAccessTokenEndpoint() { + return baseUrlWithRealm + "/protocol/openid-connect/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return baseUrlWithRealm + "/protocol/openid-connect/auth"; + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return OpenIdJsonTokenExtractor.instance(); + } + + @Override + public String getRevokeTokenEndpoint() { + throw new RuntimeException("Not implemented yet"); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/LinkedInApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/LinkedInApi.java new file mode 100644 index 000000000..62258bbec --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/LinkedInApi.java @@ -0,0 +1,51 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; + +public class LinkedInApi extends DefaultApi10a { + + private static final String AUTHORIZE_URL = "https://api.linkedin.com/uas/oauth/authenticate"; + private static final String REQUEST_TOKEN_URL = "https://api.linkedin.com/uas/oauth/requestToken"; + + private final String scopesAsString; + + protected LinkedInApi() { + scopesAsString = null; + } + + protected LinkedInApi(String... scopes) { + final StringBuilder builder = new StringBuilder(); + for (String scope : scopes) { + builder.append('+').append(scope); + } + scopesAsString = "?scope=" + builder.substring(1); + } + + private static class InstanceHolder { + + private static final LinkedInApi INSTANCE = new LinkedInApi(); + } + + public static LinkedInApi instance() { + return InstanceHolder.INSTANCE; + } + + public static LinkedInApi instance(String... scopes) { + return scopes == null || scopes.length == 0 ? instance() : new LinkedInApi(scopes); + } + + @Override + public String getAccessTokenEndpoint() { + return "https://api.linkedin.com/uas/oauth/accessToken"; + } + + @Override + public String getRequestTokenEndpoint() { + return scopesAsString == null ? REQUEST_TOKEN_URL : REQUEST_TOKEN_URL + scopesAsString; + } + + @Override + public String getAuthorizationBaseUrl() { + return AUTHORIZE_URL; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/LinkedInApi20.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/LinkedInApi20.java new file mode 100644 index 000000000..36d4ab702 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/LinkedInApi20.java @@ -0,0 +1,34 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +public class LinkedInApi20 extends DefaultApi20 { + + protected LinkedInApi20() { + } + + private static class InstanceHolder { + private static final LinkedInApi20 INSTANCE = new LinkedInApi20(); + } + + public static LinkedInApi20 instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://www.linkedin.com/oauth/v2/accessToken"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://www.linkedin.com/oauth/v2/authorization"; + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/LiveApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/LiveApi.java new file mode 100644 index 000000000..7a0a64ea5 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/LiveApi.java @@ -0,0 +1,34 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; + +public class LiveApi extends DefaultApi20 { + + protected LiveApi() { + } + + private static class InstanceHolder { + private static final LiveApi INSTANCE = new LiveApi(); + } + + public static LiveApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://login.live.com/oauth20_token.srf"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://login.live.com/oauth20_authorize.srf"; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/MailruApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/MailruApi.java new file mode 100644 index 000000000..b48091594 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/MailruApi.java @@ -0,0 +1,41 @@ +package com.github.scribejava.apis; + +import java.io.OutputStream; + +import com.github.scribejava.apis.mailru.MailruOAuthService; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; + +public class MailruApi extends DefaultApi20 { + + protected MailruApi() { + } + + private static class InstanceHolder { + + private static final MailruApi INSTANCE = new MailruApi(); + } + + public static MailruApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://connect.mail.ru/oauth/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://connect.mail.ru/oauth/authorize"; + } + + @Override + public MailruOAuthService createService(String apiKey, String apiSecret, String callback, String defaultScope, + String responseType, OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, + HttpClient httpClient) { + return new MailruOAuthService(this, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, + userAgent, httpClientConfig, httpClient); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/MediaWikiApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/MediaWikiApi.java new file mode 100644 index 000000000..3bb18001d --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/MediaWikiApi.java @@ -0,0 +1,77 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; + +public class MediaWikiApi extends DefaultApi10a { + + private static class InstanceHolder { + + private static final MediaWikiApi INSTANCE = new MediaWikiApi( + "https://meta.wikimedia.org/w/index.php", + "https://meta.wikimedia.org/wiki/" + ); + } + + private static class BetaInstanceHolder { + + private static final MediaWikiApi BETA_INSTANCE = new MediaWikiApi( + "https://meta.wikimedia.beta.wmflabs.org/w/index.php", + "https://meta.wikimedia.beta.wmflabs.org/wiki/" + ); + } + + private final String indexUrl; + private final String niceUrlBase; + + /** + * @param indexUrl The URL to the index.php of the wiki. Due to a + * MediaWiki bug, some requests must currently use the non-nice URL. + * @param niceUrlBase The base of nice URLs for the wiki, including the trailing slash. Due to + * another MediaWiki bug, some requests must currently use + * the nice URL. + */ + public MediaWikiApi(String indexUrl, String niceUrlBase) { + this.indexUrl = indexUrl; + this.niceUrlBase = niceUrlBase; + } + + /** + * The instance for wikis hosted by the Wikimedia Foundation. Consumers are requested on + * + * Special:OAuthConsumerRegistration/propose + * . + * + * @return instance + */ + public static MediaWikiApi instance() { + return InstanceHolder.INSTANCE; + } + + /** + * The instance for wikis in the Wikimedia Foundation’s Beta Cluster. Consumers are requested on + * + * Special:OAuthConsumerRegistration/propose + * . + * + * @return instanceBeta + */ + public static MediaWikiApi instanceBeta() { + return BetaInstanceHolder.BETA_INSTANCE; + } + + @Override + public String getRequestTokenEndpoint() { + return indexUrl + "?title=Special:OAuth/initiate"; + } + + @Override + public String getAuthorizationBaseUrl() { + return niceUrlBase + "Special:OAuth/authorize"; + } + + @Override + public String getAccessTokenEndpoint() { + return indexUrl + "?title=Special:OAuth/token"; + } + +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/MeetupApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/MeetupApi.java new file mode 100644 index 000000000..b2acc5680 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/MeetupApi.java @@ -0,0 +1,37 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; + +/** + * OAuth access to the Meetup.com API. For more information visit http://www.meetup.com/api + */ +public class MeetupApi extends DefaultApi10a { + + private static final String AUTHORIZE_URL = "http://www.meetup.com/authenticate"; + + protected MeetupApi() { + } + + private static class InstanceHolder { + private static final MeetupApi INSTANCE = new MeetupApi(); + } + + public static MeetupApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getRequestTokenEndpoint() { + return "http://api.meetup.com/oauth/request/"; + } + + @Override + public String getAccessTokenEndpoint() { + return "http://api.meetup.com/oauth/access/"; + } + + @Override + public String getAuthorizationBaseUrl() { + return AUTHORIZE_URL; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/MeetupApi20.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/MeetupApi20.java new file mode 100644 index 000000000..ce09e931d --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/MeetupApi20.java @@ -0,0 +1,34 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +public class MeetupApi20 extends DefaultApi20 { + + protected MeetupApi20() { + } + + private static class InstanceHolder { + private static final MeetupApi20 INSTANCE = new MeetupApi20(); + } + + public static MeetupApi20 instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://secure.meetup.com/oauth2/access"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://secure.meetup.com/oauth2/authorize"; + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/MicrosoftAzureActiveDirectory20Api.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/MicrosoftAzureActiveDirectory20Api.java new file mode 100644 index 000000000..399cf54c9 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/MicrosoftAzureActiveDirectory20Api.java @@ -0,0 +1,48 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.apis.microsoftazureactivedirectory.BaseMicrosoftAzureActiveDirectoryApi; +import com.github.scribejava.apis.microsoftazureactivedirectory.MicrosoftAzureActiveDirectory20BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; + +/** + * Microsoft Azure Active Directory Api v 2.0 + * + * @see + * Understand the OAuth 2.0 authorization code flow in Azure AD | Microsoft Docs + * @see + * Microsoft Graph REST API v1.0 reference + * @see https://portal.azure.com + */ +public class MicrosoftAzureActiveDirectory20Api extends BaseMicrosoftAzureActiveDirectoryApi { + + protected MicrosoftAzureActiveDirectory20Api() { + this(COMMON_TENANT); + } + + protected MicrosoftAzureActiveDirectory20Api(String tenant) { + super(tenant); + } + + private static class InstanceHolder { + + private static final MicrosoftAzureActiveDirectory20Api INSTANCE = new MicrosoftAzureActiveDirectory20Api(); + } + + public static MicrosoftAzureActiveDirectory20Api instance() { + return InstanceHolder.INSTANCE; + } + + public static MicrosoftAzureActiveDirectory20Api custom(String tenant) { + return new MicrosoftAzureActiveDirectory20Api(tenant); + } + + @Override + public BearerSignature getBearerSignature() { + return MicrosoftAzureActiveDirectory20BearerSignature.instance(); + } + + @Override + protected String getEndpointVersionPath() { + return "/v2.0"; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/MicrosoftAzureActiveDirectoryApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/MicrosoftAzureActiveDirectoryApi.java new file mode 100644 index 000000000..9ab4aa291 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/MicrosoftAzureActiveDirectoryApi.java @@ -0,0 +1,64 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.apis.microsoftazureactivedirectory.BaseMicrosoftAzureActiveDirectoryApi; +import com.github.scribejava.apis.microsoftazureactivedirectory.MicrosoftAzureActiveDirectoryBearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; + +/** + * Microsoft Azure Active Directory Api + * + * @see + * Understand the OAuth 2.0 authorization code flow in Azure AD | Microsoft Docs + * @see + * Azure AD Java web app Getting Started | Microsoft Docs + * @see + * Azure AD Graph API Operations on the Signed-in User + * @see https://portal.azure.com + */ +public class MicrosoftAzureActiveDirectoryApi extends BaseMicrosoftAzureActiveDirectoryApi { + + private final String resource; + + protected MicrosoftAzureActiveDirectoryApi() { + this(COMMON_TENANT, null); + } + + protected MicrosoftAzureActiveDirectoryApi(String tenant, String resource) { + super(tenant); + this.resource = resource; + } + + private static class InstanceHolder { + + private static final MicrosoftAzureActiveDirectoryApi INSTANCE = new MicrosoftAzureActiveDirectoryApi(); + } + + public static MicrosoftAzureActiveDirectoryApi instance() { + return InstanceHolder.INSTANCE; + } + + public static MicrosoftAzureActiveDirectoryApi customTenant(String tenant) { + return new MicrosoftAzureActiveDirectoryApi(tenant, null); + } + + public static MicrosoftAzureActiveDirectoryApi customResource(String resource) { + return new MicrosoftAzureActiveDirectoryApi(COMMON_TENANT, resource); + } + + public static MicrosoftAzureActiveDirectoryApi custom(String tenant, String resource) { + return new MicrosoftAzureActiveDirectoryApi(tenant, resource); + } + + @Override + protected String getAuthorizationBaseUrl() { + final String authorizationBaseUrl = super.getAuthorizationBaseUrl(); + return resource == null || resource.isEmpty() ? authorizationBaseUrl + : authorizationBaseUrl + "?resource=" + resource; + } + + @Override + public BearerSignature getBearerSignature() { + return MicrosoftAzureActiveDirectoryBearerSignature.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/MisfitApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/MisfitApi.java new file mode 100644 index 000000000..051de70c1 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/MisfitApi.java @@ -0,0 +1,35 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; + +public class MisfitApi extends DefaultApi20 { + + protected MisfitApi() { + } + + private static class InstanceHolder { + + private static final MisfitApi INSTANCE = new MisfitApi(); + } + + public static MisfitApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://api.misfitwearables.com/auth/tokens/exchange"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://api.misfitwearables.com/auth/dialog/authorize"; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/NaverApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/NaverApi.java new file mode 100644 index 000000000..f60871735 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/NaverApi.java @@ -0,0 +1,33 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; + +public class NaverApi extends DefaultApi20 { + protected NaverApi() { + } + + private static class InstanceHolder { + private static final NaverApi INSTANCE = new NaverApi(); + } + + public static NaverApi instance() { + return NaverApi.InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://nid.naver.com/oauth2.0/token?grant_type=authorization_code"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://nid.naver.com/oauth2.0/authorize"; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/OdnoklassnikiApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/OdnoklassnikiApi.java new file mode 100644 index 000000000..b87eaa072 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/OdnoklassnikiApi.java @@ -0,0 +1,55 @@ +package com.github.scribejava.apis; + +import java.io.OutputStream; + +import com.github.scribejava.apis.odnoklassniki.OdnoklassnikiOAuthService; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +public class OdnoklassnikiApi extends DefaultApi20 { + + protected OdnoklassnikiApi() { + } + + private static class InstanceHolder { + + private static final OdnoklassnikiApi INSTANCE = new OdnoklassnikiApi(); + } + + public static OdnoklassnikiApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://api.ok.ru/oauth/token.do"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://connect.ok.ru/oauth/authorize"; + } + + @Override + public OdnoklassnikiOAuthService createService(String apiKey, String apiSecret, String callback, + String defaultScope, String responseType, OutputStream debugStream, String userAgent, + HttpClientConfig httpClientConfig, HttpClient httpClient) { + return new OdnoklassnikiOAuthService(this, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, + userAgent, httpClientConfig, httpClient); + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/PinterestApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/PinterestApi.java new file mode 100644 index 000000000..70ef1caff --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/PinterestApi.java @@ -0,0 +1,34 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +public class PinterestApi extends DefaultApi20 { + + protected PinterestApi() { + } + + private static class InstanceHolder { + private static final PinterestApi INSTANCE = new PinterestApi(); + } + + public static PinterestApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://api.pinterest.com/v1/oauth/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://api.pinterest.com/oauth"; + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/PolarAPI.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/PolarAPI.java new file mode 100644 index 000000000..01e1651c6 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/PolarAPI.java @@ -0,0 +1,53 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.apis.polar.PolarJsonTokenExtractor; +import com.github.scribejava.apis.polar.PolarOAuthService; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.OAuth2AccessToken; + +import java.io.OutputStream; + +/** + * Polar's OAuth2 client's implementation source: https://www.polar.com/accesslink-api/#authentication + */ +public class PolarAPI extends DefaultApi20 { + + protected PolarAPI() { + } + + private static class InstanceHolder { + + private static final PolarAPI INSTANCE = new PolarAPI(); + } + + public static PolarAPI instance() { + return PolarAPI.InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://polarremote.com/v2/oauth2/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://flow.polar.com/oauth2/authorization"; + } + + @Override + public PolarOAuthService createService(String apiKey, String apiSecret, String callback, String defaultScope, + String responseType, OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, + HttpClient httpClient) { + + return new PolarOAuthService(this, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, + userAgent, httpClientConfig, httpClient); + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return PolarJsonTokenExtractor.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/Px500Api.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/Px500Api.java new file mode 100644 index 000000000..91e34a449 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/Px500Api.java @@ -0,0 +1,34 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; + +public class Px500Api extends DefaultApi10a { + + private static final String AUTHORIZATION_URL = "https://api.500px.com/v1/oauth/authorize"; + + protected Px500Api() { + } + + private static class InstanceHolder { + private static final Px500Api INSTANCE = new Px500Api(); + } + + public static Px500Api instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://api.500px.com/v1/oauth/access_token"; + } + + @Override + public String getRequestTokenEndpoint() { + return "https://api.500px.com/v1/oauth/request_token"; + } + + @Override + public String getAuthorizationBaseUrl() { + return AUTHORIZATION_URL; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/RenrenApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/RenrenApi.java new file mode 100644 index 000000000..d4ade9fad --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/RenrenApi.java @@ -0,0 +1,43 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; + +/** + * Renren(http://www.renren.com/) OAuth 2.0 based api. + */ +public class RenrenApi extends DefaultApi20 { + + protected RenrenApi() { + } + + private static class InstanceHolder { + private static final RenrenApi INSTANCE = new RenrenApi(); + } + + public static RenrenApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public Verb getAccessTokenVerb() { + return Verb.GET; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://graph.renren.com/oauth/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://graph.renren.com/oauth/authorize"; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/SalesforceApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/SalesforceApi.java new file mode 100644 index 000000000..8760a7fff --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/SalesforceApi.java @@ -0,0 +1,130 @@ +package com.github.scribejava.apis; + +import javax.net.ssl.SSLContext; + +import com.github.scribejava.apis.salesforce.SalesforceJsonTokenExtractor; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import javax.net.ssl.SSLSocket; + +/** + * This class is an implementation of the Salesforce OAuth2 API. + * + * The default implementation connects to the Salesforce production environment. If you want to connect to a Sandbox + * environment you've to use {@link #sandbox()} method to get sandbox instance of this API + */ +public class SalesforceApi extends DefaultApi20 { + + private static final String PRODUCTION_HOST = "login.salesforce.com"; + private static final String SANDBOX_HOST = "test.salesforce.com"; + private static final String PROTOCOL = "https://"; + private static final String ACCESS_PATH = "/services/oauth2/token"; + private static final String AUTHORIZE_PATH = "/services/oauth2/authorize"; + + private final String accessTokenUrl; + private final String authorizationBaseUrl; + + /** + * @param hostName The hostname to be used, which is either {@link #PRODUCTION_HOST} or {@link #SANDBOX_HOST}. + */ + protected SalesforceApi(String hostName) { + accessTokenUrl = PROTOCOL + hostName + ACCESS_PATH; + authorizationBaseUrl = PROTOCOL + hostName + AUTHORIZE_PATH; + try { + final SSLSocket socket = (SSLSocket) SSLContext.getDefault().getSocketFactory().createSocket(); + if (!isTLSv11orUpperEnabled(socket)) { + throw new IllegalStateException("Salesforce API required to use TLSv1.1 or upper. " + + "Enabled it by invoking method initTLSv11orUpper or somehow else"); + } + } catch (NoSuchAlgorithmException | IOException ex) { + throw new IllegalStateException("Salesforce API required to use TLSv1.1 or upper. " + + "Enabled it by invoking method initTLSv11orUpper or somehow else"); + } + } + + private static class InstanceHolder { + + private static final SalesforceApi INSTANCE = new SalesforceApi(PRODUCTION_HOST); + } + + public static SalesforceApi instance() { + return InstanceHolder.INSTANCE; + } + + public static SalesforceApi sandbox() { + return new SalesforceApi(SANDBOX_HOST); + } + + @Override + public Verb getAccessTokenVerb() { + return Verb.POST; + } + + @Override + public String getAccessTokenEndpoint() { + return accessTokenUrl; + } + + @Override + protected String getAuthorizationBaseUrl() { + return authorizationBaseUrl; + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return SalesforceJsonTokenExtractor.instance(); + } + + private static boolean isTLSv11orUpperEnabled(final SSLSocket socket) { + for (String protocol : socket.getEnabledProtocols()) { + if (protocol.startsWith("TLSv1.")) { + return true; + } + } + return false; + } + + /** + * Salesforce API requires to use TLSv1.1 or upper. + *

+ * Java 8 have TLS 1.2 enabled by default. java 7 - no, you should invoke this method or turn TLS>=1.1 somehow + * else

+ * + * @throws java.security.NoSuchAlgorithmException in case your jvm doesn't support TLSv1.1 or higher + * @throws java.security.KeyManagementException unexpected Exception from + * {@link SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom)} + * @throws java.io.IOException unexpected Exception from {@link javax.net.ssl.SSLSocketFactory#createSocket()} + */ + public static void initTLSv11orUpper() throws NoSuchAlgorithmException, KeyManagementException, IOException { + final SSLSocket socket = (SSLSocket) SSLContext.getDefault().getSocketFactory().createSocket(); + if (isTLSv11orUpperEnabled(socket)) { + return; + } + final String[] supportedProtocols = socket.getSupportedProtocols(); + Arrays.sort(supportedProtocols); + for (int i = supportedProtocols.length - 1; i >= 0; i--) { + final String supportedProtocol = supportedProtocols[i]; + if (supportedProtocol.startsWith("TLSv1.")) { + final SSLContext context = SSLContext.getInstance(supportedProtocol); + context.init(null, null, null); + SSLContext.setDefault(context); + return; + } + } + + throw new NoSuchAlgorithmException("for Salesforce API to work you need jvm with TLS 1.1 or higher support"); + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/SinaWeiboApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/SinaWeiboApi.java new file mode 100644 index 000000000..9d69a9afc --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/SinaWeiboApi.java @@ -0,0 +1,36 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; + +public class SinaWeiboApi extends DefaultApi10a { + + private static final String REQUEST_TOKEN_URL = "http://api.t.sina.com.cn/oauth/request_token"; + private static final String ACCESS_TOKEN_URL = "http://api.t.sina.com.cn/oauth/access_token"; + private static final String AUTHORIZE_URL = "http://api.t.sina.com.cn/oauth/authorize"; + + protected SinaWeiboApi() { + } + + private static class InstanceHolder { + private static final SinaWeiboApi INSTANCE = new SinaWeiboApi(); + } + + public static SinaWeiboApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getRequestTokenEndpoint() { + return REQUEST_TOKEN_URL; + } + + @Override + public String getAccessTokenEndpoint() { + return ACCESS_TOKEN_URL; + } + + @Override + public String getAuthorizationBaseUrl() { + return AUTHORIZE_URL; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/SinaWeiboApi20.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/SinaWeiboApi20.java new file mode 100644 index 000000000..19aa9f356 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/SinaWeiboApi20.java @@ -0,0 +1,37 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; + +/** + * SinaWeibo OAuth 2.0 api. + */ +public class SinaWeiboApi20 extends DefaultApi20 { + + protected SinaWeiboApi20() { + } + + private static class InstanceHolder { + private static final SinaWeiboApi20 INSTANCE = new SinaWeiboApi20(); + } + + public static SinaWeiboApi20 instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://api.weibo.com/oauth2/access_token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://api.weibo.com/oauth2/authorize"; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/SkyrockApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/SkyrockApi.java new file mode 100644 index 000000000..beb956a4a --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/SkyrockApi.java @@ -0,0 +1,42 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; + +/** + * OAuth API for Skyrock. + * + * @see Skyrock.com API + */ +public class SkyrockApi extends DefaultApi10a { + + private static final String API_ENDPOINT = "https://api.skyrock.com/v2"; + private static final String REQUEST_TOKEN_RESOURCE = "/oauth/initiate"; + private static final String AUTHORIZE_URL = "/oauth/authorize"; + private static final String ACCESS_TOKEN_RESOURCE = "/oauth/token"; + + protected SkyrockApi() { + } + + private static class InstanceHolder { + private static final SkyrockApi INSTANCE = new SkyrockApi(); + } + + public static SkyrockApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return API_ENDPOINT + ACCESS_TOKEN_RESOURCE; + } + + @Override + public String getRequestTokenEndpoint() { + return API_ENDPOINT + REQUEST_TOKEN_RESOURCE; + } + + @Override + public String getAuthorizationBaseUrl() { + return API_ENDPOINT + AUTHORIZE_URL; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/SlackApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/SlackApi.java new file mode 100644 index 000000000..4d834fff1 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/SlackApi.java @@ -0,0 +1,37 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.apis.slack.SlackJsonTokenExtractor; +import com.github.scribejava.core.builder.api.DefaultApi20; + +/** + * Slack.com API + */ +public class SlackApi extends DefaultApi20 { + + protected SlackApi() { + } + + private static class InstanceHolder { + + private static final SlackApi INSTANCE = new SlackApi(); + } + + public static SlackApi instance() { + return SlackApi.InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://slack.com/api/oauth.v2.access"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://slack.com/oauth/v2/authorize"; + } + + @Override + public SlackJsonTokenExtractor getAccessTokenExtractor() { + return SlackJsonTokenExtractor.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/StackExchangeApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/StackExchangeApi.java new file mode 100644 index 000000000..3ba195460 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/StackExchangeApi.java @@ -0,0 +1,46 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.OAuth2AccessTokenExtractor; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; + +/** + * Stack Exchange authentication via OAuth 2.0 (stackoverflow.com, + * askubuntu.com, etc.). + */ +public class StackExchangeApi extends DefaultApi20 { + + protected StackExchangeApi() { + } + + private static class InstanceHolder { + private static final StackExchangeApi INSTANCE = new StackExchangeApi(); + } + + public static StackExchangeApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://stackexchange.com/oauth/access_token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://stackexchange.com/oauth"; + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return OAuth2AccessTokenExtractor.instance(); + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/TheThingsNetworkV1StagingApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/TheThingsNetworkV1StagingApi.java new file mode 100644 index 000000000..844d75758 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/TheThingsNetworkV1StagingApi.java @@ -0,0 +1,27 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; + +public class TheThingsNetworkV1StagingApi extends DefaultApi20 { + + protected TheThingsNetworkV1StagingApi() { + } + + private static class InstanceHolder { + private static final TheThingsNetworkV1StagingApi INSTANCE = new TheThingsNetworkV1StagingApi(); + } + + public static TheThingsNetworkV1StagingApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://account.thethingsnetwork.org/users/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://account.thethingsnetwork.org/users/authorize"; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/TheThingsNetworkV2PreviewApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/TheThingsNetworkV2PreviewApi.java new file mode 100644 index 000000000..1ac5437a0 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/TheThingsNetworkV2PreviewApi.java @@ -0,0 +1,27 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; + +public class TheThingsNetworkV2PreviewApi extends DefaultApi20 { + + protected TheThingsNetworkV2PreviewApi() { + } + + private static class InstanceHolder { + private static final TheThingsNetworkV2PreviewApi INSTANCE = new TheThingsNetworkV2PreviewApi(); + } + + public static TheThingsNetworkV2PreviewApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://preview.account.thethingsnetwork.org/users/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://preview.account.thethingsnetwork.org/users/authorize"; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/TrelloApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/TrelloApi.java new file mode 100644 index 000000000..438f57402 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/TrelloApi.java @@ -0,0 +1,35 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; + +public class TrelloApi extends DefaultApi10a { + + private static final String AUTHORIZE_URL = "https://trello.com/1/OAuthAuthorizeToken"; + + protected TrelloApi() { + } + + private static class InstanceHolder { + private static final TrelloApi INSTANCE = new TrelloApi(); + } + + public static TrelloApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://trello.com/1/OAuthGetAccessToken"; + } + + @Override + public String getRequestTokenEndpoint() { + return "https://trello.com/1/OAuthGetRequestToken"; + } + + @Override + public String getAuthorizationBaseUrl() { + return AUTHORIZE_URL; + } + +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/TumblrApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/TumblrApi.java new file mode 100644 index 000000000..111bf3342 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/TumblrApi.java @@ -0,0 +1,36 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; + +public class TumblrApi extends DefaultApi10a { + + private static final String AUTHORIZE_URL = "https://www.tumblr.com/oauth/authorize"; + private static final String REQUEST_TOKEN_RESOURCE = "https://www.tumblr.com/oauth/request_token"; + private static final String ACCESS_TOKEN_RESOURCE = "https://www.tumblr.com/oauth/access_token"; + + protected TumblrApi() { + } + + private static class InstanceHolder { + private static final TumblrApi INSTANCE = new TumblrApi(); + } + + public static TumblrApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return ACCESS_TOKEN_RESOURCE; + } + + @Override + public String getRequestTokenEndpoint() { + return REQUEST_TOKEN_RESOURCE; + } + + @Override + public String getAuthorizationBaseUrl() { + return AUTHORIZE_URL; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/TutByApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/TutByApi.java new file mode 100644 index 000000000..41f71b307 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/TutByApi.java @@ -0,0 +1,34 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.apis.tutby.TutByBearerSignature; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; + +public class TutByApi extends DefaultApi20 { + + protected TutByApi() { + } + + private static class InstanceHolder { + private static final TutByApi INSTANCE = new TutByApi(); + } + + public static TutByApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "http://profile.tut.by/getToken"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "http://profile.tut.by/auth"; + } + + @Override + public BearerSignature getBearerSignature() { + return TutByBearerSignature.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/TwitterApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/TwitterApi.java new file mode 100644 index 000000000..d18c22b16 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/TwitterApi.java @@ -0,0 +1,62 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; + +public class TwitterApi extends DefaultApi10a { + + private static final String AUTHORIZE_URL = "https://api.twitter.com/oauth/authorize"; + private static final String REQUEST_TOKEN_RESOURCE = "api.twitter.com/oauth/request_token"; + private static final String ACCESS_TOKEN_RESOURCE = "api.twitter.com/oauth/access_token"; + + protected TwitterApi() { + } + + private static class InstanceHolder { + private static final TwitterApi INSTANCE = new TwitterApi(); + } + + public static TwitterApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://" + ACCESS_TOKEN_RESOURCE; + } + + @Override + public String getRequestTokenEndpoint() { + return "https://" + REQUEST_TOKEN_RESOURCE; + } + + @Override + public String getAuthorizationBaseUrl() { + return AUTHORIZE_URL; + } + + /** + * Twitter 'friendlier' authorization endpoint for OAuth. + * + * Uses SSL. + */ + public static class Authenticate extends TwitterApi { + + private static final String AUTHENTICATE_URL = "https://api.twitter.com/oauth/authenticate"; + + private Authenticate() { + } + + private static class InstanceHolder { + private static final Authenticate INSTANCE = new Authenticate(); + } + + public static Authenticate instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAuthorizationBaseUrl() { + return AUTHENTICATE_URL; + } + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/UcozApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/UcozApi.java new file mode 100644 index 000000000..1a8992704 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/UcozApi.java @@ -0,0 +1,48 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.extractors.OAuth1AccessTokenJSONExtractor; +import com.github.scribejava.core.extractors.OAuth1RequestTokenJSONExtractor; +import com.github.scribejava.core.builder.api.DefaultApi10a; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; + +public class UcozApi extends DefaultApi10a { + private static final String AUTHORIZE_URL = "http://uapi.ucoz.com/accounts/oauthauthorizetoken"; + + protected UcozApi() { + } + + private static class InstanceHolder { + private static final UcozApi INSTANCE = new UcozApi(); + } + + public static UcozApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint(){ + return "http://uapi.ucoz.com/accounts/oauthgetaccesstoken"; + } + + @Override + public String getRequestTokenEndpoint() { + return "http://uapi.ucoz.com/accounts/oauthgetrequesttoken"; + } + + @Override + public String getAuthorizationBaseUrl() { + return AUTHORIZE_URL; + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return OAuth1AccessTokenJSONExtractor.instance(); + } + + @Override + public TokenExtractor getRequestTokenExtractor() { + return OAuth1RequestTokenJSONExtractor.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/ViadeoApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/ViadeoApi.java new file mode 100644 index 000000000..fb70de258 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/ViadeoApi.java @@ -0,0 +1,40 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; + +public class ViadeoApi extends DefaultApi20 { + + protected ViadeoApi() { + } + + private static class InstanceHolder { + private static final ViadeoApi INSTANCE = new ViadeoApi(); + } + + public static ViadeoApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public Verb getAccessTokenVerb() { + return Verb.GET; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://secure.viadeo.com/oauth-provider/access_token2"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://secure.viadeo.com/oauth-provider/authorize2"; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/VkontakteApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/VkontakteApi.java new file mode 100644 index 000000000..dfc96275b --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/VkontakteApi.java @@ -0,0 +1,58 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.apis.vk.VKJsonTokenExtractor; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +public class VkontakteApi extends DefaultApi20 { + + public static final String VERSION = "5.92"; + + protected VkontakteApi() { + } + + private static class InstanceHolder { + + private static final VkontakteApi INSTANCE = new VkontakteApi(); + } + + public static VkontakteApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public Verb getAccessTokenVerb() { + return Verb.GET; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://oauth.vk.com/access_token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://oauth.vk.com/authorize?v=" + VERSION; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return VKJsonTokenExtractor.instance(); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/WunderlistAPI.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/WunderlistAPI.java new file mode 100644 index 000000000..abf19db92 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/WunderlistAPI.java @@ -0,0 +1,58 @@ +package com.github.scribejava.apis; + +import java.io.OutputStream; + +import com.github.scribejava.apis.wunderlist.WunderlistOAuthService; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +/** + * Wunderlist.com Api + */ +public class WunderlistAPI extends DefaultApi20 { + + protected WunderlistAPI() { + } + + private static class InstanceHolder { + + private static final WunderlistAPI INSTANCE = new WunderlistAPI(); + } + + public static WunderlistAPI instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://www.wunderlist.com/oauth/access_token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://www.wunderlist.com/oauth/authorize"; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } + + @Override + public WunderlistOAuthService createService(String apiKey, String apiSecret, String callback, String defaultScope, + String responseType, OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, + HttpClient httpClient) { + return new WunderlistOAuthService(this, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, + userAgent, httpClientConfig, httpClient); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/XeroApi20.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/XeroApi20.java new file mode 100644 index 000000000..2141ed007 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/XeroApi20.java @@ -0,0 +1,31 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; + +/** + * Xero.com Api + */ +public class XeroApi20 extends DefaultApi20 { + + protected XeroApi20() { + } + + private static class InstanceHolder { + + private static final XeroApi20 INSTANCE = new XeroApi20(); + } + + public static XeroApi20 instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://identity.xero.com/connect/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://login.xero.com/identity/connect/authorize"; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/XingApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/XingApi.java new file mode 100755 index 000000000..b83da3679 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/XingApi.java @@ -0,0 +1,35 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; + +public class XingApi extends DefaultApi10a { + + private static final String AUTHORIZE_URL = "https://api.xing.com/v1/authorize"; + + protected XingApi() { + } + + private static class InstanceHolder { + private static final XingApi INSTANCE = new XingApi(); + } + + public static XingApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://api.xing.com/v1/access_token"; + } + + @Override + public String getRequestTokenEndpoint() { + return "https://api.xing.com/v1/request_token"; + } + + @Override + public String getAuthorizationBaseUrl() { + return AUTHORIZE_URL; + } + +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/YahooApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/YahooApi.java new file mode 100644 index 000000000..6f3be2038 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/YahooApi.java @@ -0,0 +1,34 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi10a; + +public class YahooApi extends DefaultApi10a { + + private static final String AUTHORIZE_URL = "https://api.login.yahoo.com/oauth/v2/request_auth"; + + protected YahooApi() { + } + + private static class InstanceHolder { + private static final YahooApi INSTANCE = new YahooApi(); + } + + public static YahooApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://api.login.yahoo.com/oauth/v2/get_token"; + } + + @Override + public String getRequestTokenEndpoint() { + return "https://api.login.yahoo.com/oauth/v2/get_request_token"; + } + + @Override + public String getAuthorizationBaseUrl() { + return AUTHORIZE_URL; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/YahooApi20.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/YahooApi20.java new file mode 100644 index 000000000..bc50f6779 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/YahooApi20.java @@ -0,0 +1,27 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.core.builder.api.DefaultApi20; + +public class YahooApi20 extends DefaultApi20 { + + protected YahooApi20() { + } + + private static class InstanceHolder { + private static final YahooApi20 INSTANCE = new YahooApi20(); + } + + public static YahooApi20 instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://api.login.yahoo.com/oauth2/get_token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://api.login.yahoo.com/oauth2/request_auth"; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/facebook/FacebookAccessTokenErrorResponse.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/facebook/FacebookAccessTokenErrorResponse.java new file mode 100644 index 000000000..ea5053931 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/facebook/FacebookAccessTokenErrorResponse.java @@ -0,0 +1,99 @@ +package com.github.scribejava.apis.facebook; + +import com.github.scribejava.core.model.OAuthResponseException; +import com.github.scribejava.core.model.Response; +import java.io.IOException; +import java.util.Objects; + +/** + * non standard Facebook replace for {@link com.github.scribejava.core.model.OAuth2AccessTokenErrorResponse} + * + * examples:
+ * + * '{"error":{"message":"This authorization code has been + * used.","type":"OAuthException","code":100,"fbtrace_id":"DtxvtGRaxbB"}}'
+ * + * '{"error":{"message":"Error validating application. Invalid application + * ID.","type":"OAuthException","code":101,"fbtrace_id":"CvDR+X4WWIx"}}' + */ +public class FacebookAccessTokenErrorResponse extends OAuthResponseException { + + private static final long serialVersionUID = -1277129766099856895L; + + private final String errorMessage; + private final String type; + private final int codeInt; + private final String fbtraceId; + + public FacebookAccessTokenErrorResponse(String errorMessage, String type, int code, String fbtraceId, + Response response) + throws IOException { + super(response); + this.errorMessage = errorMessage; + this.type = type; + this.codeInt = code; + this.fbtraceId = fbtraceId; + } + + public String getErrorMessage() { + return errorMessage; + } + + public String getType() { + return type; + } + + public int getCodeInt() { + return codeInt; + } + + public String getFbtraceId() { + return fbtraceId; + } + + @Override + public int hashCode() { + int hash = super.hashCode(); + hash = 83 * hash + Objects.hashCode(errorMessage); + hash = 83 * hash + Objects.hashCode(type); + hash = 83 * hash + Objects.hashCode(codeInt); + hash = 83 * hash + Objects.hashCode(fbtraceId); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + if (!super.equals(obj)) { + return false; + } + + final FacebookAccessTokenErrorResponse other = (FacebookAccessTokenErrorResponse) obj; + + if (!Objects.equals(errorMessage, other.getErrorMessage())) { + return false; + } + if (!Objects.equals(type, other.getType())) { + return false; + } + if (codeInt != other.getCodeInt()) { + return false; + } + return Objects.equals(fbtraceId, other.getFbtraceId()); + } + + @Override + public String toString() { + return "FacebookAccessTokenErrorResponse{'type'='" + type + "', 'codeInt'='" + codeInt + + "', 'fbtraceId'='" + fbtraceId + "', 'response'='" + getResponse() + + "', 'errorMessage'='" + errorMessage + "'}"; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/facebook/FacebookAccessTokenJsonExtractor.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/facebook/FacebookAccessTokenJsonExtractor.java new file mode 100644 index 000000000..f51935436 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/facebook/FacebookAccessTokenJsonExtractor.java @@ -0,0 +1,46 @@ +package com.github.scribejava.apis.facebook; + +import com.fasterxml.jackson.databind.JsonNode; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.model.Response; +import java.io.IOException; + +/** + * non standard Facebook Extractor + */ +public class FacebookAccessTokenJsonExtractor extends OAuth2AccessTokenJsonExtractor { + + protected FacebookAccessTokenJsonExtractor() { + } + + private static class InstanceHolder { + + private static final FacebookAccessTokenJsonExtractor INSTANCE = new FacebookAccessTokenJsonExtractor(); + } + + public static FacebookAccessTokenJsonExtractor instance() { + return InstanceHolder.INSTANCE; + } + + /** + * non standard. examples:
+ * + * '{"error":{"message":"This authorization code has been + * used.","type":"OAuthException","code":100,"fbtrace_id":"DtxvtGRaxbB"}}'
+ * + * '{"error":{"message":"Error validating application. Invalid application + * ID.","type":"OAuthException","code":101,"fbtrace_id":"CvDR+X4WWIx"}}' + * + * @param response response + */ + @Override + public void generateError(Response response) throws IOException { + final JsonNode errorNode = OAuth2AccessTokenJsonExtractor.OBJECT_MAPPER + .readTree(response.getBody()) + .get("error"); + + throw new FacebookAccessTokenErrorResponse(errorNode.get("message").asText(), errorNode.get("type").asText(), + errorNode.get("code").asInt(), errorNode.get("fbtrace_id").asText(), response); + } + +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/facebook/FacebookService.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/facebook/FacebookService.java new file mode 100644 index 000000000..efb53a4f3 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/facebook/FacebookService.java @@ -0,0 +1,46 @@ +package com.github.scribejava.apis.facebook; + +import com.github.scribejava.apis.FacebookApi; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.OutputStream; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Formatter; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +public class FacebookService extends OAuth20Service { + + public FacebookService(FacebookApi api, String apiKey, String apiSecret, String callback, String defaultScope, + String responseType, OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, + HttpClient httpClient) { + super(api, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, userAgent, httpClientConfig, + httpClient); + } + + @Override + public void signRequest(String accessToken, OAuthRequest request) { + super.signRequest(accessToken, request); + + final Mac mac; + try { + mac = Mac.getInstance("HmacSHA256"); + final SecretKeySpec secretKey = new SecretKeySpec(getApiSecret().getBytes(), "HmacSHA256"); + mac.init(secretKey); + + final Formatter appsecretProof = new Formatter(); + + for (byte b : mac.doFinal(accessToken.getBytes())) { + appsecretProof.format("%02x", b); + } + + request.addParameter("appsecret_proof", appsecretProof.toString()); + } catch (NoSuchAlgorithmException | InvalidKeyException e) { + throw new IllegalStateException("There is a problem while generating Facebook appsecret_proof.", e); + } + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/fitbit/FitBitJsonTokenExtractor.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/fitbit/FitBitJsonTokenExtractor.java new file mode 100644 index 000000000..24ed6025a --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/fitbit/FitBitJsonTokenExtractor.java @@ -0,0 +1,55 @@ +package com.github.scribejava.apis.fitbit; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.model.OAuth2AccessTokenErrorResponse; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.oauth2.OAuth2Error; +import java.io.IOException; + +public class FitBitJsonTokenExtractor extends OAuth2AccessTokenJsonExtractor { + + protected FitBitJsonTokenExtractor() { + } + + private static class InstanceHolder { + + private static final FitBitJsonTokenExtractor INSTANCE = new FitBitJsonTokenExtractor(); + } + + public static FitBitJsonTokenExtractor instance() { + return InstanceHolder.INSTANCE; + } + + @Override + protected FitBitOAuth2AccessToken createToken(String accessToken, String tokenType, Integer expiresIn, + String refreshToken, String scope, JsonNode response, String rawResponse) { + return new FitBitOAuth2AccessToken(accessToken, tokenType, expiresIn, refreshToken, scope, + response.get("user_id").asText(), rawResponse); + } + + /** + * Related documentation: https://dev.fitbit.com/build/reference/web-api/oauth2/ + */ + @Override + public void generateError(Response response) throws IOException { + final JsonNode errorNode; + try { + errorNode = OAuth2AccessTokenJsonExtractor.OBJECT_MAPPER.readTree(response.getBody()).get("errors").get(0); + } catch (JsonProcessingException ex) { + throw new OAuth2AccessTokenErrorResponse(null, null, null, response); + } + + OAuth2Error errorCode; + try { + errorCode = OAuth2Error + .parseFrom(extractRequiredParameter(errorNode, "errorType", response.getBody()).asText()); + } catch (IllegalArgumentException iaE) { + //non oauth standard error code + errorCode = null; + } + + throw new OAuth2AccessTokenErrorResponse(errorCode, errorNode.get("message").asText(), null, response); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/fitbit/FitBitOAuth2AccessToken.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/fitbit/FitBitOAuth2AccessToken.java new file mode 100644 index 000000000..018128bde --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/fitbit/FitBitOAuth2AccessToken.java @@ -0,0 +1,50 @@ +package com.github.scribejava.apis.fitbit; + +import com.github.scribejava.core.model.OAuth2AccessToken; +import java.util.Objects; + +public class FitBitOAuth2AccessToken extends OAuth2AccessToken { + + private static final long serialVersionUID = -6374486860742407411L; + + private final String userId; + + public FitBitOAuth2AccessToken(String accessToken, String openIdToken, String rawResponse) { + this(accessToken, null, null, null, null, openIdToken, rawResponse); + } + + public FitBitOAuth2AccessToken(String accessToken, String tokenType, Integer expiresIn, String refreshToken, + String scope, String userId, String rawResponse) { + super(accessToken, tokenType, expiresIn, refreshToken, scope, rawResponse); + this.userId = userId; + } + + public String getUserId() { + return userId; + } + + @Override + public int hashCode() { + int hash = super.hashCode(); + hash = 37 * hash + Objects.hashCode(userId); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + if (!super.equals(obj)) { + return false; + } + + return Objects.equals(userId, ((FitBitOAuth2AccessToken) obj).getUserId()); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/google/GoogleDeviceAuthorizationJsonExtractor.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/google/GoogleDeviceAuthorizationJsonExtractor.java new file mode 100644 index 000000000..d3dd77772 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/google/GoogleDeviceAuthorizationJsonExtractor.java @@ -0,0 +1,25 @@ +package com.github.scribejava.apis.google; + +import com.github.scribejava.core.extractors.DeviceAuthorizationJsonExtractor; + +public class GoogleDeviceAuthorizationJsonExtractor extends DeviceAuthorizationJsonExtractor { + + protected GoogleDeviceAuthorizationJsonExtractor() { + } + + private static class InstanceHolder { + + private static final GoogleDeviceAuthorizationJsonExtractor INSTANCE + = new GoogleDeviceAuthorizationJsonExtractor(); + } + + public static GoogleDeviceAuthorizationJsonExtractor instance() { + return GoogleDeviceAuthorizationJsonExtractor.InstanceHolder.INSTANCE; + } + + @Override + protected String getVerificationUriParamName() { + return "verification_url"; + } + +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/imgur/ImgurOAuthService.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/imgur/ImgurOAuthService.java new file mode 100644 index 000000000..317934e35 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/imgur/ImgurOAuthService.java @@ -0,0 +1,53 @@ +package com.github.scribejava.apis.imgur; + +import java.io.OutputStream; + +import com.github.scribejava.apis.ImgurApi; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.oauth.AccessTokenRequestParams; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.core.pkce.PKCE; + +public class ImgurOAuthService extends OAuth20Service { + + public ImgurOAuthService(ImgurApi api, String apiKey, String apiSecret, String callback, String defaultScope, + String responseType, OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, + HttpClient httpClient) { + super(api, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, userAgent, httpClientConfig, + httpClient); + } + + @Override + protected OAuthRequest createAccessTokenRequest(AccessTokenRequestParams params) { + final DefaultApi20 api = getApi(); + final OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint()); + request.addBodyParameter(OAuthConstants.CLIENT_ID, getApiKey()); + request.addBodyParameter(OAuthConstants.CLIENT_SECRET, getApiSecret()); + + final String oauthVerifier = params.getCode(); + if (ImgurApi.isOob(getCallback())) { + request.addBodyParameter(OAuthConstants.GRANT_TYPE, "pin"); + request.addBodyParameter("pin", oauthVerifier); + } else { + request.addBodyParameter(OAuthConstants.GRANT_TYPE, OAuthConstants.AUTHORIZATION_CODE); + request.addBodyParameter(OAuthConstants.CODE, oauthVerifier); + } + + final String pkceCodeVerifier = params.getPkceCodeVerifier(); + if (pkceCodeVerifier != null) { + request.addParameter(PKCE.PKCE_CODE_VERIFIER_PARAM, pkceCodeVerifier); + } + + return request; + } + + @Override + public void signRequest(String accessToken, OAuthRequest request) { + request.addHeader(OAuthConstants.HEADER, + accessToken == null ? "Client-ID " + getApiKey() : "Bearer " + accessToken); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/instagram/InstagramAccessTokenErrorResponse.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/instagram/InstagramAccessTokenErrorResponse.java new file mode 100644 index 000000000..bae3454a2 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/instagram/InstagramAccessTokenErrorResponse.java @@ -0,0 +1,84 @@ +package com.github.scribejava.apis.instagram; + +import com.github.scribejava.core.model.OAuthResponseException; +import java.io.IOException; +import java.util.Objects; +import com.github.scribejava.core.model.Response; + +/** + * non standard Instagram replace for {@link com.github.scribejava.core.model.OAuth2AccessTokenErrorResponse} + * + * examples:
+ * + * '{"error_type": "OAuthException", "code": 400, "error_message": "Missing required field client_id"}' + */ +public class InstagramAccessTokenErrorResponse extends OAuthResponseException { + + private static final long serialVersionUID = -1277129706699856895L; + + private final String errorType; + private final int code; + private final String errorMessage; + private final transient Response response; + + public InstagramAccessTokenErrorResponse(String errorType, int code, String errorMessage, Response response) + throws IOException { + super(response); + this.errorType = errorType; + this.code = code; + this.errorMessage = errorMessage; + this.response = response; + } + + public String getErrorType() { + return errorType; + } + + public int getCode() { + return code; + } + + public String getErrorMessage() { + return errorMessage; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + if (!super.equals(obj)) { + return false; + } + + final InstagramAccessTokenErrorResponse that = (InstagramAccessTokenErrorResponse) obj; + if (!Objects.equals(errorMessage, that.getErrorMessage())) { + return false; + } + return code == that.code && Objects.equals(errorType, that.errorType) + && Objects.equals(response, that.response); + } + + @Override + public int hashCode() { + int hash = super.hashCode(); + hash = 83 * hash + Objects.hashCode(response); + hash = 83 * hash + Objects.hashCode(errorMessage); + hash = 83 * hash + Objects.hashCode(errorType); + hash = 83 * hash + Objects.hashCode(code); + return hash; + } + + @Override + public String toString() { + return "InstagramAccessTokenErrorResponse{" + + "errorType='" + errorType + + "', code=" + code + + "', errorMessage='" + errorMessage + + "', response=" + response + + '}'; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/instagram/InstagramAccessTokenJsonExtractor.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/instagram/InstagramAccessTokenJsonExtractor.java new file mode 100644 index 000000000..8f30b2e96 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/instagram/InstagramAccessTokenJsonExtractor.java @@ -0,0 +1,55 @@ +package com.github.scribejava.apis.instagram; + +import java.io.IOException; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.scribejava.apis.facebook.FacebookAccessTokenJsonExtractor; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.model.Response; + +/** + * non standard Instagram Extractor + */ +public class InstagramAccessTokenJsonExtractor extends OAuth2AccessTokenJsonExtractor { + + protected InstagramAccessTokenJsonExtractor() { + } + + private static class InstanceHolder { + + private static final InstagramAccessTokenJsonExtractor INSTANCE = new InstagramAccessTokenJsonExtractor(); + } + + public static InstagramAccessTokenJsonExtractor instance() { + return InstanceHolder.INSTANCE; + } + + /** + * Non standard error message. Could be Instagram or Facebook specific. Usually Instagram type is used for getting + * access tokens. Facebook type is used for refreshing tokens. + * + * examples:
+ * + * Instagram specific: '{"error_type": "OAuthException", "code": 400, "error_message": "Missing required field + * client_id"}' + * + * Facebook specific: '{"error":{"message":"Error validating application. Invalid application + * ID.","type":"OAuthException","code":101,"fbtrace_id":"CvDR+X4WWIx"}}' + * + * @param response response + */ + @Override + public void generateError(Response response) throws IOException { + final JsonNode errorNode = OAuth2AccessTokenJsonExtractor.OBJECT_MAPPER.readTree(response.getBody()); + final JsonNode error = errorNode.get("error"); + if (error != null) { + FacebookAccessTokenJsonExtractor.instance().generateError(response); + } else { + throw new InstagramAccessTokenErrorResponse( + errorNode.get("error_type").asText(), + errorNode.get("code").asInt(), + errorNode.get("error_message").asText(), + response + ); + } + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/instagram/InstagramService.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/instagram/InstagramService.java new file mode 100644 index 000000000..5de1f3782 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/instagram/InstagramService.java @@ -0,0 +1,105 @@ +package com.github.scribejava.apis.instagram; + +import com.github.scribejava.apis.InstagramApi; +import java.io.IOException; +import java.io.OutputStream; +import java.util.concurrent.ExecutionException; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.util.concurrent.Future; + +public class InstagramService extends OAuth20Service { + + public InstagramService(InstagramApi api, String apiKey, String apiSecret, String callback, String defaultScope, + String responseType, OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, + HttpClient httpClient) { + super(api, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, userAgent, httpClientConfig, + httpClient); + } + + /** + * Refresh a long-lived Instagram User Access Token that is at least 24 hours old but has not expired. Refreshed + * tokens are valid for 60 days from the date at which they are refreshed. + * + * @param accessToken long-lived access token + * @param scope (not used) + * @return refresh token request + */ + @Override + protected OAuthRequest createRefreshTokenRequest(String accessToken, String scope) { + if (accessToken == null || accessToken.isEmpty()) { + throw new IllegalArgumentException("The accessToken cannot be null or empty"); + } + final OAuthRequest request = new OAuthRequest(Verb.GET, getApi().getRefreshTokenEndpoint()); + + request.addParameter(OAuthConstants.GRANT_TYPE, "ig_refresh_token"); + request.addParameter(OAuthConstants.ACCESS_TOKEN, accessToken); + + logRequestWithParams("refresh token", request); + + return request; + } + + public Future getLongLivedAccessTokenAsync(OAuth2AccessToken accessToken) { + return getLongLivedAccessToken(accessToken.getAccessToken(), null); + } + + public Future getLongLivedAccessTokenAsync(String shortLivedAccessToken) { + return getLongLivedAccessToken(shortLivedAccessToken, null); + } + + public Future getLongLivedAccessToken(String shortLivedAccessToken, + OAuthAsyncRequestCallback callback) { + return sendAccessTokenRequestAsync(createLongLivedAccessTokenRequest(shortLivedAccessToken), callback); + } + + public Future getLongLivedAccessToken(OAuth2AccessToken accessToken, + OAuthAsyncRequestCallback callback) { + return getLongLivedAccessToken(accessToken.getAccessToken(), callback); + } + + /** + * Get long-lived access token. + * + * Initial accessToken is valid for 1 hour so one can get long-lived access token. Long-lived access token is valid + * for 60 days. + * + * @param accessToken short-lived access token + * @return long-lived access token with filled expireIn and refreshToken + * @throws java.lang.InterruptedException + * @throws java.util.concurrent.ExecutionException + * @throws java.io.IOException + */ + public OAuth2AccessToken getLongLivedAccessToken(OAuth2AccessToken accessToken) + throws InterruptedException, ExecutionException, IOException { + return getLongLivedAccessToken(accessToken.getAccessToken()); + } + + public OAuth2AccessToken getLongLivedAccessToken(String shortLivedAccessToken) + throws InterruptedException, ExecutionException, IOException { + final OAuthRequest request = createLongLivedAccessTokenRequest(shortLivedAccessToken); + return sendAccessTokenRequestSync(request); + } + + private OAuthRequest createLongLivedAccessTokenRequest(String shortLivedAccessToken) { + final OAuthRequest request = new OAuthRequest(Verb.GET, InstagramApi.LONG_LIVED_ACCESS_TOKEN_ENDPOINT); + + getApi().getClientAuthentication().addClientAuthentication(request, getApiKey(), getApiSecret()); + + request.addParameter(OAuthConstants.GRANT_TYPE, "ig_exchange_token"); + request.addParameter(OAuthConstants.ACCESS_TOKEN, shortLivedAccessToken); + + if (isDebug()) { + log("created long-lived access token request with body params [%s], query string params [%s]", + request.getBodyParams().asFormUrlEncodedString(), + request.getQueryStringParams().asFormUrlEncodedString()); + } + return request; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/mailru/MailruOAuthService.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/mailru/MailruOAuthService.java new file mode 100644 index 000000000..a9ff7d77b --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/mailru/MailruOAuthService.java @@ -0,0 +1,74 @@ +package com.github.scribejava.apis.mailru; + +import com.github.scribejava.apis.MailruApi; +import java.net.URLDecoder; +import java.util.Map; +import java.util.TreeMap; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Formatter; + +public class MailruOAuthService extends OAuth20Service { + + public MailruOAuthService(MailruApi api, String apiKey, String apiSecret, String callback, String defaultScope, + String responseType, OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, + HttpClient httpClient) { + super(api, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, userAgent, httpClientConfig, + httpClient); + } + + @Override + public void signRequest(String accessToken, OAuthRequest request) { + // sig = md5(params + secret_key) + request.addQuerystringParameter("session_key", accessToken); + request.addQuerystringParameter("app_id", getApiKey()); + final String completeUrl = request.getCompleteUrl(); + + try { + final String clientSecret = getApiSecret(); + final int queryIndex = completeUrl.indexOf('?'); + if (queryIndex != -1) { + final String urlPart = completeUrl.substring(queryIndex + 1); + final Map map = new TreeMap<>(); + for (String param : urlPart.split("&")) { + final String[] parts = param.split("="); + map.put(parts[0], (parts.length == 1) ? "" : parts[1]); + } + + final StringBuilder urlNew = new StringBuilder(); + for (Map.Entry entry : map.entrySet()) { + urlNew.append(entry.getKey()); + urlNew.append('='); + urlNew.append(entry.getValue()); + } + + final String sigSource = URLDecoder.decode(urlNew.toString(), "UTF-8") + clientSecret; + request.addQuerystringParameter("sig", md5(sigSource)); + } + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException(e); + } + } + + public static String md5(String orgString) { + try { + final MessageDigest md = MessageDigest.getInstance("MD5"); + final byte[] array = md.digest(orgString.getBytes(Charset.forName("UTF-8"))); + final Formatter builder = new Formatter(); + for (byte b : array) { + builder.format("%02x", b); + } + return builder.toString(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException("MD5 is unsupported?", e); + } + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/microsoftazureactivedirectory/BaseMicrosoftAzureActiveDirectoryApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/microsoftazureactivedirectory/BaseMicrosoftAzureActiveDirectoryApi.java new file mode 100644 index 000000000..5e4891164 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/microsoftazureactivedirectory/BaseMicrosoftAzureActiveDirectoryApi.java @@ -0,0 +1,41 @@ +package com.github.scribejava.apis.microsoftazureactivedirectory; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +public abstract class BaseMicrosoftAzureActiveDirectoryApi extends DefaultApi20 { + + protected static final String COMMON_TENANT = "common"; + + private static final String MSFT_LOGIN_URL = "https://login.microsoftonline.com/"; + private static final String OAUTH_2 = "/oauth2"; + private final String tenant; + + protected BaseMicrosoftAzureActiveDirectoryApi() { + this(COMMON_TENANT); + } + + protected BaseMicrosoftAzureActiveDirectoryApi(String tenant) { + this.tenant = tenant == null || tenant.isEmpty() ? COMMON_TENANT : tenant; + } + + @Override + public String getAccessTokenEndpoint() { + return MSFT_LOGIN_URL + tenant + OAUTH_2 + getEndpointVersionPath() + "/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return MSFT_LOGIN_URL + tenant + OAUTH_2 + getEndpointVersionPath() + "/authorize"; + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } + + protected String getEndpointVersionPath() { + return ""; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/microsoftazureactivedirectory/BaseMicrosoftAzureActiveDirectoryBearerSignature.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/microsoftazureactivedirectory/BaseMicrosoftAzureActiveDirectoryBearerSignature.java new file mode 100644 index 000000000..ab85674af --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/microsoftazureactivedirectory/BaseMicrosoftAzureActiveDirectoryBearerSignature.java @@ -0,0 +1,20 @@ +package com.github.scribejava.apis.microsoftazureactivedirectory; + +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureAuthorizationRequestHeaderField; + +public abstract class BaseMicrosoftAzureActiveDirectoryBearerSignature + extends BearerSignatureAuthorizationRequestHeaderField { + + private final String acceptedFormat; + + protected BaseMicrosoftAzureActiveDirectoryBearerSignature(String acceptedFormat) { + this.acceptedFormat = acceptedFormat; + } + + @Override + public void signRequest(String accessToken, OAuthRequest request) { + super.signRequest(accessToken, request); + request.addHeader("Accept", acceptedFormat); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/microsoftazureactivedirectory/MicrosoftAzureActiveDirectory20BearerSignature.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/microsoftazureactivedirectory/MicrosoftAzureActiveDirectory20BearerSignature.java new file mode 100644 index 000000000..c554beeff --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/microsoftazureactivedirectory/MicrosoftAzureActiveDirectory20BearerSignature.java @@ -0,0 +1,18 @@ +package com.github.scribejava.apis.microsoftazureactivedirectory; + +public class MicrosoftAzureActiveDirectory20BearerSignature extends BaseMicrosoftAzureActiveDirectoryBearerSignature { + + protected MicrosoftAzureActiveDirectory20BearerSignature() { + super("application/json"); + } + + private static class InstanceHolder { + + private static final MicrosoftAzureActiveDirectory20BearerSignature INSTANCE + = new MicrosoftAzureActiveDirectory20BearerSignature(); + } + + public static MicrosoftAzureActiveDirectory20BearerSignature instance() { + return InstanceHolder.INSTANCE; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/microsoftazureactivedirectory/MicrosoftAzureActiveDirectoryBearerSignature.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/microsoftazureactivedirectory/MicrosoftAzureActiveDirectoryBearerSignature.java new file mode 100644 index 000000000..bfddd523a --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/microsoftazureactivedirectory/MicrosoftAzureActiveDirectoryBearerSignature.java @@ -0,0 +1,18 @@ +package com.github.scribejava.apis.microsoftazureactivedirectory; + +public class MicrosoftAzureActiveDirectoryBearerSignature extends BaseMicrosoftAzureActiveDirectoryBearerSignature { + + protected MicrosoftAzureActiveDirectoryBearerSignature() { + super("application/json; odata=minimalmetadata; streaming=true; charset=utf-8"); + } + + private static class InstanceHolder { + + private static final MicrosoftAzureActiveDirectoryBearerSignature INSTANCE + = new MicrosoftAzureActiveDirectoryBearerSignature(); + } + + public static MicrosoftAzureActiveDirectoryBearerSignature instance() { + return InstanceHolder.INSTANCE; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/odnoklassniki/OdnoklassnikiOAuthService.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/odnoklassniki/OdnoklassnikiOAuthService.java new file mode 100644 index 000000000..fd1327a6d --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/odnoklassniki/OdnoklassnikiOAuthService.java @@ -0,0 +1,72 @@ +package com.github.scribejava.apis.odnoklassniki; + +import com.github.scribejava.apis.OdnoklassnikiApi; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Parameter; +import com.github.scribejava.core.model.ParameterList; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; + +import java.net.URLDecoder; +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Collections; +import java.util.Formatter; +import java.util.List; + +public class OdnoklassnikiOAuthService extends OAuth20Service { + + public OdnoklassnikiOAuthService(OdnoklassnikiApi api, String apiKey, String apiSecret, String callback, + String defaultScope, String responseType, OutputStream debugStream, String userAgent, + HttpClientConfig httpClientConfig, HttpClient httpClient) { + super(api, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, userAgent, httpClientConfig, + httpClient); + } + + @Override + public void signRequest(String accessToken, OAuthRequest request) { + //sig = lower(md5( sorted_request_params_composed_string + md5(access_token + application_secret_key))) + try { + final String tokenDigest = md5(accessToken + getApiSecret()); + + final ParameterList queryParams = request.getQueryStringParams(); + queryParams.addAll(request.getBodyParams()); + final List allParams = queryParams.getParams(); + + Collections.sort(allParams); + + final StringBuilder stringParams = new StringBuilder(); + for (Parameter param : allParams) { + stringParams.append(param.getKey()) + .append('=') + .append(param.getValue()); + } + + final String sigSource = URLDecoder.decode(stringParams.toString(), "UTF-8") + tokenDigest; + request.addQuerystringParameter("sig", md5(sigSource).toLowerCase()); + + super.signRequest(accessToken, request); + } catch (UnsupportedEncodingException unex) { + throw new IllegalStateException(unex); + } + } + + public static String md5(String orgString) { + try { + final MessageDigest md = MessageDigest.getInstance("MD5"); + final byte[] array = md.digest(orgString.getBytes(Charset.forName("UTF-8"))); + final Formatter builder = new Formatter(); + for (byte b : array) { + builder.format("%02x", b); + } + return builder.toString(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException("MD5 is unsupported?", e); + } + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/openid/OpenIdJsonTokenExtractor.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/openid/OpenIdJsonTokenExtractor.java new file mode 100644 index 000000000..1fc441a70 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/openid/OpenIdJsonTokenExtractor.java @@ -0,0 +1,30 @@ +package com.github.scribejava.apis.openid; + +import com.fasterxml.jackson.databind.JsonNode; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; + +/** + * additionally parses OpenID id_token + */ +public class OpenIdJsonTokenExtractor extends OAuth2AccessTokenJsonExtractor { + + protected OpenIdJsonTokenExtractor() { + } + + private static class InstanceHolder { + + private static final OpenIdJsonTokenExtractor INSTANCE = new OpenIdJsonTokenExtractor(); + } + + public static OpenIdJsonTokenExtractor instance() { + return InstanceHolder.INSTANCE; + } + + @Override + protected OpenIdOAuth2AccessToken createToken(String accessToken, String tokenType, Integer expiresIn, + String refreshToken, String scope, JsonNode response, String rawResponse) { + final JsonNode idToken = response.get("id_token"); + return new OpenIdOAuth2AccessToken(accessToken, tokenType, expiresIn, refreshToken, scope, + idToken == null ? null : idToken.asText(), rawResponse); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/openid/OpenIdOAuth2AccessToken.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/openid/OpenIdOAuth2AccessToken.java new file mode 100644 index 000000000..7e6588444 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/openid/OpenIdOAuth2AccessToken.java @@ -0,0 +1,59 @@ +package com.github.scribejava.apis.openid; + +import com.github.scribejava.core.model.OAuth2AccessToken; +import java.util.Objects; + +public class OpenIdOAuth2AccessToken extends OAuth2AccessToken { + + private static final long serialVersionUID = -4534058186528117610L; + + /** + * Id_token is part of OpenID Connect specification. It can hold user information that you can directly extract + * without additional request to provider. + * + * See http://openid.net/specs/openid-connect-core-1_0.html#id_token-tokenExample and + * https://bitbucket.org/nimbusds/nimbus-jose-jwt/wiki/Home + * + * Here will be encoded and signed id token in JWT format or null, if not defined. + */ + private final String openIdToken; + + public OpenIdOAuth2AccessToken(String accessToken, String openIdToken, String rawResponse) { + this(accessToken, null, null, null, null, openIdToken, rawResponse); + } + + public OpenIdOAuth2AccessToken(String accessToken, String tokenType, Integer expiresIn, String refreshToken, + String scope, String openIdToken, String rawResponse) { + super(accessToken, tokenType, expiresIn, refreshToken, scope, rawResponse); + this.openIdToken = openIdToken; + } + + public String getOpenIdToken() { + return openIdToken; + } + + @Override + public int hashCode() { + int hash = super.hashCode(); + hash = 37 * hash + Objects.hashCode(openIdToken); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + if (!super.equals(obj)) { + return false; + } + + return Objects.equals(openIdToken, ((OpenIdOAuth2AccessToken) obj).getOpenIdToken()); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/polar/PolarJsonTokenExtractor.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/polar/PolarJsonTokenExtractor.java new file mode 100644 index 000000000..1258dfe59 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/polar/PolarJsonTokenExtractor.java @@ -0,0 +1,55 @@ +package com.github.scribejava.apis.polar; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.model.OAuth2AccessTokenErrorResponse; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.oauth2.OAuth2Error; +import java.io.IOException; + +/** + * Token related documentation: https://www.polar.com/accesslink-api/#token-endpoint + */ +public class PolarJsonTokenExtractor extends OAuth2AccessTokenJsonExtractor { + + protected PolarJsonTokenExtractor() { + } + + private static class InstanceHolder { + + private static final PolarJsonTokenExtractor INSTANCE = new PolarJsonTokenExtractor(); + } + + public static PolarJsonTokenExtractor instance() { + return InstanceHolder.INSTANCE; + } + + @Override + protected PolarOAuth2AccessToken createToken(String accessToken, String tokenType, Integer expiresIn, + String refreshToken, String scope, JsonNode response, String rawResponse) { + return new PolarOAuth2AccessToken(accessToken, tokenType, expiresIn, refreshToken, scope, + response.get("x_user_id").asText(), rawResponse); + } + + @Override + public void generateError(Response response) throws IOException { + final JsonNode errorNode; + try { + errorNode = OAuth2AccessTokenJsonExtractor.OBJECT_MAPPER.readTree(response.getBody()).get("errors").get(0); + } catch (JsonProcessingException ex) { + throw new OAuth2AccessTokenErrorResponse(null, null, null, response); + } + + OAuth2Error errorCode; + try { + errorCode = OAuth2Error + .parseFrom(extractRequiredParameter(errorNode, "errorType", response.getBody()).asText()); + } catch (IllegalArgumentException iaE) { + //non oauth standard error code + errorCode = null; + } + + throw new OAuth2AccessTokenErrorResponse(errorCode, errorNode.get("message").asText(), null, response); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/polar/PolarOAuth2AccessToken.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/polar/PolarOAuth2AccessToken.java new file mode 100644 index 000000000..99710728f --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/polar/PolarOAuth2AccessToken.java @@ -0,0 +1,47 @@ +package com.github.scribejava.apis.polar; + +import com.github.scribejava.core.model.OAuth2AccessToken; + +import java.util.Objects; + +public class PolarOAuth2AccessToken extends OAuth2AccessToken { + + private static final long serialVersionUID = 1L; + + private final String userId; + + public PolarOAuth2AccessToken(String accessToken, String tokenType, Integer expiresIn, String refreshToken, + String scope, String userId, String rawResponse) { + super(accessToken, tokenType, expiresIn, refreshToken, scope, rawResponse); + this.userId = userId; + } + + public String getUserId() { + return userId; + } + + @Override + public int hashCode() { + int hash = super.hashCode(); + hash = 37 * hash + Objects.hashCode(userId); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + if (!super.equals(obj)) { + return false; + } + + return Objects.equals(userId, ((PolarOAuth2AccessToken) obj).getUserId()); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/polar/PolarOAuthService.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/polar/PolarOAuthService.java new file mode 100644 index 000000000..c016d6ac7 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/polar/PolarOAuthService.java @@ -0,0 +1,47 @@ +package com.github.scribejava.apis.polar; + +import com.github.scribejava.apis.PolarAPI; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.oauth.AccessTokenRequestParams; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.core.pkce.PKCE; + +import java.io.OutputStream; + +public class PolarOAuthService extends OAuth20Service { + + public PolarOAuthService(PolarAPI api, String apiKey, String apiSecret, String callback, String defaultScope, + String responseType, OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, + HttpClient httpClient) { + super(api, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, userAgent, httpClientConfig, + httpClient); + } + + @Override + protected OAuthRequest createAccessTokenRequest(AccessTokenRequestParams params) { + final OAuthRequest request = new OAuthRequest(getApi().getAccessTokenVerb(), getApi().getAccessTokenEndpoint()); + + getApi().getClientAuthentication().addClientAuthentication(request, getApiKey(), getApiSecret()); + + request.addParameter(OAuthConstants.CODE, params.getCode()); + final String callback = getCallback(); + if (callback != null) { + request.addParameter(OAuthConstants.REDIRECT_URI, callback); + } + request.addParameter(OAuthConstants.GRANT_TYPE, OAuthConstants.AUTHORIZATION_CODE); + + final String pkceCodeVerifier = params.getPkceCodeVerifier(); + if (pkceCodeVerifier != null) { + request.addParameter(PKCE.PKCE_CODE_VERIFIER_PARAM, pkceCodeVerifier); + } + if (isDebug()) { + log("created access token request with body params [%s], query string params [%s]", + request.getBodyParams().asFormUrlEncodedString(), + request.getQueryStringParams().asFormUrlEncodedString()); + } + return request; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/salesforce/SalesforceJsonTokenExtractor.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/salesforce/SalesforceJsonTokenExtractor.java new file mode 100644 index 000000000..62a3294cf --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/salesforce/SalesforceJsonTokenExtractor.java @@ -0,0 +1,30 @@ +package com.github.scribejava.apis.salesforce; + +import com.fasterxml.jackson.databind.JsonNode; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; + +/** + * This extractor parses in addition to the standard Extractor the instance_url + * of the used Salesforce organization. + */ +public class SalesforceJsonTokenExtractor extends OAuth2AccessTokenJsonExtractor { + + protected SalesforceJsonTokenExtractor() { + } + + private static class InstanceHolder { + + private static final SalesforceJsonTokenExtractor INSTANCE = new SalesforceJsonTokenExtractor(); + } + + public static SalesforceJsonTokenExtractor instance() { + return InstanceHolder.INSTANCE; + } + + @Override + protected SalesforceToken createToken(String accessToken, String tokenType, Integer expiresIn, + String refreshToken, String scope, JsonNode response, String rawResponse) { + return new SalesforceToken(accessToken, tokenType, expiresIn, refreshToken, scope, + extractRequiredParameter(response, "instance_url", rawResponse).asText(), rawResponse); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/salesforce/SalesforceToken.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/salesforce/SalesforceToken.java new file mode 100644 index 000000000..242cb7e31 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/salesforce/SalesforceToken.java @@ -0,0 +1,54 @@ +package com.github.scribejava.apis.salesforce; + +import java.util.Objects; + +import com.github.scribejava.core.model.OAuth2AccessToken; + +public class SalesforceToken extends OAuth2AccessToken { + + private static final long serialVersionUID = 7496092256264195577L; + + /** + * This token model includes the instance_url to address the needed + * Salesforce organization instance. + */ + private final String instanceUrl; + + public SalesforceToken(String accessToken, String instanceUrl, String rawResponse) { + this(accessToken, null, null, null, null, instanceUrl, rawResponse); + } + + public SalesforceToken(String accessToken, String tokenType, Integer expiresIn, String refreshToken, String scope, + String instanceUrl, String rawResponse) { + super(accessToken, tokenType, expiresIn, refreshToken, scope, rawResponse); + this.instanceUrl = instanceUrl; + } + + public String getInstanceUrl() { + return instanceUrl; + } + + @Override + public int hashCode() { + int hash = super.hashCode(); + hash = 37 * hash + Objects.hashCode(instanceUrl); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + if (!super.equals(obj)) { + return false; + } + return Objects.equals(instanceUrl, ((SalesforceToken) obj).getInstanceUrl()); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/slack/SlackJsonTokenExtractor.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/slack/SlackJsonTokenExtractor.java new file mode 100644 index 000000000..ca0be7587 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/slack/SlackJsonTokenExtractor.java @@ -0,0 +1,34 @@ +package com.github.scribejava.apis.slack; + +import com.fasterxml.jackson.databind.JsonNode; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; + +public class SlackJsonTokenExtractor extends OAuth2AccessTokenJsonExtractor { + + protected SlackJsonTokenExtractor() { + } + + private static class InstanceHolder { + + private static final SlackJsonTokenExtractor INSTANCE = new SlackJsonTokenExtractor(); + } + + public static SlackJsonTokenExtractor instance() { + return SlackJsonTokenExtractor.InstanceHolder.INSTANCE; + } + + @Override + protected SlackOAuth2AccessToken createToken(String accessToken, String tokenType, Integer expiresIn, + String refreshToken, String scope, JsonNode response, String rawResponse) { + final String userAccessToken; + final JsonNode userAccessTokenNode = response.get("authed_user").get("access_token"); + if (userAccessTokenNode == null) { + userAccessToken = ""; + } else { + userAccessToken = userAccessTokenNode.asText(); + } + + return new SlackOAuth2AccessToken(accessToken, tokenType, expiresIn, refreshToken, scope, userAccessToken, + rawResponse); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/slack/SlackOAuth2AccessToken.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/slack/SlackOAuth2AccessToken.java new file mode 100644 index 000000000..d1d28ad7b --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/slack/SlackOAuth2AccessToken.java @@ -0,0 +1,47 @@ +package com.github.scribejava.apis.slack; + +import com.github.scribejava.core.model.OAuth2AccessToken; + +import java.util.Objects; + +public class SlackOAuth2AccessToken extends OAuth2AccessToken { + + private static final long serialVersionUID = 1L; + + private final String userAccessToken; + + public SlackOAuth2AccessToken(String accessToken, String tokenType, Integer expiresIn, String refreshToken, + String scope, String userAccessToken, String rawResponse) { + super(accessToken, tokenType, expiresIn, refreshToken, scope, rawResponse); + this.userAccessToken = userAccessToken; + } + + public String getUserAccessToken() { + return userAccessToken; + } + + @Override + public int hashCode() { + int hash = super.hashCode(); + hash = 37 * hash + Objects.hashCode(userAccessToken); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + if (!super.equals(obj)) { + return false; + } + + return Objects.equals(userAccessToken, ((SlackOAuth2AccessToken) obj).getUserAccessToken()); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/tutby/TutByBearerSignature.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/tutby/TutByBearerSignature.java new file mode 100644 index 000000000..0c7609073 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/tutby/TutByBearerSignature.java @@ -0,0 +1,25 @@ +package com.github.scribejava.apis.tutby; + +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; + +public class TutByBearerSignature implements BearerSignature { + + protected TutByBearerSignature() { + } + + private static class InstanceHolder { + + private static final TutByBearerSignature INSTANCE = new TutByBearerSignature(); + } + + public static TutByBearerSignature instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public void signRequest(String accessToken, OAuthRequest request) { + request.addQuerystringParameter(OAuthConstants.TOKEN, accessToken); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/vk/VKJsonTokenExtractor.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/vk/VKJsonTokenExtractor.java new file mode 100644 index 000000000..a3d14aacf --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/vk/VKJsonTokenExtractor.java @@ -0,0 +1,30 @@ +package com.github.scribejava.apis.vk; + +import com.fasterxml.jackson.databind.JsonNode; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; + +/** + * additionally parses email + */ +public class VKJsonTokenExtractor extends OAuth2AccessTokenJsonExtractor { + + protected VKJsonTokenExtractor() { + } + + private static class InstanceHolder { + + private static final VKJsonTokenExtractor INSTANCE = new VKJsonTokenExtractor(); + } + + public static VKJsonTokenExtractor instance() { + return InstanceHolder.INSTANCE; + } + + @Override + protected VKOAuth2AccessToken createToken(String accessToken, String tokenType, Integer expiresIn, + String refreshToken, String scope, JsonNode response, String rawResponse) { + final JsonNode email = response.get("email"); + return new VKOAuth2AccessToken(accessToken, tokenType, expiresIn, refreshToken, scope, + email == null ? null : email.asText(), rawResponse); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/vk/VKOAuth2AccessToken.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/vk/VKOAuth2AccessToken.java new file mode 100644 index 000000000..a8e75992b --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/vk/VKOAuth2AccessToken.java @@ -0,0 +1,50 @@ +package com.github.scribejava.apis.vk; + +import com.github.scribejava.core.model.OAuth2AccessToken; +import java.util.Objects; + +public class VKOAuth2AccessToken extends OAuth2AccessToken { + + private static final long serialVersionUID = -3539517142527580499L; + + private final String email; + + public VKOAuth2AccessToken(String accessToken, String email, String rawResponse) { + this(accessToken, null, null, null, null, email, rawResponse); + } + + public VKOAuth2AccessToken(String accessToken, String tokenType, Integer expiresIn, String refreshToken, + String scope, String email, String rawResponse) { + super(accessToken, tokenType, expiresIn, refreshToken, scope, rawResponse); + this.email = email; + } + + public String getEmail() { + return email; + } + + @Override + public int hashCode() { + int hash = super.hashCode(); + hash = 37 * hash + Objects.hashCode(email); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + if (!super.equals(obj)) { + return false; + } + + return Objects.equals(email, ((VKOAuth2AccessToken) obj).getEmail()); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/wunderlist/WunderlistOAuthService.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/wunderlist/WunderlistOAuthService.java new file mode 100644 index 000000000..06a248d9c --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/wunderlist/WunderlistOAuthService.java @@ -0,0 +1,25 @@ +package com.github.scribejava.apis.wunderlist; + +import java.io.OutputStream; + +import com.github.scribejava.apis.WunderlistAPI; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.oauth.OAuth20Service; + +public class WunderlistOAuthService extends OAuth20Service { + + public WunderlistOAuthService(WunderlistAPI api, String apiKey, String apiSecret, String callback, + String defaultScope, String responseType, OutputStream debugStream, String userAgent, + HttpClientConfig httpClientConfig, HttpClient httpClient) { + super(api, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, userAgent, httpClientConfig, + httpClient); + } + + @Override + public void signRequest(String accessToken, OAuthRequest request) { + super.signRequest(accessToken, request); + request.addHeader("X-Client-ID", getApiKey()); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/ExampleUtils.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/ExampleUtils.java new file mode 100644 index 000000000..5f60abcb1 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/ExampleUtils.java @@ -0,0 +1,55 @@ +package com.github.scribejava.apis; + +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +public class ExampleUtils { + + private ExampleUtils() { + } + + public static void turnOfSSl() { + try { + final TrustManager[] trustAllCerts = new TrustManager[]{new TrustAllCertsManager() + }; + + final SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, trustAllCerts, new java.security.SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + + final HostnameVerifier allHostsValid = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + + HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); + } catch (NoSuchAlgorithmException | KeyManagementException e) { + throw new RuntimeException(e); + } + } + + private static class TrustAllCertsManager implements X509TrustManager { + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/AWeberExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/AWeberExample.java new file mode 100644 index 000000000..e61110716 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/AWeberExample.java @@ -0,0 +1,71 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.AWeberApi; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class AWeberExample { + + //To get your consumer key/secret, and view API docs, see https://labs.aweber.com/docs + private static final String ACCOUNT_RESOURCE_URL = "https://api.aweber.com/1.0/accounts/"; + + private static final String CONSUMER_KEY = ""; + private static final String CONSUMER_SECRET = ""; + + private AWeberExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + final OAuth10aService service = new ServiceBuilder(CONSUMER_KEY) + .apiSecret(CONSUMER_SECRET) + .build(AWeberApi.instance()); + + final Scanner in = new Scanner(System.in); + + System.out.println("=== AWeber's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(service.getAuthorizationUrl(requestToken)); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, ACCOUNT_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with AWeber and ScribeJava! :)"); + } + +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/AsanaExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/AsanaExample.java new file mode 100644 index 000000000..1ab4d3d3c --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/AsanaExample.java @@ -0,0 +1,82 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.Asana20Api; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.IOException; +import java.util.Random; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class AsanaExample { + + private static final String PROTECTED_RESOURCE_URL = "https://app.asana.com/api/1.0/users/me"; + + private AsanaExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + final String apiKey = "your client id"; + final String apiSecret = "your client secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + final OAuth20Service service = new ServiceBuilder(apiKey) + .apiSecret(apiSecret) + .callback("https://localhost/") + .build(Asana20Api.instance()); + final Scanner in = new Scanner(System.in); + + // Obtain Auth URL + System.out.println("Fetching the Authorication URL..."); + System.out.println("Got the Authorization URL!"); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Refreshing the Access Token..."); + accessToken = service.refreshAccessToken(accessToken.getRefreshToken()); + System.out.println("Refreshed the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/AutomaticExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/AutomaticExample.java new file mode 100644 index 000000000..ae0c299f2 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/AutomaticExample.java @@ -0,0 +1,83 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.AutomaticAPI; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.IOException; +import java.util.Random; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class AutomaticExample { + + private static final String NETWORK_NAME = "Automatic"; + private static final String PROTECTED_RESOURCE_URL = "https://api.automatic.com/user/me/"; + + private AutomaticExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("http://www.example.com/oauth_callback/") + .defaultScope("scope:user:profile") + .build(AutomaticAPI.instance()); + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + // Trade the Authorization Code for the Access Token + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Box20Example.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Box20Example.java new file mode 100644 index 000000000..11673af20 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Box20Example.java @@ -0,0 +1,91 @@ +package com.github.scribejava.apis.examples; + +import java.util.Random; +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.BoxApi20; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +public class Box20Example { + + private static final String NETWORK_NAME = "Box"; + private static final String PROTECTED_RESOURCE_URL = "https://api.box.com/2.0/users/me"; + + private Box20Example() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + //Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String secretState = "security_token" + new Random().nextInt(999_999); + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("https://example.com/callback") + .build(BoxApi20.instance()); + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + //pass access_type=offline to get refresh token + final Map additionalParams = new HashMap<>(); + additionalParams.put("access_type", "offline"); + //force to reget refresh token (if user are asked not the first time) + additionalParams.put("prompt", "consent"); + final String authorizationUrl = service.createAuthorizationUrlBuilder() + .state(secretState) + .additionalParams(additionalParams) + .build(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } + +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/DataportenExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/DataportenExample.java new file mode 100644 index 000000000..fe8fada2a --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/DataportenExample.java @@ -0,0 +1,80 @@ +package com.github.scribejava.apis.examples; + +import java.util.Random; +import java.util.Scanner; +import com.github.scribejava.apis.DataportenApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class DataportenExample { + + private static final String NETWORK_NAME = "Dataporten"; + private static final String PROTECTED_RESOURCE_URL = "https://auth.dataporten.no/userinfo"; + + private DataportenExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("http://www.example.com/oauth_callback/") + .build(DataportenApi.instance()); + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/DiggExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/DiggExample.java new file mode 100644 index 000000000..eb2820683 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/DiggExample.java @@ -0,0 +1,75 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.DiggApi; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class DiggExample { + + private static final String NETWORK_NAME = "Digg"; + private static final String PROTECTED_RESOURCE_URL = "http://services.digg.com/2.0/comment.digg"; + + private DiggExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your own api key and secret + final String apiKey = "myKey"; + final String apiSecret = "mySecret"; + final OAuth10aService service = new ServiceBuilder(apiKey) + .apiSecret(apiSecret) + .build(DiggApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(requestToken); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.POST, PROTECTED_RESOURCE_URL); + request.addBodyParameter("comment_id", "20100729223726:4fef610331ee46a3b5cbd740bf71313e"); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/DiscordExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/DiscordExample.java new file mode 100644 index 000000000..f42bde9ec --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/DiscordExample.java @@ -0,0 +1,90 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.DiscordApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.IOException; +import java.util.Random; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class DiscordExample { + + private static final String NETWORK_NAME = "Discord"; + private static final String PROTECTED_RESOURCE_URL = "https://discordapp.com/api/users/@me"; + + private DiscordExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, ExecutionException, InterruptedException { + // Replace these with your client id and secret + final String clientId = "client id"; + final String clientSecret = "client secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope("identify") // replace with desired scope + .callback("http://example.com/callback") + .userAgent("ScribeJava") + .build(DiscordApi.instance()); + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(if your curious it looks like this: " + accessToken + + ", 'rawResponse'='" + accessToken.getRawResponse() + "')"); + + System.out.println("Refreshing the Access Token..."); + accessToken = service.refreshAccessToken(accessToken.getRefreshToken()); + System.out.println("Refreshed the Access Token!"); + System.out.println("(if your curious it looks like this: " + accessToken + + ", 'rawResponse'='" + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/DropboxExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/DropboxExample.java new file mode 100644 index 000000000..bcf02624a --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/DropboxExample.java @@ -0,0 +1,74 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.DropboxApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.IOException; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class DropboxExample { + + private static final String NETWORK_NAME = "Dropbox.com"; + private static final String PROTECTED_RESOURCE_URL = "https://api.dropboxapi.com/2/users/get_space_usage"; + private static final String PAYLOAD = "null"; + private static final String CONTENT_TYPE_NAME = "Content-Type"; + private static final String CONTENT_TYPE_VALUE = "application/json"; + + private DropboxExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "client id"; + final String clientSecret = "client secret"; + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("https://www.example.com/oauth_callback/") + .build(DropboxApi.instance()); + + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.POST, PROTECTED_RESOURCE_URL); + request.addHeader(CONTENT_TYPE_NAME, CONTENT_TYPE_VALUE); + request.setPayload(PAYLOAD); + service.signRequest(accessToken, request); + + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/EtsyExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/EtsyExample.java new file mode 100644 index 000000000..ad55cb07c --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/EtsyExample.java @@ -0,0 +1,66 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.EtsyApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; + +import java.io.IOException; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class EtsyExample { + + private static final String PROTECTED_RESOURCE_URL = "https://openapi.etsy.com/v2/users/__SELF__"; + + private EtsyExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String[] args) throws InterruptedException, ExecutionException, IOException { + // Replace with your api and secret key + final OAuth10aService service = new ServiceBuilder("your api key") + .apiSecret("your secret key") + .build(EtsyApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== Etsy's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(service.getAuthorizationUrl(requestToken)); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("That's it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FacebookExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FacebookExample.java new file mode 100644 index 000000000..db8f6bdea --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FacebookExample.java @@ -0,0 +1,82 @@ +package com.github.scribejava.apis.examples; + +import java.util.Random; +import java.util.Scanner; +import com.github.scribejava.apis.FacebookApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class FacebookExample { + + private static final String NETWORK_NAME = "Facebook"; + private static final String PROTECTED_RESOURCE_URL = "https://graph.facebook.com/v3.2/me"; + + private FacebookExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("http://www.example.com/oauth_callback/") + .build(FacebookApi.instance()); + + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FitbitApi20Example.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FitbitApi20Example.java new file mode 100644 index 000000000..e5818a92a --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FitbitApi20Example.java @@ -0,0 +1,81 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; + +import com.github.scribejava.apis.FitbitApi20; +import com.github.scribejava.apis.fitbit.FitBitOAuth2AccessToken; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +public class FitbitApi20Example { + + private static final String NETWORK_NAME = "Fitbit"; + + private static final String PROTECTED_RESOURCE_URL = "https://api.fitbit.com/1/user/%s/profile.json"; + + private FitbitApi20Example() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws Exception { + + // Replace these with your client id and secret fron your app + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope("activity profile") // replace with desired scope + //your callback URL to store and handle the authorization code sent by Fitbit + .callback("http://www.example.com/oauth_callback/") + .build(FitbitApi20.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl("some_params"); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken oauth2AccessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(if your curious it looks like this: " + oauth2AccessToken + + ", 'rawResponse'='" + oauth2AccessToken.getRawResponse() + "')"); + System.out.println(); + + if (!(oauth2AccessToken instanceof FitBitOAuth2AccessToken)) { + System.out.println("oauth2AccessToken is not instance of FitBitOAuth2AccessToken. Strange enough. exit."); + return; + } + + final FitBitOAuth2AccessToken accessToken = (FitBitOAuth2AccessToken) oauth2AccessToken; + // Now let's go and ask for a protected resource! + // This will get the profile for this user + System.out.println("Now we're going to access a protected resource..."); + + final OAuthRequest request = new OAuthRequest(Verb.GET, + String.format(PROTECTED_RESOURCE_URL, accessToken.getUserId())); + request.addHeader("x-li-format", "json"); + + service.signRequest(accessToken, request); + + System.out.println(); + try (Response response = service.execute(request)) { + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FlickrExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FlickrExample.java new file mode 100644 index 000000000..8cdf8a209 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FlickrExample.java @@ -0,0 +1,71 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.FlickrApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; + +import java.io.IOException; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class FlickrExample { + + private static final String PROTECTED_RESOURCE_URL = "http://api.flickr.com/services/rest/"; + + private FlickrExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your own api key and secret + final String apiKey = "your_app_id"; + final String apiSecret = "your_api_secret"; + + final OAuth10aService service = new ServiceBuilder(apiKey) + .apiSecret(apiSecret) + .build(FlickrApi.instance(FlickrApi.FlickrPerm.DELETE)); + final Scanner in = new Scanner(System.in); + + System.out.println("=== Flickr's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + final String authorizationUrl = service.getAuthorizationUrl(requestToken); + System.out.println(authorizationUrl); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + request.addQuerystringParameter("method", "flickr.test.login"); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Foursquare2Example.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Foursquare2Example.java new file mode 100644 index 000000000..cdd29180a --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Foursquare2Example.java @@ -0,0 +1,67 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.Foursquare2Api; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class Foursquare2Example { + + private static final String PROTECTED_RESOURCE_URL + = "https://api.foursquare.com/v2/users/self/friends?oauth_token="; + + private Foursquare2Example() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your own api key and secret + final String apiKey = "your client id"; + final String apiSecret = "your client secret"; + final OAuth20Service service = new ServiceBuilder(apiKey) + .apiSecret(apiSecret) + .callback("http://localhost:9000/") + .build(Foursquare2Api.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== Foursquare2's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL + accessToken.getAccessToken()); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FoursquareExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FoursquareExample.java new file mode 100644 index 000000000..6aa3c9435 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FoursquareExample.java @@ -0,0 +1,65 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.FoursquareApi; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class FoursquareExample { + + private static final String PROTECTED_RESOURCE_URL = "http://api.foursquare.com/v1/user"; + + private FoursquareExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + final OAuth10aService service = new ServiceBuilder("your client id") + .apiSecret("your client secret") + .build(FoursquareApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== Foursquare's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(service.getAuthorizationUrl(requestToken)); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } + +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FrappeExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FrappeExample.java new file mode 100644 index 000000000..827f8aacd --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FrappeExample.java @@ -0,0 +1,68 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.FrappeApi; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class FrappeExample { + + private static final String NETWORK_NAME = "Frappe"; + private static final String PROTECTED_RESOURCE_PATH = "/api/method/frappe.integrations.oauth2.openid_profile"; + + private FrappeExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + //Replace these with your client id and secret + final String clientId = "clientId"; + final String clientSecret = "clientSecret"; + final String clientDomain = "https://example.com"; + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope("openid all") + .callback("https://example.com/callback") + .build(FrappeApi.instance(clientDomain)); + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth 2.0 Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + // Trade the Authorization Code for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, clientDomain + PROTECTED_RESOURCE_PATH); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FreelancerExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FreelancerExample.java new file mode 100644 index 000000000..023d789c4 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/FreelancerExample.java @@ -0,0 +1,72 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.FreelancerApi; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class FreelancerExample { + + private static final String NETWORK_NAME = "Freelancer"; + private static final String AUTHORIZE_URL + = "http://www.sandbox.freelancer.com/users/api-token/auth.php?oauth_token="; + private static final String PROTECTED_RESOURCE_URL = "http://api.sandbox.freelancer.com/Job/getJobList.json"; + private static final String SCOPE = "http://api.sandbox.freelancer.com"; + + private FreelancerExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + final OAuth10aService service = new ServiceBuilder("your client id") + .apiSecret("your client secret") + .withScope(SCOPE) + .build(FreelancerApi.Sandbox.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println("(The raw response looks like this: " + requestToken.getRawResponse() + "')"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(AUTHORIZE_URL + requestToken.getToken()); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + request.addHeader("GData-Version", "3.0"); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/GeniusExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/GeniusExample.java new file mode 100644 index 000000000..9749a168e --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/GeniusExample.java @@ -0,0 +1,89 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; + +import com.github.scribejava.apis.GeniusApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class GeniusExample { + + private static final String NETWORK_NAME = "Genius"; + private static final String PROTECTED_RESOURCE_URL = "https://api.genius.com/songs/378195"; + + private GeniusExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String secretState = "100"; + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope("me") + .callback("com.scribejavatest://callback") + .userAgent("ScribeJava") + .build(GeniusApi.instance()); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code; + final String value; + try (Scanner in = new Scanner(System.in, "UTF-8")) { + code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + + "'."); + System.out.print(">>"); + value = in.nextLine(); + } + + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(View Access Token contents: " + accessToken + + ", 'rawResponse'='" + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Accessing a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Viewing contents..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/GitHubAsyncOkHttpExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/GitHubAsyncOkHttpExample.java new file mode 100644 index 000000000..a0c94792c --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/GitHubAsyncOkHttpExample.java @@ -0,0 +1,86 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.GitHubApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.httpclient.okhttp.OkHttpHttpClientConfig; + +import java.io.IOException; +import java.util.Random; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class GitHubAsyncOkHttpExample { + + private static final String NETWORK_NAME = "GitHub"; + private static final String PROTECTED_RESOURCE_URL = "https://api.github.com/user"; + + private GitHubAsyncOkHttpExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, ExecutionException, InterruptedException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + try (OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("http://www.example.com/oauth_callback/") + .httpClientConfig(OkHttpHttpClientConfig.defaultConfig()) + .build(GitHubApi.instance())) { + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/GitHubExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/GitHubExample.java new file mode 100644 index 000000000..bfd3f2512 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/GitHubExample.java @@ -0,0 +1,80 @@ +package com.github.scribejava.apis.examples; + +import java.util.Random; +import java.util.Scanner; +import com.github.scribejava.apis.GitHubApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class GitHubExample { + + private static final String NETWORK_NAME = "GitHub"; + private static final String PROTECTED_RESOURCE_URL = "https://api.github.com/user"; + + private GitHubExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("http://www.example.com/oauth_callback/") + .build(GitHubApi.instance()); + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20ArmeriaExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20ArmeriaExample.java new file mode 100644 index 000000000..04fddb1da --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20ArmeriaExample.java @@ -0,0 +1,118 @@ +package com.github.scribejava.apis.examples; + +import java.util.Random; +import java.util.Scanner; +import com.github.scribejava.apis.GoogleApi20; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.httpclient.armeria.ArmeriaHttpClientConfig; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +public class Google20ArmeriaExample { + + private static final String NETWORK_NAME = "Google Armeria"; + private static final String PROTECTED_RESOURCE_URL = "https://www.googleapis.com/oauth2/v3/userinfo"; + + private Google20ArmeriaExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws InterruptedException, ExecutionException, IOException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + + try (OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope("profile") // replace with desired scope + .callback("http://example.com/callback") + .httpClientConfig(ArmeriaHttpClientConfig.defaultConfig()) + .build(GoogleApi20.instance())) { + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + //pass access_type=offline to get refresh token + //https://developers.google.com/identity/protocols/OAuth2WebServer#preparing-to-start-the-oauth-20-flow + final Map additionalParams = new HashMap<>(); + additionalParams.put("access_type", "offline"); + //force to reget refresh token (if user are asked not the first time) + additionalParams.put("prompt", "consent"); + final String authorizationUrl = service.createAuthorizationUrlBuilder() + .state(secretState) + .additionalParams(additionalParams) + .build(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + + "')"); + + System.out.println("Refreshing the Access Token..."); + accessToken = service.refreshAccessToken(accessToken.getRefreshToken()); + System.out.println("Refreshed the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + while (true) { + System.out.println("Paste fieldnames to fetch (leave empty to get profile, 'exit' to stop example)"); + System.out.print(">>"); + final String query = in.nextLine(); + System.out.println(); + + final String requestUrl; + if ("exit".equals(query)) { + break; + } else if (query == null || query.isEmpty()) { + requestUrl = PROTECTED_RESOURCE_URL; + } else { + requestUrl = PROTECTED_RESOURCE_URL + "?fields=" + query; + } + + final OAuthRequest request = new OAuthRequest(Verb.GET, requestUrl); + service.signRequest(accessToken, request); + System.out.println(); + try (Response response = service.execute(request)) { + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + } + } + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20AsyncAHCExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20AsyncAHCExample.java new file mode 100644 index 000000000..a894db2bf --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20AsyncAHCExample.java @@ -0,0 +1,126 @@ +package com.github.scribejava.apis.examples; + +import java.util.Random; +import java.util.Scanner; +import com.github.scribejava.apis.GoogleApi20; +import com.github.scribejava.httpclient.ahc.AhcHttpClientConfig; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import org.asynchttpclient.DefaultAsyncHttpClientConfig; + +public class Google20AsyncAHCExample { + + private static final String NETWORK_NAME = "Google Async"; + private static final String PROTECTED_RESOURCE_URL = "https://www.googleapis.com/oauth2/v3/userinfo"; + + private Google20AsyncAHCExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws InterruptedException, ExecutionException, IOException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + final HttpClientConfig clientConfig = new AhcHttpClientConfig(new DefaultAsyncHttpClientConfig.Builder() + .setMaxConnections(5) + .setRequestTimeout(10_000) + .setPooledConnectionIdleTimeout(1_000) + .setReadTimeout(1_000) + .build()); + + try (OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope("profile") // replace with desired scope + .callback("http://example.com/callback") + .httpClientConfig(clientConfig) + .build(GoogleApi20.instance())) { + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + //pass access_type=offline to get refresh token + //https://developers.google.com/identity/protocols/OAuth2WebServer#preparing-to-start-the-oauth-20-flow + final Map additionalParams = new HashMap<>(); + additionalParams.put("access_type", "offline"); + //force to reget refresh token (if user are asked not the first time) + additionalParams.put("prompt", "consent"); + final String authorizationUrl = service.createAuthorizationUrlBuilder() + .state(secretState) + .additionalParams(additionalParams) + .build(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + + "')"); + + System.out.println("Refreshing the Access Token..."); + accessToken = service.refreshAccessToken(accessToken.getRefreshToken()); + System.out.println("Refreshed the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + while (true) { + System.out.println("Paste fieldnames to fetch (leave empty to get profile, 'exit' to stop example)"); + System.out.print(">>"); + final String query = in.nextLine(); + System.out.println(); + + final String requestUrl; + if ("exit".equals(query)) { + break; + } else if (query == null || query.isEmpty()) { + requestUrl = PROTECTED_RESOURCE_URL; + } else { + requestUrl = PROTECTED_RESOURCE_URL + "?fields=" + query; + } + + final OAuthRequest request = new OAuthRequest(Verb.GET, requestUrl); + service.signRequest(accessToken, request); + System.out.println(); + try (Response response = service.execute(request)) { + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + } + } + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20DeviceAuthorizationGrantExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20DeviceAuthorizationGrantExample.java new file mode 100644 index 000000000..fc361e13f --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20DeviceAuthorizationGrantExample.java @@ -0,0 +1,82 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.GoogleApi20; +import com.github.scribejava.core.model.DeviceAuthorization; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class Google20DeviceAuthorizationGrantExample { + + private static final String NETWORK_NAME = "Google"; + private static final String PROTECTED_RESOURCE_URL = "https://www.googleapis.com/oauth2/v3/userinfo"; + + private Google20DeviceAuthorizationGrantExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your_client_secret"; + + final OAuth20Service service = new ServiceBuilder(clientId) + .debug() + .apiSecret(clientSecret) + .defaultScope("profile") // replace with desired scope + .build(GoogleApi20.instance()); + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + System.out.println("Requesting a set of verification codes..."); + + final DeviceAuthorization deviceAuthorization = service.getDeviceAuthorizationCodes(); + System.out.println("Got the Device Authorization Codes!"); + System.out.println(deviceAuthorization); + + System.out.println("Now go and authorize ScribeJava. Visit: " + deviceAuthorization.getVerificationUri() + + " and enter the code: " + deviceAuthorization.getUserCode()); + if (deviceAuthorization.getVerificationUriComplete() != null) { + System.out.println("Or visit " + deviceAuthorization.getVerificationUriComplete()); + } + + System.out.println("Polling for an Access Token..."); + final OAuth2AccessToken accessToken = service.pollAccessTokenDeviceAuthorizationGrant(deviceAuthorization); + + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + while (true) { + System.out.println("Paste fieldnames to fetch (leave empty to get profile, 'exit' to stop the example)"); + System.out.print(">>"); + final String query = in.nextLine(); + System.out.println(); + final String requestUrl; + if ("exit".equals(query)) { + break; + } else if (query == null || query.isEmpty()) { + requestUrl = PROTECTED_RESOURCE_URL; + } else { + requestUrl = PROTECTED_RESOURCE_URL + "?fields=" + query; + } + final OAuthRequest request = new OAuthRequest(Verb.GET, requestUrl); + service.signRequest(accessToken, request); + System.out.println(); + try (Response response = service.execute(request)) { + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + } + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20Example.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20Example.java new file mode 100644 index 000000000..ca70409f4 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20Example.java @@ -0,0 +1,111 @@ +package com.github.scribejava.apis.examples; + +import java.util.Random; +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.GoogleApi20; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +public class Google20Example { + + private static final String NETWORK_NAME = "Google"; + private static final String PROTECTED_RESOURCE_URL = "https://www.googleapis.com/oauth2/v3/userinfo"; + + private Google20Example() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your_client_id"; + final String clientSecret = "your_client_secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope("profile") // replace with desired scope + .callback("http://example.com/callback") + .build(GoogleApi20.instance()); + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + //pass access_type=offline to get refresh token + //https://developers.google.com/identity/protocols/OAuth2WebServer#preparing-to-start-the-oauth-20-flow + final Map additionalParams = new HashMap<>(); + additionalParams.put("access_type", "offline"); + //force to reget refresh token (if user are asked not the first time) + additionalParams.put("prompt", "consent"); + final String authorizationUrl = service.createAuthorizationUrlBuilder() + .state(secretState) + .additionalParams(additionalParams) + .build(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + + System.out.println("Refreshing the Access Token..."); + accessToken = service.refreshAccessToken(accessToken.getRefreshToken()); + System.out.println("Refreshed the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + while (true) { + System.out.println("Paste fieldnames to fetch (leave empty to get profile, 'exit' to stop example)"); + System.out.print(">>"); + final String query = in.nextLine(); + System.out.println(); + + final String requestUrl; + if ("exit".equals(query)) { + break; + } else if (query == null || query.isEmpty()) { + requestUrl = PROTECTED_RESOURCE_URL; + } else { + requestUrl = PROTECTED_RESOURCE_URL + "?fields=" + query; + } + + final OAuthRequest request = new OAuthRequest(Verb.GET, requestUrl); + service.signRequest(accessToken, request); + System.out.println(); + try (Response response = service.execute(request)) { + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + } + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20RevokeExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20RevokeExample.java new file mode 100644 index 000000000..ba513ca52 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20RevokeExample.java @@ -0,0 +1,109 @@ +package com.github.scribejava.apis.examples; + +import java.util.Random; +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.GoogleApi20; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +public class Google20RevokeExample { + + private static final String NETWORK_NAME = "Google"; + private static final String PROTECTED_RESOURCE_URL = "https://www.googleapis.com/oauth2/v3/userinfo"; + + private Google20RevokeExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope("profile") // replace with desired scope + .callback("http://example.com/callback") + .build(GoogleApi20.instance()); + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + //pass access_type=offline to get refresh token + //https://developers.google.com/identity/protocols/OAuth2WebServer#preparing-to-start-the-oauth-20-flow + final Map additionalParams = new HashMap<>(); + additionalParams.put("access_type", "offline"); + //force to reget refresh token (if user are asked not the first time) + additionalParams.put("prompt", "consent"); + final String authorizationUrl = service.createAuthorizationUrlBuilder() + .state(secretState) + .additionalParams(additionalParams) + .build(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + System.out.println(); + try (Response response = service.execute(request)) { + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Revoking token..."); + service.revokeToken(accessToken.getAccessToken()); + System.out.println("done."); + System.out.println("After revoke we should fail requesting any data... Press enter to try"); + in.nextLine(); + //Google Note: Following a successful revocation response, + //it might take some time before the revocation has full effect. + int responseCode; + do { + Thread.sleep(1000); + request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + System.out.println(); + try (Response response = service.execute(request)) { + responseCode = response.getCode(); + System.out.println(responseCode); + System.out.println(response.getBody()); + } + System.out.println(); + } while (responseCode == 200); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20WithPKCEExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20WithPKCEExample.java new file mode 100644 index 000000000..8c840b8d5 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20WithPKCEExample.java @@ -0,0 +1,117 @@ +package com.github.scribejava.apis.examples; + +import java.util.Random; +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.GoogleApi20; +import com.github.scribejava.core.oauth.AuthorizationUrlBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.AccessTokenRequestParams; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +public class Google20WithPKCEExample { + + private static final String NETWORK_NAME = "Google"; + private static final String PROTECTED_RESOURCE_URL = "https://www.googleapis.com/oauth2/v3/userinfo"; + + private Google20WithPKCEExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope("profile") // replace with desired scope + .callback("http://example.com/callback") + .build(GoogleApi20.instance()); + + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + //pass access_type=offline to get refresh token + //https://developers.google.com/identity/protocols/OAuth2WebServer#preparing-to-start-the-oauth-20-flow + final Map additionalParams = new HashMap<>(); + additionalParams.put("access_type", "offline"); + //force to reget refresh token (if user are asked not the first time) + additionalParams.put("prompt", "consent"); + + final AuthorizationUrlBuilder authorizationUrlBuilder = service.createAuthorizationUrlBuilder() + .state(secretState) + .additionalParams(additionalParams) + .initPKCE(); + + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrlBuilder.build()); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + OAuth2AccessToken accessToken = service.getAccessToken(AccessTokenRequestParams.create(code) + .pkceCodeVerifier(authorizationUrlBuilder.getPkce().getCodeVerifier())); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + + System.out.println("Refreshing the Access Token..."); + accessToken = service.refreshAccessToken(accessToken.getRefreshToken()); + System.out.println("Refreshed the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + while (true) { + System.out.println("Paste fieldnames to fetch (leave empty to get profile, 'exit' to stop example)"); + System.out.print(">>"); + final String query = in.nextLine(); + System.out.println(); + + final String requestUrl; + if ("exit".equals(query)) { + break; + } else if (query == null || query.isEmpty()) { + requestUrl = PROTECTED_RESOURCE_URL; + } else { + requestUrl = PROTECTED_RESOURCE_URL + "?fields=" + query; + } + + final OAuthRequest request = new OAuthRequest(Verb.GET, requestUrl); + service.signRequest(accessToken, request); + System.out.println(); + try (Response response = service.execute(request)) { + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + } + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/HHExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/HHExample.java new file mode 100644 index 000000000..c013b7d2b --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/HHExample.java @@ -0,0 +1,67 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; + +import com.github.scribejava.apis.HHApi; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class HHExample { + + private static final String NETWORK_NAME = "hh.ru"; + private static final String PROTECTED_RESOURCE_URL = "https://api.hh.ru/me"; + + private HHExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your own client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("http://your.site.com/callback") + .build(HHApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/HiOrgServerExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/HiOrgServerExample.java new file mode 100644 index 000000000..2602d1257 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/HiOrgServerExample.java @@ -0,0 +1,92 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.HiOrgServerApi20; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.Random; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class HiOrgServerExample { + + private static final String NETWORK_NAME = "HiOrgServer"; + private static final String PROTECTED_RESOURCE_URL = "https://www.hiorg-server.de/api/oauth2/v1/user.php"; + private static final String CLIENT_ID = "your client id"; + private static final String CLIENT_SECRET = "your client secret"; + private static final String CALLBACK_URL = "http://www.example.com/oauth_callback/"; + + private HiOrgServerExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = CLIENT_ID; + final String clientSecret = CLIENT_SECRET; + final String secretState = "secret" + new Random().nextInt(999_999); + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope("basic eigenedaten") + .callback(CALLBACK_URL) + .build(HiOrgServerApi20.instance()); + + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + System.out.println("Refreshing the Access Token..."); + accessToken = service.refreshAccessToken(accessToken.getRefreshToken()); + System.out.println("Refreshed the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } + +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/ImgurExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/ImgurExample.java new file mode 100644 index 000000000..229e3a7ee --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/ImgurExample.java @@ -0,0 +1,67 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.ImgurApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; + +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class ImgurExample { + + private static final String NETWORK_NAME = "Imgur"; + private static final String PROTECTED_RESOURCE_URL = "https://api.imgur.com/3/account/me"; + + private ImgurExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your own api key and secret + final String apiKey = "your client id"; + final String apiSecret = "your client secret"; + final OAuth20Service service = new ServiceBuilder(apiKey) + .apiSecret(apiSecret) + .build(ImgurApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/InstagramExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/InstagramExample.java new file mode 100644 index 000000000..9694ba909 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/InstagramExample.java @@ -0,0 +1,97 @@ +package com.github.scribejava.apis.examples; + +import java.io.IOException; +import java.util.Random; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; +import com.github.scribejava.apis.InstagramApi; +import com.github.scribejava.apis.instagram.InstagramService; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +public class InstagramExample { + + private static final String NETWORK_NAME = "Instagram"; + private static final String PROTECTED_RESOURCE_URL + = "https://graph.instagram.com/me/media?fields=id,caption,media_type,media_url,username"; + + private InstagramExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "client-id"; + final String clientSecret = "client-secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope("user_profile,user_media") + .callback("http://example.com") + .build(InstagramApi.instance()); + + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + final InstagramService instagramService = (InstagramService) service; + System.out.println("Now let's exchange our short-lived token to long-lived access token..."); + final OAuth2AccessToken longLivedAccessToken = instagramService.getLongLivedAccessToken(accessToken); + System.out.println("Got the Access Token!"); + System.out.println("(The access token raw response looks like this: " + longLivedAccessToken.getRawResponse() + + "')"); + + System.out.println("Now it's time to refresh long-lived token..."); + final OAuth2AccessToken refreshAccessToken = service.refreshAccessToken(longLivedAccessToken.getAccessToken()); + System.out.println("Got the refreshed Access Token!"); + System.out.println("(The refreshed access token raw response looks like this: " + + refreshAccessToken.getRawResponse() + "')"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Kaixin20Example.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Kaixin20Example.java new file mode 100644 index 000000000..482453cb4 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Kaixin20Example.java @@ -0,0 +1,68 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.KaixinApi20; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class Kaixin20Example { + + private static final String NETWORK_NAME = "Kaixin"; + private static final String PROTECTED_RESOURCE_URL = "https://api.kaixin001.com/users/me.json"; + + private Kaixin20Example() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your own api key and secret + final String apiKey = "your api key"; + final String apiSecret = "your api secret"; + final OAuth20Service service = new ServiceBuilder(apiKey) + .apiSecret(apiSecret) + .callback("http://your.domain.com/handle") + .build(KaixinApi20.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/KakaoExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/KakaoExample.java new file mode 100644 index 000000000..643182ea8 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/KakaoExample.java @@ -0,0 +1,70 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.KakaoApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.IOException; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class KakaoExample { + + private static final String NETWORK_NAME = "Kakao"; + private static final String PROTECTED_RESOURCE_URL = "https://kapi.kakao.com/v2/user/me"; + + private KakaoExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace this with your client id + final String clientId = "your client id"; + + final OAuth20Service service = new ServiceBuilder(clientId) + .callback("http://www.example.com/oauth_callback/") + .build(KakaoApi.instance()); + + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/KeycloakExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/KeycloakExample.java new file mode 100644 index 000000000..2d78ffb97 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/KeycloakExample.java @@ -0,0 +1,72 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.KeycloakApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.IOException; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class KeycloakExample { + + private KeycloakExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your own api key, secret, callback, base url and realm + final String apiKey = "your_api_key"; + final String apiSecret = "your_api_secret"; + final String callback = "your_callback"; + final String baseUrl = "your_base_url"; + final String realm = "your_realm"; + + final String protectedResourceUrl = baseUrl + "/auth/realms/" + realm + "/protocol/openid-connect/userinfo"; + + final OAuth20Service service = new ServiceBuilder(apiKey) + .apiSecret(apiSecret) + .defaultScope("openid") + .callback(callback) + .build(KeycloakApi.instance(baseUrl, realm)); + final Scanner in = new Scanner(System.in); + + System.out.println("=== Keyloack's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, protectedResourceUrl); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LinkedIn20Example.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LinkedIn20Example.java new file mode 100644 index 000000000..05e6733df --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LinkedIn20Example.java @@ -0,0 +1,85 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.LinkedInApi20; +import com.github.scribejava.core.builder.ScopeBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.Random; +import java.util.concurrent.ExecutionException; + +public class LinkedIn20Example { + + private static final String NETWORK_NAME = "LinkedIn"; + private static final String PROTECTED_RESOURCE_URL = "https://api.linkedin.com/v2/me"; + private static final String PROTECTED_EMAIL_RESOURCE_URL + = "https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))"; + + private LinkedIn20Example() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope(new ScopeBuilder("r_liteprofile", "r_emailaddress")) // replace with desired scope + .callback("http://example.com/callback") + .build(LinkedInApi20.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String secretState = "secret" + new Random().nextInt(999_999); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + System.out.println("Now we're going to get the email of the current user..."); + final OAuthRequest emailRequest = new OAuthRequest(Verb.GET, PROTECTED_EMAIL_RESOURCE_URL); + emailRequest.addHeader("x-li-format", "json"); + emailRequest.addHeader("Accept-Language", "ru-RU"); + service.signRequest(accessToken, emailRequest); + System.out.println(); + try (Response emailResponse = service.execute(emailRequest)) { + System.out.println(emailResponse.getCode()); + System.out.println(emailResponse.getBody()); + } + System.out.println(); + + System.out.println("Now we're going to access a protected profile resource..."); + + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + request.addHeader("x-li-format", "json"); + request.addHeader("Accept-Language", "ru-RU"); + service.signRequest(accessToken, request); + System.out.println(); + try (Response response = service.execute(request)) { + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LinkedInExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LinkedInExample.java new file mode 100644 index 000000000..ec1051134 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LinkedInExample.java @@ -0,0 +1,67 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.LinkedInApi; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class LinkedInExample { + + private static final String PROTECTED_RESOURCE_URL + = "http://api.linkedin.com/v1/people/~/connections:(id,last-name)"; + + private LinkedInExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + final OAuth10aService service = new ServiceBuilder("your client id") + .apiSecret("your client secret") + .build(LinkedInApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== LinkedIn's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(service.getAuthorizationUrl(requestToken)); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } + +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LinkedInExampleWithScopes.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LinkedInExampleWithScopes.java new file mode 100644 index 000000000..3b795de1f --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LinkedInExampleWithScopes.java @@ -0,0 +1,71 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.LinkedInApi; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class LinkedInExampleWithScopes { + + private static final String PROTECTED_RESOURCE_URL + = "http://api.linkedin.com/v1/people/~/connections:(id,last-name)"; + + private LinkedInExampleWithScopes() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client id"; + + final OAuth10aService service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .build(LinkedInApi.instance("foo", "bar", "baz")); + final Scanner in = new Scanner(System.in); + + System.out.println("=== LinkedIn's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(service.getAuthorizationUrl(requestToken)); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } + +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LiveExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LiveExample.java new file mode 100644 index 000000000..2c8635a1a --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LiveExample.java @@ -0,0 +1,68 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.LiveApi; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class LiveExample { + + private static final String PROTECTED_RESOURCE_URL = "https://apis.live.net/v5.0/me"; + + private LiveExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your own api key and secret + final String apiKey = ""; + final String apiSecret = ""; + final OAuth20Service service = new ServiceBuilder(apiKey) + .apiSecret(apiSecret) + .defaultScope("wl.basic") + .callback("http://localhost:9000/") + .build(LiveApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== Windows Live's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MailruAsyncExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MailruAsyncExample.java new file mode 100644 index 000000000..1ad9f56cc --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MailruAsyncExample.java @@ -0,0 +1,82 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.httpclient.ning.NingHttpClientConfig; +import com.ning.http.client.AsyncHttpClientConfig; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; +import com.github.scribejava.apis.MailruApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; + +public class MailruAsyncExample { + + private static final String NETWORK_NAME = "Mail.ru"; + private static final String PROTECTED_RESOURCE_URL + = "http://www.appsmail.ru/platform/api?method=users.getInfo&secure=1"; + + private MailruAsyncExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws InterruptedException, ExecutionException, IOException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + + final NingHttpClientConfig clientConfig = new NingHttpClientConfig(new AsyncHttpClientConfig.Builder() + .setMaxConnections(5) + .setRequestTimeout(10_000) + .setAllowPoolingConnections(false) + .setPooledConnectionIdleTimeout(1_000) + .setReadTimeout(10_000) + .build()); + + try (OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("http://www.example.com/oauth_callback/") + .httpClientConfig(clientConfig) + .build(MailruApi.instance())) { + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s Async OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + + "')"); + System.out.println(); + + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MailruExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MailruExample.java new file mode 100644 index 000000000..4eb4c7aff --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MailruExample.java @@ -0,0 +1,68 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.apis.MailruApi; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class MailruExample { + + private static final String NETWORK_NAME = "Mail.ru"; + private static final String PROTECTED_RESOURCE_URL + = "http://www.appsmail.ru/platform/api?method=users.getInfo&secure=1"; + + private MailruExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("http://www.example.com/oauth_callback/") + .build(MailruApi.instance()); + + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MediaWikiExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MediaWikiExample.java new file mode 100644 index 000000000..621480013 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MediaWikiExample.java @@ -0,0 +1,72 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.MediaWikiApi; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class MediaWikiExample { + + // To get your consumer key/secret, see https://meta.wikimedia.org/wiki/Special:OAuthConsumerRegistration/propose + private static final String CONSUMER_KEY = ""; + private static final String CONSUMER_SECRET = ""; + + private static final String API_USERINFO_URL + = "https://meta.wikimedia.org/w/api.php?action=query&format=json&meta=userinfo"; + + private MediaWikiExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + final OAuth10aService service = new ServiceBuilder(CONSUMER_KEY) + .apiSecret(CONSUMER_SECRET) + .build(MediaWikiApi.instance()); + + final Scanner in = new Scanner(System.in); + + System.out.println("=== MediaWiki's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(service.getAuthorizationUrl(requestToken)); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, API_USERINFO_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with MediaWiki and ScribeJava! :)"); + } + +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Meetup20Example.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Meetup20Example.java new file mode 100644 index 000000000..f64ec246b --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Meetup20Example.java @@ -0,0 +1,70 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.MeetupApi20; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.IOException; +import java.util.Random; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class Meetup20Example { + + private static final String NETWORK_NAME = "Meetup"; + private static final String PROTECTED_RESOURCE_URL = " https://api.meetup.com/self/groups"; + + private Meetup20Example() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your Meetup consumer id and secret + final String consumerKey = "your consumer key"; + final String consumerSecret = "your consumer secret"; + final OAuth20Service service = new ServiceBuilder(consumerKey) + .apiSecret(consumerSecret) + .defaultScope("basic") // replace with desired scopes + .callback("http://example.com/callback") // replace with appropriate URI for your consumer, + // see https://www.meetup.com/meetup_api/auth/#redirect_uris + .build(MeetupApi20.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String secretState = "secret" + new Random().nextInt(999_999); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + System.out.println("Now we're going to the user's groups...."); + + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + System.out.println(); + try (Response response = service.execute(request)) { + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MeetupExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MeetupExample.java new file mode 100644 index 000000000..e3c7c8e8c --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MeetupExample.java @@ -0,0 +1,65 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.MeetupApi; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class MeetupExample { + + private static final String PROTECTED_RESOURCE_URL = "http://api.meetup.com/2/member/self"; + + private MeetupExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + final OAuth10aService service = new ServiceBuilder("your client id") + .apiSecret("your client secret") + .build(MeetupApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== Meetup's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(service.getAuthorizationUrl(requestToken)); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MicrosoftAzureActiveDirectory20Example.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MicrosoftAzureActiveDirectory20Example.java new file mode 100644 index 000000000..71f346bc6 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MicrosoftAzureActiveDirectory20Example.java @@ -0,0 +1,63 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.MicrosoftAzureActiveDirectory20Api; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class MicrosoftAzureActiveDirectory20Example { + + private static final String NETWORK_NAME = "Microsoft Azure Active Directory"; + private static final String PROTECTED_RESOURCE_URL = "https://graph.microsoft.com/v1.0/me"; + + private MicrosoftAzureActiveDirectory20Example() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "client id here"; + final String clientSecret = "client secret here"; + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope("openid User.Read") + .callback("http://www.example.com/oauth_callback/") + .build(MicrosoftAzureActiveDirectory20Api.instance()); + final Scanner in = new Scanner(System.in, "UTF-8"); + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MicrosoftAzureActiveDirectoryExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MicrosoftAzureActiveDirectoryExample.java new file mode 100644 index 000000000..6c9610f06 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MicrosoftAzureActiveDirectoryExample.java @@ -0,0 +1,70 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.MicrosoftAzureActiveDirectoryApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.IOException; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class MicrosoftAzureActiveDirectoryExample { + + private static final String NETWORK_NAME = "Microsoft Azure Active Directory"; + private static final String PROTECTED_RESOURCE_URL = "https://graph.windows.net/me?api-version=1.6"; + + private MicrosoftAzureActiveDirectoryExample() { + + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "client id here"; + final String clientSecret = "client secret here"; + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope("openid") + .callback("http://www.example.com/oauth_callback/") + .build(MicrosoftAzureActiveDirectoryApi.instance()); + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MisfitExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MisfitExample.java new file mode 100644 index 000000000..65e048499 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MisfitExample.java @@ -0,0 +1,71 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.MisfitApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; + +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class MisfitExample { + + private static final String NETWORK_NAME = "Misfit"; + private static final String PROTECTED_RESOURCE_URL + = "https://api.misfitwearables.com/move/resource/v1/user/me/profile"; + + private MisfitExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your own api key and secret + final String apiKey = "your client id"; + final String apiSecret = "your client secret"; + final OAuth20Service service = new ServiceBuilder(apiKey) + .apiSecret(apiSecret) + .callback("http://example.com/callback/") + .defaultScope("public,birthday,email,tracking,session,sleep") + .build(MisfitApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/NaverExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/NaverExample.java new file mode 100644 index 000000000..7918ebd02 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/NaverExample.java @@ -0,0 +1,84 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.NaverApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.IOException; +import java.util.Random; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class NaverExample { + + private static final String NETWORK_NAME = "Naver"; + private static final String PROTECTED_RESOURCE_URL = "https://openapi.naver.com/v1/nid/me"; + + private NaverExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("http://www.example.com/oauth_callback/") + .build(NaverApi.instance()); + + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/OdnoklassnikiExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/OdnoklassnikiExample.java new file mode 100644 index 000000000..ff2c05863 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/OdnoklassnikiExample.java @@ -0,0 +1,77 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.OdnoklassnikiApi; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class OdnoklassnikiExample { + + private static final String NETWORK_NAME = "Odnoklassniki.ru"; + private static final String PROTECTED_RESOURCE_URL + = "https://api.ok.ru/api/users/getCurrentUser?application_key=%1$s&format=JSON"; + + private OdnoklassnikiExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your api client id"; + final String publicKey = "your api public key"; + final String secretKey = "your api secret key"; + + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(secretKey) + .callback("http://your.site.com/callback") + .build(OdnoklassnikiApi.instance()); + + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + System.out.println("Refreshing the Access Token..."); + accessToken = service.refreshAccessToken(accessToken.getRefreshToken()); + System.out.println("Refreshed the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, String.format(PROTECTED_RESOURCE_URL, publicKey)); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/PinterestExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/PinterestExample.java new file mode 100644 index 000000000..73ad113d5 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/PinterestExample.java @@ -0,0 +1,69 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.PinterestApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; + +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class PinterestExample { + + private static final String PROTECTED_RESOURCE_URL = "https://api.pinterest.com/v1/me/"; + + private PinterestExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your own api key and secret + final String apiKey = "your_app_id"; + final String apiSecret = "your_app_secret"; + final OAuth20Service service = new ServiceBuilder(apiKey) + .apiSecret(apiSecret) + .defaultScope("read_public,write_public,read_relationships,write_relationships") + .callback("https://localhost/") // Add as valid callback in developer portal + .build(PinterestApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== Pinterest's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/PolarAPIExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/PolarAPIExample.java new file mode 100644 index 000000000..501a8e470 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/PolarAPIExample.java @@ -0,0 +1,82 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.PolarAPI; +import com.github.scribejava.apis.polar.PolarOAuth2AccessToken; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.util.Scanner; + +public class PolarAPIExample { + + private static final String NETWORK_NAME = "Polar"; + + private static final String PROTECTED_RESOURCE_URL = "https://www.polaraccesslink.com/v3/users/%s"; + + private PolarAPIExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws Exception { + final String clientId = "your_api_client"; + final String clientSecret = "your_api_secret"; + final String scope = "accesslink.read_all"; + final String callback = "your_api_callback"; + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope(scope) + //your callback URL to store and handle the authorization code sent by Polar + .callback(callback) + .build(PolarAPI.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl("some_params"); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + System.out.println("Got the Access Token!"); + final OAuth2AccessToken oauth2AccessToken = service.getAccessToken(code); + System.out.println("(if your curious it looks like this: " + oauth2AccessToken + + ", 'rawResponse'='" + oauth2AccessToken.getRawResponse() + "')"); + System.out.println(); + + if (!(oauth2AccessToken instanceof PolarOAuth2AccessToken)) { + System.out.println("oauth2AccessToken is not instance of PolarOAuth2AccessToken. Strange enough. exit."); + return; + } + + final PolarOAuth2AccessToken accessToken = (PolarOAuth2AccessToken) oauth2AccessToken; + + // Now let's go and ask for a protected resource! + // This will get the profile for this user + System.out.println("Now we're going to access a protected resource..."); + + final OAuthRequest request = new OAuthRequest(Verb.GET, String.format(PROTECTED_RESOURCE_URL, + accessToken.getUserId())); + request.addHeader("Accept", "application/json"); + + service.signRequest(accessToken, request); + + System.out.println(); + try (Response response = service.execute(request)) { + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Px500Example.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Px500Example.java new file mode 100644 index 000000000..e441cebdd --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Px500Example.java @@ -0,0 +1,67 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.Px500Api; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class Px500Example { + + private static final String PROTECTED_RESOURCE_URL = "https://api.500px.com/v1/"; + + private Px500Example() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + final OAuth10aService service = new ServiceBuilder("your-api-key") + .apiSecret("your-api-secret") + .build(Px500Api.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== 500Px's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(service.getAuthorizationUrl(requestToken)); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } + +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/RenrenExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/RenrenExample.java new file mode 100644 index 000000000..701be48b4 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/RenrenExample.java @@ -0,0 +1,114 @@ +package com.github.scribejava.apis.examples; + +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.Map; +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.RenrenApi; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Formatter; +import java.util.List; +import java.util.concurrent.ExecutionException; + +public class RenrenExample { + + private static final String NETWORK_NAME = "Renren"; + private static final String PROTECTED_RESOURCE_URL = "http://api.renren.com/restserver.do"; + + private RenrenExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your own api key and secret + final String apiKey = "your api key"; + final String apiSecret = "your api secret"; + final OAuth20Service service = new ServiceBuilder(apiKey) + .apiSecret(apiSecret) + .defaultScope("status_update publish_feed") + .callback("http://your.doman.com/oauth/renren") + .build(RenrenApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.POST, PROTECTED_RESOURCE_URL); + final Map parameters = new HashMap<>(); + parameters.put("method", "users.getInfo"); + parameters.put("format", "json"); + parameters.put("v", "1.0"); + + final List sigString = new ArrayList<>(parameters.size() + 1); + for (Map.Entry parameter : parameters.entrySet()) { + request.addQuerystringParameter(parameter.getKey(), parameter.getValue()); + sigString.add(String.format("%s=%s", parameter.getKey(), parameter.getValue())); + } + sigString.add(String.format("%s=%s", OAuthConstants.ACCESS_TOKEN, accessToken.getAccessToken())); + Collections.sort(sigString); + final StringBuilder sigBuilder = new StringBuilder(); + for (String param : sigString) { + sigBuilder.append(param); + } + sigBuilder.append(apiSecret); + + final String sig = sigBuilder.toString(); + System.out.println("Sig string: " + sig); + request.addQuerystringParameter("sig", md5(sig)); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } + + public static String md5(String orgString) { + try { + final MessageDigest md = MessageDigest.getInstance("MD5"); + final byte[] array = md.digest(orgString.getBytes(Charset.forName("UTF-8"))); + final Formatter builder = new Formatter(); + for (byte b : array) { + builder.format("%02x", b); + } + return builder.toString(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException("MD5 is unsupported?", e); + } + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SalesforceExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SalesforceExample.java new file mode 100644 index 000000000..6e8ce342a --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SalesforceExample.java @@ -0,0 +1,104 @@ +package com.github.scribejava.apis.examples; + +import java.io.IOException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.Scanner; + +import com.github.scribejava.apis.SalesforceApi; +import com.github.scribejava.apis.salesforce.SalesforceToken; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.concurrent.ExecutionException; + +public class SalesforceExample { + + private static final String NETWORK_NAME = "Salesforce"; + + private SalesforceExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, NoSuchAlgorithmException, KeyManagementException, + InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + //IT's important! Salesforce upper require TLS v1.1 or higher. + //They are enabled in Java 8 by default, but not in Java 7 + SalesforceApi.initTLSv11orUpper(); + + // The below used ServiceBuilder connects to login.salesforce.com + // (production environment). + // + // When you plan to connect to a Sandbox environment you've to use SalesforceApi.sandbox() API instance + // new ServiceBuilder.....build(SalesforceApi.sandbox()); + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("https://www.example.com/callback") + .build(SalesforceApi.instance()); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth20 Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code; + try (Scanner in = new Scanner(System.in)) { + code = in.nextLine(); + } + System.out.println(); + + // The code needs to be URL decoded + final String codeEncoded = URLDecoder.decode(code, "UTF-8"); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + + final OAuth2AccessToken accessToken = service.getAccessToken(codeEncoded); + final SalesforceToken salesforceAccessToken; + if (accessToken instanceof SalesforceToken) { + salesforceAccessToken = (SalesforceToken) accessToken; + } else { + throw new IllegalStateException("Salesforce API didn't return SalesforceToken."); + } + System.out.println("Got the Access Token!"); + + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + System.out.println("instance_url is: " + salesforceAccessToken.getInstanceUrl()); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're reading accounts from the Salesforce org (maxing them to 10)."); + + // Sample SOQL statement + final String queryEncoded = URLEncoder.encode("Select Id, Name from Account LIMIT 10", "UTF-8"); + + // Building the query URI. We've parsed the instance URL from the accessToken request. + final String url = salesforceAccessToken.getInstanceUrl() + "/services/data/v36.0/query?q=" + queryEncoded; + + System.out.println(); + System.out.println("Full URL: " + url); + + final OAuthRequest request = new OAuthRequest(Verb.GET, url); + service.signRequest(salesforceAccessToken, request); + System.out.println(); + try (Response response = service.execute(request)) { + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SalesforceNingAsyncExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SalesforceNingAsyncExample.java new file mode 100644 index 000000000..6c3987046 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SalesforceNingAsyncExample.java @@ -0,0 +1,101 @@ +package com.github.scribejava.apis.examples; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +import com.github.scribejava.apis.SalesforceApi; +import com.github.scribejava.apis.salesforce.SalesforceToken; +import com.github.scribejava.httpclient.ning.NingHttpClientConfig; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.ning.http.client.AsyncHttpClientConfig; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; + +public class SalesforceNingAsyncExample { + + private static final String NETWORK_NAME = "Salesforce"; + + private SalesforceNingAsyncExample() { + } + + @SuppressWarnings({"unchecked", "rawtypes", "PMD.SystemPrintln"}) + public static void main(String... args) throws InterruptedException, ExecutionException, + UnsupportedEncodingException, IOException, NoSuchAlgorithmException, KeyManagementException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + + final NingHttpClientConfig clientConfig = new NingHttpClientConfig(new AsyncHttpClientConfig.Builder() + .setMaxConnections(5) + .setRequestTimeout(10_000) + .setAllowPoolingConnections(false) + .setPooledConnectionIdleTimeout(1_000) + .setReadTimeout(10_000) + .build()); + + //IT's important! Salesforce upper require TLS v1.1 or higher + SalesforceApi.initTLSv11orUpper(); + try (OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .httpClientConfig(clientConfig) + .callback("https://www.example.com/callback") + .build(SalesforceApi.instance())) { + System.out.println("=== " + NETWORK_NAME + "'s OAuth20 Workflow ==="); + System.out.println(); + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code; + try (Scanner in = new Scanner(System.in)) { + code = in.nextLine(); + } + System.out.println(); + final String codeEncoded = URLDecoder.decode(code, "UTF-8"); + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + + final OAuth2AccessToken accessToken = service.getAccessToken(codeEncoded); + final SalesforceToken salesforceAccessToken; + if (accessToken instanceof SalesforceToken) { + salesforceAccessToken = (SalesforceToken) accessToken; + } else { + throw new IllegalStateException("Salesforce API didn't return SalesforceToken."); + } + System.out.println("Got the Access Token!"); + + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + + "')"); + System.out.println(); + System.out.println("Instance is: " + salesforceAccessToken.getInstanceUrl()); + // Now let's go and ask for a protected resource! + System.out.println("Now we're reading accounts from the Salesforce org (maxing them to 10)."); + // Sample SOQL statement + final String queryEncoded = URLEncoder.encode("Select Id, Name from Account LIMIT 10", "UTF-8"); + // Building the query URI. We've parsed the instance URL from the + // accessToken request. + final String url = salesforceAccessToken.getInstanceUrl() + "/services/data/v36.0/query?q=" + queryEncoded; + System.out.println(); + System.out.println("Full URL: " + url); + final OAuthRequest request = new OAuthRequest(Verb.GET, url); + System.out.println(); + try (Response response = service.execute(request)) { + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + } + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SinaWeibo2Example.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SinaWeibo2Example.java new file mode 100644 index 000000000..3ac982efb --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SinaWeibo2Example.java @@ -0,0 +1,69 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.SinaWeiboApi20; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class SinaWeibo2Example { + + private static final String NETWORK_NAME = "SinaWeibo"; + private static final String PROTECTED_RESOURCE_URL = "https://api.weibo.com/2/account/get_uid.json"; + + private SinaWeibo2Example() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your own api key and secret + final String apiKey = "your_api_key"; + final String apiSecret = "your_api_secret"; + final OAuth20Service service = new ServiceBuilder(apiKey) + .apiSecret(apiSecret) + .callback("http://www.dajie.com/oauth/sina") + .build(SinaWeiboApi20.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SinaWeiboExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SinaWeiboExample.java new file mode 100644 index 000000000..767ccdbab --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SinaWeiboExample.java @@ -0,0 +1,74 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.SinaWeiboApi; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class SinaWeiboExample { + + private static final String NETWORK_NAME = "SinaWeibo"; + private static final String PROTECTED_RESOURCE_URL = "http://api.t.sina.com.cn/account/verify_credentials.json"; + + private SinaWeiboExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your own api key and secret + final String apiKey = "your key"; + final String apiSecret = "your secret"; + final OAuth10aService service = new ServiceBuilder(apiKey) + .apiSecret(apiSecret) + .build(SinaWeiboApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Grab a request token. + System.out.println("Fetching request token."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got it ... "); + System.out.println(requestToken.getToken()); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(requestToken); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SkyrockExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SkyrockExample.java new file mode 100644 index 000000000..f2c0cf007 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SkyrockExample.java @@ -0,0 +1,68 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.SkyrockApi; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class SkyrockExample { + + private static final String PROTECTED_RESOURCE_URL = "https://api.skyrock.com/v2/user/get.json"; + + private SkyrockExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + final OAuth10aService service = new ServiceBuilder("your-api-key") + .apiSecret("your-api-secret") + .build(SkyrockApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== Skyrock's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(service.getAuthorizationUrl(requestToken)); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } + +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SlackExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SlackExample.java new file mode 100644 index 000000000..44a952d16 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/SlackExample.java @@ -0,0 +1,102 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.SlackApi; +import com.github.scribejava.apis.slack.SlackOAuth2AccessToken; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class SlackExample { + + private static final String NETWORK_NAME = "Slack.com"; + private static final String BOT_RESOURCE_URL = "https://slack.com/api/channels.list"; + private static final String BOT_SCOPE = "channels:read"; + private static final String USER_RESOURCE_URL = "https://slack.com/api/users.list"; + private static final String USER_SCOPE = "users:read"; + private static final String PAYLOAD = "null"; + private static final String CONTENT_TYPE_NAME = "Content-Type"; + private static final String CONTENT_TYPE_VALUE = "application/json"; + + private SlackExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "client-id"; + final String clientSecret = "client-secret"; + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("https://www.example.com/oauth_callback/") + .defaultScope(BOT_SCOPE) + .build(SlackApi.instance()); + + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + + final Map additionalParams = new HashMap<>(); + // define user scope if any + additionalParams.put("user_scope", USER_SCOPE); + final String authorizationUrl = service.createAuthorizationUrlBuilder() + .additionalParams(additionalParams) + .build(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + System.out.println("Getting info using BOT token..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, BOT_RESOURCE_URL); + request.addHeader(CONTENT_TYPE_NAME, CONTENT_TYPE_VALUE); + request.setPayload(PAYLOAD); + service.signRequest(accessToken, request); + + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + System.out.println(); + } + + System.out.println("Getting info using USER token..."); + final OAuthRequest userRequest = new OAuthRequest(Verb.GET, USER_RESOURCE_URL); + userRequest.addHeader(CONTENT_TYPE_NAME, CONTENT_TYPE_VALUE); + userRequest.setPayload(PAYLOAD); + final SlackOAuth2AccessToken token = (SlackOAuth2AccessToken) accessToken; + service.signRequest(token.getUserAccessToken(), userRequest); + + try (Response response = service.execute(userRequest)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/StackExchangeExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/StackExchangeExample.java new file mode 100644 index 000000000..5b4d52bcb --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/StackExchangeExample.java @@ -0,0 +1,88 @@ +package com.github.scribejava.apis.examples; + +import java.util.Random; +import java.util.Scanner; + +import com.github.scribejava.apis.StackExchangeApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class StackExchangeExample { + + private static final String NETWORK_NAME = "Stack Exchange"; + private static final String PROTECTED_RESOURCE_URL = "https://api.stackexchange.com/2.2/me"; + + private StackExchangeExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id, secret, application key and + // optionally site name + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String key = "your client key"; + // Enter one of Stack Exchange site names the user has account with. + final String site = "stackoverflow"; + final String secretState = "secret" + new Random().nextInt(999_999); + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("http://www.example.com/oauth_callback/") + .build(StackExchangeApi.instance()); + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, + PROTECTED_RESOURCE_URL + "?site=" + site + "&key=" + key); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TheThingsNetworkV1StagingExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TheThingsNetworkV1StagingExample.java new file mode 100644 index 000000000..63139e589 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TheThingsNetworkV1StagingExample.java @@ -0,0 +1,97 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.TheThingsNetworkV1StagingApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.IOException; +import java.net.URLDecoder; +import java.util.Random; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class TheThingsNetworkV1StagingExample { + + private static final String NETWORK_NAME = "TTNv1staging"; + private static final String PROTECTED_RESOURCE_URL = "https://account.thethingsnetwork.org/applications"; + + private TheThingsNetworkV1StagingExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your_client_id"; + final String clientSecret = "your_client_secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + final String redirectURI = "https://your_redirect_uri"; + + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback(redirectURI) + .build(TheThingsNetworkV1StagingApi.instance()); + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + + // TTN v1staging does not have URL safe keys, so we have to decode it + final String code = URLDecoder.decode(in.nextLine(), "UTF-8"); + System.out.println("Using code: " + code); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Oops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + + service.signRequest(accessToken, request); + request.addHeader("Accept", "application/json"); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + + if (response.getCode() == 401) { + System.out.println("Not authorised: " + response.getBody()); + } else { + System.out.println("You should see a JSON array of your registered applications:"); + System.out.println(response.getBody()); + + System.out.println(); + System.out.println("That's it man! Go and build something awesome with ScribeJava! :)"); + } + } + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TheThingsNetworkV2PreviewExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TheThingsNetworkV2PreviewExample.java new file mode 100644 index 000000000..25316d6ea --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TheThingsNetworkV2PreviewExample.java @@ -0,0 +1,94 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.TheThingsNetworkV2PreviewApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.IOException; +import java.util.Random; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class TheThingsNetworkV2PreviewExample { + + private static final String NETWORK_NAME = "TTNv2preview"; + private static final String PROTECTED_RESOURCE_URL + = "https://preview.account.thethingsnetwork.org/api/v2/applications"; + + private TheThingsNetworkV2PreviewExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your_client_id"; + final String clientSecret = "your_client_secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + final String redirectURI = "https://your_redirect_uri"; + + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback(redirectURI) + .build(TheThingsNetworkV2PreviewApi.instance()); + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Oops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + + service.signRequest(accessToken, request); + request.addHeader("Accept", "application/json"); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + + if (response.getCode() == 401) { + System.out.println("Not authorised: " + response.getBody()); + } else { + System.out.println("You should see a JSON array of your registered applications:"); + System.out.println(response.getBody()); + + System.out.println(); + System.out.println("That's it man! Go and build something awesome with ScribeJava! :)"); + } + } + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TrelloExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TrelloExample.java new file mode 100644 index 000000000..737bd768e --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TrelloExample.java @@ -0,0 +1,67 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.TrelloApi; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class TrelloExample { + + private static final String API_KEY = "your_api_key"; + private static final String API_SECRET = "your_api_secret"; + private static final String PROTECTED_RESOURCE_URL = "https://trello.com/1/members/me"; + + private TrelloExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + final OAuth10aService service = new ServiceBuilder(API_KEY) + .apiSecret(API_SECRET) + .build(TrelloApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== Trello's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(service.getAuthorizationUrl(requestToken)); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } + +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TumblrExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TumblrExample.java new file mode 100644 index 000000000..063b8b9b2 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TumblrExample.java @@ -0,0 +1,66 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.TumblrApi; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class TumblrExample { + + private static final String PROTECTED_RESOURCE_URL = "http://api.tumblr.com/v2/user/info"; + + private TumblrExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + final OAuth10aService service = new ServiceBuilder("MY_CONSUMER_KEY") + .apiSecret("MY_CONSUMER_SECRET") + // OOB forbidden. We need an url and the better is on the tumblr website ! + .callback("http://www.tumblr.com/connect/login_success.html") + .build(TumblrApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== Tumblr's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(service.getAuthorizationUrl(requestToken)); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TutByExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TutByExample.java new file mode 100644 index 000000000..c6aaf7eab --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TutByExample.java @@ -0,0 +1,67 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; + +import com.github.scribejava.apis.TutByApi; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class TutByExample { + + private static final String NETWORK_NAME = "Tut.by"; + private static final String PROTECTED_RESOURCE_URL = "http://profile.tut.by/getInfo"; + + private TutByExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("http://www.example.com/oauth_callback/") + .build(TutByApi.instance()); + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TwitterExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TwitterExample.java new file mode 100644 index 000000000..748fa9034 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TwitterExample.java @@ -0,0 +1,64 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.TwitterApi; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class TwitterExample { + + private static final String PROTECTED_RESOURCE_URL = "https://api.twitter.com/1.1/account/verify_credentials.json"; + + private TwitterExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + final OAuth10aService service = new ServiceBuilder("your client id") + .apiSecret("your client secret") + .build(TwitterApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== Twitter's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(service.getAuthorizationUrl(requestToken)); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("That's it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/UcozExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/UcozExample.java new file mode 100644 index 000000000..5760bb36a --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/UcozExample.java @@ -0,0 +1,60 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.UcozApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; + +import java.io.IOException; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class UcozExample { + + private static final String PROTECTED_RESOURCE_URL = "http://artmurka.com/uapi/shop/request?page=categories"; + + private UcozExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + final OAuth10aService service = new ServiceBuilder("your_api_key") + .apiSecret("your_api_secret") + .debug() + .build(UcozApi.instance()); + final Scanner in = new Scanner(System.in); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(service.getAuthorizationUrl(requestToken)); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/ViadeoExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/ViadeoExample.java new file mode 100644 index 000000000..39dbcff78 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/ViadeoExample.java @@ -0,0 +1,67 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.ViadeoApi; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class ViadeoExample { + + private static final String NETWORK_NAME = "Viadeo"; + private static final String PROTECTED_RESOURCE_URL = "https://api.viadeo.com/me?user_detail=full"; + + private ViadeoExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your own api key and secret + final String apiKey = "your_app_id"; + final String apiSecret = "your_api_secret"; + final OAuth20Service service = new ServiceBuilder(apiKey) + .apiSecret(apiSecret) + .callback("http://www.example.com/oauth_callback/") + .build(ViadeoApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteAsyncApacheExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteAsyncApacheExample.java new file mode 100644 index 000000000..392348b2b --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteAsyncApacheExample.java @@ -0,0 +1,87 @@ +package com.github.scribejava.apis.examples; + +import java.util.Random; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; +import com.github.scribejava.apis.VkontakteApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.httpclient.apache.ApacheHttpClientConfig; +import java.io.IOException; + +public class VkontakteAsyncApacheExample { + + private static final String NETWORK_NAME = "vk.com"; + private static final String PROTECTED_RESOURCE_URL = "https://api.vk.com/method/users.get?v=" + + VkontakteApi.VERSION; + + private VkontakteAsyncApacheExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws InterruptedException, ExecutionException, IOException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + + try ( OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("http://www.example.com/oauth_callback/") + .httpClientConfig(ApacheHttpClientConfig.defaultConfig()) + .build(VkontakteApi.instance())) { + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s Async OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessTokenAsync(code).get(); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try ( Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteAsyncNingExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteAsyncNingExample.java new file mode 100644 index 000000000..bfb80d1a9 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteAsyncNingExample.java @@ -0,0 +1,95 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.httpclient.ning.NingHttpClientConfig; +import com.ning.http.client.AsyncHttpClientConfig; +import java.util.Random; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; +import com.github.scribejava.apis.VkontakteApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; + +public class VkontakteAsyncNingExample { + + private static final String NETWORK_NAME = "vk.com"; + private static final String PROTECTED_RESOURCE_URL = "https://api.vk.com/method/users.get?v=" + + VkontakteApi.VERSION; + + private VkontakteAsyncNingExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws InterruptedException, ExecutionException, IOException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + final NingHttpClientConfig clientConfig = new NingHttpClientConfig(new AsyncHttpClientConfig.Builder() + .setMaxConnections(5) + .setRequestTimeout(10_000) + .setAllowPoolingConnections(false) + .setPooledConnectionIdleTimeout(1_000) + .setReadTimeout(1_000) + .build()); + + try ( OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback("http://www.example.com/oauth_callback/") + .httpClientConfig(clientConfig) + .build(VkontakteApi.instance())) { + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s Async OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessTokenAsync(code).get(); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try ( Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteClientCredentialsGrantExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteClientCredentialsGrantExample.java new file mode 100644 index 000000000..3e4d2d363 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteClientCredentialsGrantExample.java @@ -0,0 +1,38 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.VkontakteApi; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class VkontakteClientCredentialsGrantExample { + + private static final String NETWORK_NAME = "vk.com>"; + + private VkontakteClientCredentialsGrantExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope("wall,offline") // replace with desired scope + .callback("http://your.site.com/callback") + .build(VkontakteApi.instance()); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + final OAuth2AccessToken accessToken = service.getAccessTokenClientCredentialsGrant(); + + System.out.println("Got the Access Token!"); + System.out.println(accessToken.getRawResponse()); + System.out.println(); + + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteExample.java new file mode 100644 index 000000000..ca1a698bf --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteExample.java @@ -0,0 +1,78 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.VkontakteApi; +import com.github.scribejava.apis.vk.VKOAuth2AccessToken; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.AccessTokenRequestParams; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class VkontakteExample { + + private static final String NETWORK_NAME = "vk.com"; + private static final String PROTECTED_RESOURCE_URL = "https://api.vk.com/method/users.get?v=" + + VkontakteApi.VERSION; + + private VkontakteExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope("wall,offline") // replace with desired scope + .callback("http://your.site.com/callback") + .build(VkontakteApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String customScope = "wall,offline,email"; + final String authorizationUrl = service.createAuthorizationUrlBuilder() + .scope(customScope) + .build(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(AccessTokenRequestParams.create(code) + .scope(customScope)); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + if (accessToken instanceof VKOAuth2AccessToken) { + System.out.println("it's a VKOAuth2AccessToken, it has email field = '" + + ((VKOAuth2AccessToken) accessToken).getEmail() + "'."); + } + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try ( Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteExternalHttpExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteExternalHttpExample.java new file mode 100644 index 000000000..fe5340294 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteExternalHttpExample.java @@ -0,0 +1,87 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.VkontakteApi; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.httpclient.ahc.AhcHttpClient; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import org.asynchttpclient.DefaultAsyncHttpClient; +import org.asynchttpclient.DefaultAsyncHttpClientConfig; + +public class VkontakteExternalHttpExample { + + private static final String NETWORK_NAME = "vk.com"; + private static final String PROTECTED_RESOURCE_URL = "https://api.vk.com/method/users.get?v=" + + VkontakteApi.VERSION; + + private VkontakteExternalHttpExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + + //create any http client externally + final DefaultAsyncHttpClientConfig httpClientConfig = new DefaultAsyncHttpClientConfig.Builder() + .setMaxConnections(5) + .setRequestTimeout(10_000) + .setPooledConnectionIdleTimeout(1_000) + .setReadTimeout(1_000) + .build(); + //wrap it + try ( DefaultAsyncHttpClient ahcHttpClient = new DefaultAsyncHttpClient(httpClientConfig)) { + //wrap it + final AhcHttpClient wrappedAHCHttpClient = new AhcHttpClient(ahcHttpClient); + + final OAuth20Service service = new ServiceBuilder(clientId) + .httpClient(wrappedAHCHttpClient) + .apiSecret(clientSecret) + .defaultScope("wall,offline") // replace with desired scope + .callback("http://your.site.com/callback") + .build(VkontakteApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try ( Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/WunderlistExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/WunderlistExample.java new file mode 100644 index 000000000..5d3ffd562 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/WunderlistExample.java @@ -0,0 +1,73 @@ +package com.github.scribejava.apis.examples; + +import java.io.IOException; +import java.util.Random; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +import com.github.scribejava.apis.WunderlistAPI; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +public class WunderlistExample { + + private static final String NETWORK_NAME = "Wunderlist"; + private static final String PROTECTED_RESOURCE_URL = "https://a.wunderlist.com/api/v1/user"; + + private WunderlistExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your own values + final String apiKey = "apiKey"; + final String apiSecret = "apiSecret"; + final String callbackUrl = "http://example.com/callback"; + final String secretState = "security_token" + new Random().nextInt(999_999); + + final OAuth20Service service = new ServiceBuilder(apiKey) + .apiSecret(apiSecret) + .callback(callbackUrl) + .build(WunderlistAPI.instance()); + + final String code; + try (Scanner in = new Scanner(System.in, "UTF-8")) { + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + code = in.nextLine(); + } + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/XeroExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/XeroExample.java new file mode 100644 index 000000000..d66334e40 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/XeroExample.java @@ -0,0 +1,110 @@ +package com.github.scribejava.apis.examples; + +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Scanner; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.scribejava.apis.XeroApi20; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class XeroExample { + + private static final String NETWORK_NAME = "Xero"; + private static final String PROTECTED_RESOURCE_URL = "https://api.xero.com/connections"; + private static final String PROTECTED_ORGANISATION_URL = "https://api.xero.com/api.xro/2.0/Organisation"; + + private XeroExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String callback = "your callback url"; + + final String secretState = "secret" + new Random().nextInt(999_999); + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + // replace with desired scope + .defaultScope("openid email profile offline_access accounting.settings accounting.transactions") + .callback(callback) + .build(XeroApi20.instance()); + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(secretState); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + //First GET the Xero Tenant ID + System.out.println("Getting Xero tenant id..."); + final OAuthRequest requestConn = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + requestConn.addHeader("Accept", "application/json"); + service.signRequest(accessToken.getAccessToken(), requestConn); + final Response connResp = service.execute(requestConn); + + final ObjectMapper objectMapper = new ObjectMapper(); + final List> tenantList = objectMapper.readValue(connResp.getBody(), + objectMapper.getTypeFactory().constructCollectionType(List.class, Map.class)); + + System.out.println(); + System.out.println(connResp.getCode()); + System.out.println(connResp.getBody()); + System.out.println(); + System.out.println("Your Xero tenant id is ...." + tenantList.get(0).get("tenantId")); + System.out.println(); + + // GET protected Resource + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_ORGANISATION_URL); + request.addHeader("xero-tenant-id", tenantList.get(0).get("tenantId")); + service.signRequest(accessToken.getAccessToken(), request); + final Response response = service.execute(request); + + // Now let's go and ask for a protected resource! + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/XingExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/XingExample.java new file mode 100755 index 000000000..ebf946db5 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/XingExample.java @@ -0,0 +1,65 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.XingApi; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class XingExample { + + private static final String PROTECTED_RESOURCE_URL = "https://api.xing.com/v1/users/me"; + + private XingExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + final OAuth10aService service = new ServiceBuilder("your client id") + .apiSecret("your client secret") + .build(XingApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== Xing's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(service.getAuthorizationUrl(requestToken)); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + } + +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Yahoo20Example.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Yahoo20Example.java new file mode 100644 index 000000000..49b655462 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Yahoo20Example.java @@ -0,0 +1,79 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.YahooApi20; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.IOException; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +/** + * Flow as documented at https://developer.yahoo.com/oauth2/guide/flows_authcode + *
    + *
  1. Create an application at https://developer.yahoo.com/apps/create/
  2. + *
  3. Make sure application has permission to API resource (Profiles, Fantasy Sports, etc)
  4. + *
  5. get Client ID and Client Secret after registering your app
  6. + *
+ */ +public class Yahoo20Example { + + private static final String PROTECTED_RESOURCE_URL + = "https://fantasysports.yahooapis.com/fantasy/v2/users;use_login=1/games/teams"; + + private Yahoo20Example() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Add your personal information here + final String clientId = "ADD CLIENT ID HERE!!!!"; + final String clientSecret = "ADD SECRET HERE!!!!"; + + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback(OAuthConstants.OOB) + .build(YahooApi20.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== Yahoo's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(service.getAuthorizationUrl()); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + System.out.println("Trading the Authorization Code for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/YahooExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/YahooExample.java new file mode 100644 index 000000000..acaa42aea --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/YahooExample.java @@ -0,0 +1,67 @@ +package com.github.scribejava.apis.examples; + +import java.util.Scanner; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.apis.YahooApi; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class YahooExample { + + private static final String PROTECTED_RESOURCE_URL + = "http://social.yahooapis.com/v1/user/A6ROU63MXWDCW3Y5MGCYWVHDJI/profile/status?format=json"; + + private YahooExample() { + } + + @SuppressWarnings("PMD.SystemPrintln") + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + final OAuth10aService service = new ServiceBuilder("your client id") + .apiSecret("your client secret") + .build(YahooApi.instance()); + final Scanner in = new Scanner(System.in); + + System.out.println("=== Yahoo's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + final OAuth1RequestToken requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(service.getAuthorizationUrl(requestToken)); + System.out.println("And paste the verifier here"); + System.out.print(">>"); + final String oauthVerifier = in.nextLine(); + System.out.println(); + + // Trade the Request Token and Verifier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth1AccessToken accessToken = service.getAccessToken(requestToken, oauthVerifier); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + try (Response response = service.execute(request)) { + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + } + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/facebook/FacebookAccessTokenJsonExtractorTest.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/facebook/FacebookAccessTokenJsonExtractorTest.java new file mode 100644 index 000000000..240f08b81 --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/facebook/FacebookAccessTokenJsonExtractorTest.java @@ -0,0 +1,43 @@ +package com.github.scribejava.apis.facebook; + +import com.github.scribejava.core.model.Response; +import java.io.IOException; +import java.util.Collections; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import org.junit.Test; +import org.junit.function.ThrowingRunnable; + +public class FacebookAccessTokenJsonExtractorTest { + + private final FacebookAccessTokenJsonExtractor extractor = FacebookAccessTokenJsonExtractor.instance(); + + @Test + public void shouldThrowExceptionIfResponseIsError() throws IOException { + final String body = "{\"error\":" + + "{\"message\":\"This authorization code has been used.\"," + + "\"type\":\"OAuthException\"," + + "\"code\":100," + + "\"fbtrace_id\":\"DtxvtGRaxbB\"}}"; + try (Response response = error(body)) { + + final FacebookAccessTokenErrorResponse fateR = assertThrows(FacebookAccessTokenErrorResponse.class, + new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.extract(response); + } + }); + + assertEquals("This authorization code has been used.", fateR.getErrorMessage()); + assertEquals("OAuthException", fateR.getType()); + assertEquals(100, fateR.getCodeInt()); + assertEquals("DtxvtGRaxbB", fateR.getFbtraceId()); + assertEquals(body, fateR.getResponse().getBody()); + } + } + + private static Response error(String body) { + return new Response(400, /* message */ null, /* headers */ Collections.emptyMap(), body); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/fitbit/FitBitJsonTokenExtractorTest.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/fitbit/FitBitJsonTokenExtractorTest.java new file mode 100644 index 000000000..836a0d6ba --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/fitbit/FitBitJsonTokenExtractorTest.java @@ -0,0 +1,38 @@ +package com.github.scribejava.apis.fitbit; + +import com.github.scribejava.core.model.OAuth2AccessTokenErrorResponse; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.oauth2.OAuth2Error; +import java.io.IOException; + +import org.junit.Test; + +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertEquals; +import org.junit.function.ThrowingRunnable; + +public class FitBitJsonTokenExtractorTest { + + private static final String ERROR_DESCRIPTION = "Authorization code invalid: " + + "cbb1c11b23209011e89be71201fa6381464dc0af " + + "Visit https://dev.fitbit.com/docs/oauth2 for more information " + + "on the Fitbit Web API authorization process."; + private static final String ERROR_JSON = "{\"errors\":[{\"errorType\":\"invalid_grant\",\"message\":\"" + + ERROR_DESCRIPTION + "\"}],\"success\":false}"; + + @Test + public void testErrorExtraction() throws IOException { + + final FitBitJsonTokenExtractor extractor = new FitBitJsonTokenExtractor(); + final OAuth2AccessTokenErrorResponse thrown = assertThrows(OAuth2AccessTokenErrorResponse.class, + new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.generateError(new Response(403, null, null, ERROR_JSON)); + } + }); + assertSame(OAuth2Error.INVALID_GRANT, thrown.getError()); + assertEquals(ERROR_DESCRIPTION, thrown.getErrorDescription()); + } +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/odnoklassniki/OdnoklassnikiServiceTest.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/odnoklassniki/OdnoklassnikiServiceTest.java new file mode 100644 index 000000000..f4bfbccac --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/odnoklassniki/OdnoklassnikiServiceTest.java @@ -0,0 +1,42 @@ +package com.github.scribejava.apis.odnoklassniki; + +import com.github.scribejava.apis.OdnoklassnikiApi; +import com.github.scribejava.core.builder.ServiceBuilder; + +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.ParameterList; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.model.Parameter; +import com.github.scribejava.core.oauth.OAuth20Service; +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class OdnoklassnikiServiceTest { + + private static final String URL = "https://api.ok.ru/fb.do?method=friends.get&fields=uid%2C" + + "first_name%2Clast_name%2Cpic_2&application_key=AAAAAAAAAAAAAAAA&format=json"; + + private final OAuth20Service service = new ServiceBuilder("0000000000") + .apiSecret("CCCCCCCCCCCCCCCCCCCCCCCC") + .defaultScope("VALUABLE_ACCESS") + .callback("http://your.site.com/callback") + .build(OdnoklassnikiApi.instance()); + + @Test + public void testSigGeneration() { + final OAuth2AccessToken accessToken = new OAuth2AccessToken("d3iwa.403gvrs194740652m1k4w2a503k3c"); + final OAuthRequest request = new OAuthRequest(Verb.GET, URL); + service.signRequest(accessToken, request); + assertEquals("96127f5ca29a8351399e94bbd284ab16", findParam(request.getQueryStringParams(), "sig")); + } + + private static String findParam(ParameterList list, String key) { + for (Parameter param : list.getParams()) { + if (param.getKey().equals(key)) { + return param.getValue(); + } + } + return null; + } +} diff --git a/scribejava-core/pom.xml b/scribejava-core/pom.xml new file mode 100644 index 000000000..d5fbfc488 --- /dev/null +++ b/scribejava-core/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + + com.github.scribejava + scribejava + 8.3.4-SNAPSHOT + ../pom.xml + + + com.github.scribejava + scribejava-core + ScribeJava Core + jar + + + + com.github.scribejava + scribejava-java8 + ${project.version} + + + commons-codec + commons-codec + 1.15 + true + + + jakarta.xml.bind + jakarta.xml.bind-api + 4.0.0 + true + + + javax.xml.bind + jaxb-api + 2.3.0 + true + + + + + + + org.apache.felix + maven-bundle-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + + + + diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/base64/Base64.java b/scribejava-core/src/main/java/com/github/scribejava/core/base64/Base64.java new file mode 100644 index 000000000..18a8f01a0 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/base64/Base64.java @@ -0,0 +1,55 @@ +package com.github.scribejava.core.base64; + +public abstract class Base64 { + + private static volatile Base64 instance; + + public static Base64 getInstance() { + Base64 localInstance = instance; + if (localInstance == null) { + synchronized (Base64.class) { + localInstance = instance; + if (localInstance == null) { + localInstance = createInstance(); + instance = localInstance; + } + } + } + return localInstance; + } + + private static Base64 createInstance() { + if (Java8Base64.isAvailable()) { + return new Java8Base64(); + } + if (Jaxb230Base64.isAvailable()) { + return new Jaxb230Base64(); + } + if (JaxbBase64.isAvailable()) { + return new JaxbBase64(); + } + if (CommonsCodecBase64.isAvailable()) { + return new CommonsCodecBase64(); + } + throw new IllegalStateException( + "No Base64 implementation was provided. Java 8 Base64, Apache Commons Codec or JAXB is needed"); + } + + public static void init(Base64 base64) { + synchronized (Base64.class) { + instance = base64; + } + } + + public static String encode(byte[] bytes) { + return getInstance().internalEncode(bytes); + } + + public static String encodeUrlWithoutPadding(byte[] bytes) { + return getInstance().internalEncodeUrlWithoutPadding(bytes); + } + + protected abstract String internalEncode(byte[] bytes); + + protected abstract String internalEncodeUrlWithoutPadding(byte[] bytes); +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/base64/CommonsCodecBase64.java b/scribejava-core/src/main/java/com/github/scribejava/core/base64/CommonsCodecBase64.java new file mode 100644 index 000000000..bb172d720 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/base64/CommonsCodecBase64.java @@ -0,0 +1,36 @@ +package com.github.scribejava.core.base64; + +public class CommonsCodecBase64 extends Base64 { + + private static final org.apache.commons.codec.binary.Base64 BASE64_ENCODER; + private static final org.apache.commons.codec.binary.Base64 BASE64_URL_ENCODER_WITHOUT_PADDING; + + static { + if (isAvailable()) { + BASE64_ENCODER = new org.apache.commons.codec.binary.Base64(); + BASE64_URL_ENCODER_WITHOUT_PADDING = new org.apache.commons.codec.binary.Base64(0, null, true); + } else { + BASE64_ENCODER = null; + BASE64_URL_ENCODER_WITHOUT_PADDING = null; + } + } + + @Override + protected String internalEncode(byte[] bytes) { + return BASE64_ENCODER.encodeToString(bytes); + } + + @Override + protected String internalEncodeUrlWithoutPadding(byte[] bytes) { + return BASE64_URL_ENCODER_WITHOUT_PADDING.encodeToString(bytes); + } + + static boolean isAvailable() { + try { + Class.forName("org.apache.commons.codec.binary.Base64", false, CommonsCodecBase64.class.getClassLoader()); + return true; + } catch (ClassNotFoundException cnfE) { + return false; + } + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/base64/Java8Base64.java b/scribejava-core/src/main/java/com/github/scribejava/core/base64/Java8Base64.java new file mode 100644 index 000000000..8e4c6c990 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/base64/Java8Base64.java @@ -0,0 +1,26 @@ +package com.github.scribejava.core.base64; + +public class Java8Base64 extends Base64 { + + private static final com.github.scribejava.java8.base64.Java8Base64 JAVA8_BASE64 + = isAvailable() ? new com.github.scribejava.java8.base64.Java8Base64() : null; + + @Override + protected String internalEncode(byte[] bytes) { + return JAVA8_BASE64.internalEncode(bytes); + } + + @Override + protected String internalEncodeUrlWithoutPadding(byte[] bytes) { + return JAVA8_BASE64.internalEncodeUrlWithoutPadding(bytes); + } + + static boolean isAvailable() { + try { + Class.forName("java.util.Base64", false, Java8Base64.class.getClassLoader()); + return true; + } catch (ClassNotFoundException cnfE) { + return false; + } + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/base64/Jaxb230Base64.java b/scribejava-core/src/main/java/com/github/scribejava/core/base64/Jaxb230Base64.java new file mode 100644 index 000000000..c4ee4d799 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/base64/Jaxb230Base64.java @@ -0,0 +1,32 @@ +package com.github.scribejava.core.base64; + +import javax.xml.bind.DatatypeConverter; + +/** + * JAXB v2.3.0 (the latest for JRE 7) + */ +public class Jaxb230Base64 extends Base64 { + + @Override + protected String internalEncode(byte[] bytes) { + return DatatypeConverter.printBase64Binary(bytes); + } + + @Override + protected String internalEncodeUrlWithoutPadding(byte[] bytes) { + String string = DatatypeConverter.printBase64Binary(bytes); + while (string.endsWith("=")) { + string = string.substring(0, string.length() - 1); + } + return string.replace('+', '-').replace('/', '_'); + } + + static boolean isAvailable() { + try { + Class.forName("javax.xml.bind.DatatypeConverter", false, Jaxb230Base64.class.getClassLoader()); + return true; + } catch (ClassNotFoundException cnfE) { + return false; + } + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/base64/JaxbBase64.java b/scribejava-core/src/main/java/com/github/scribejava/core/base64/JaxbBase64.java new file mode 100644 index 000000000..85e889501 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/base64/JaxbBase64.java @@ -0,0 +1,29 @@ +package com.github.scribejava.core.base64; + +import jakarta.xml.bind.DatatypeConverter; + +public class JaxbBase64 extends Base64 { + + @Override + protected String internalEncode(byte[] bytes) { + return DatatypeConverter.printBase64Binary(bytes); + } + + @Override + protected String internalEncodeUrlWithoutPadding(byte[] bytes) { + String string = DatatypeConverter.printBase64Binary(bytes); + while (string.endsWith("=")) { + string = string.substring(0, string.length() - 1); + } + return string.replace('+', '-').replace('/', '_'); + } + + static boolean isAvailable() { + try { + Class.forName("jakarta.xml.bind.DatatypeConverter", false, JaxbBase64.class.getClassLoader()); + return true; + } catch (ClassNotFoundException cnfE) { + return false; + } + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/builder/ScopeBuilder.java b/scribejava-core/src/main/java/com/github/scribejava/core/builder/ScopeBuilder.java new file mode 100644 index 000000000..8bd22e1a4 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/builder/ScopeBuilder.java @@ -0,0 +1,56 @@ +package com.github.scribejava.core.builder; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * OAuth2.0 Scope Builder. It allows specifying multiple scopes one by one. It will combine them in the single + * space-delimited string. OAuth 2.0 standard specifies space as a delimiter for scopes + * (https://tools.ietf.org/html/rfc6749#section-3.3). If you found API, that do not support spaces, but support + * something else, let ScribeJava know (submit the issue here https://github.com/scribejava/scribejava/issues) and use + * your own concatenated string as a temporary workaround. + */ +public class ScopeBuilder { + + private final Set scopes = new HashSet<>(); + + public ScopeBuilder() { + } + + public ScopeBuilder(String scope) { + withScope(scope); + } + + public ScopeBuilder(String... scopes) { + withScopes(scopes); + } + + public ScopeBuilder(Collection scopes) { + withScopes(scopes); + } + + public final ScopeBuilder withScope(String scope) { + scopes.add(scope); + return this; + } + + public final ScopeBuilder withScopes(String... scopes) { + this.scopes.addAll(Arrays.asList(scopes)); + return this; + } + + public final ScopeBuilder withScopes(Collection scopes) { + this.scopes.addAll(scopes); + return this; + } + + public String build() { + final StringBuilder scopeBuilder = new StringBuilder(); + for (String scope : scopes) { + scopeBuilder.append(' ').append(scope); + } + return scopeBuilder.substring(1); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/builder/ServiceBuilder.java b/scribejava-core/src/main/java/com/github/scribejava/core/builder/ServiceBuilder.java new file mode 100644 index 000000000..eade1ede5 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/builder/ServiceBuilder.java @@ -0,0 +1,130 @@ +package com.github.scribejava.core.builder; + +import com.github.scribejava.core.builder.api.DefaultApi10a; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.oauth.OAuth10aService; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.core.oauth.OAuthService; +import com.github.scribejava.core.utils.Preconditions; + +import java.io.OutputStream; + +/** + * Implementation of the Builder pattern, with a fluent interface that creates a {@link OAuthService} + */ +public class ServiceBuilder implements ServiceBuilderOAuth10a, ServiceBuilderOAuth20 { + + private String callback; + private String apiKey; + private String apiSecret; + private String scope; + private OutputStream debugStream; + private String responseType = "code"; + private String userAgent; + + private HttpClientConfig httpClientConfig; + private HttpClient httpClient; + + public ServiceBuilder(String apiKey) { + apiKey(apiKey); + } + + @Override + public ServiceBuilder callback(String callback) { + this.callback = callback; + return this; + } + + @Override + public final ServiceBuilder apiKey(String apiKey) { + Preconditions.checkEmptyString(apiKey, "Invalid Api key"); + this.apiKey = apiKey; + return this; + } + + @Override + public ServiceBuilder apiSecret(String apiSecret) { + Preconditions.checkEmptyString(apiSecret, "Invalid Api secret"); + this.apiSecret = apiSecret; + return this; + } + + @Override + public ServiceBuilder apiSecretIsEmptyStringUnsafe() { + apiSecret = ""; + return this; + } + + private ServiceBuilder setScope(String scope) { + Preconditions.checkEmptyString(scope, "Invalid OAuth scope"); + this.scope = scope; + return this; + } + + @Override + public ServiceBuilderOAuth20 defaultScope(String defaultScope) { + return setScope(defaultScope); + } + + @Override + public ServiceBuilderOAuth20 defaultScope(ScopeBuilder scopeBuilder) { + return setScope(scopeBuilder.build()); + } + + @Override + public ServiceBuilderOAuth10a withScope(String scope) { + return setScope(scope); + } + + @Override + public ServiceBuilder debugStream(OutputStream debugStream) { + Preconditions.checkNotNull(debugStream, "debug stream can't be null"); + this.debugStream = debugStream; + return this; + } + + @Override + public ServiceBuilderOAuth20 responseType(String responseType) { + Preconditions.checkEmptyString(responseType, "Invalid OAuth responseType"); + this.responseType = responseType; + return this; + } + + @Override + public ServiceBuilder httpClientConfig(HttpClientConfig httpClientConfig) { + Preconditions.checkNotNull(httpClientConfig, "httpClientConfig can't be null"); + this.httpClientConfig = httpClientConfig; + return this; + } + + @Override + public ServiceBuilder httpClient(HttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + @Override + public ServiceBuilder userAgent(String userAgent) { + this.userAgent = userAgent; + return this; + } + + @Override + public ServiceBuilder debug() { + return debugStream(System.out); + } + + @Override + public OAuth10aService build(DefaultApi10a api) { + return api.createService(apiKey, apiSecret, callback, scope, debugStream, userAgent, httpClientConfig, + httpClient); + } + + @Override + public OAuth20Service build(DefaultApi20 api) { + return api.createService(apiKey, apiSecret, callback, scope, responseType, debugStream, userAgent, + httpClientConfig, httpClient); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/builder/ServiceBuilderCommon.java b/scribejava-core/src/main/java/com/github/scribejava/core/builder/ServiceBuilderCommon.java new file mode 100644 index 000000000..fd71c49d8 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/builder/ServiceBuilderCommon.java @@ -0,0 +1,63 @@ +package com.github.scribejava.core.builder; + +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.oauth.OAuthService; +import java.io.OutputStream; + +/** + * Implementation of the Builder pattern, with a fluent interface that creates a {@link OAuthService} + */ +public interface ServiceBuilderCommon { + + /** + * Adds an OAuth callback url + * + * @param callback callback url. Must be a valid url or 'oob' + * ({@link com.github.scribejava.core.model.OAuthConstants#OOB} for out of band OAuth + * @return the {@link ServiceBuilder} instance for method chaining + */ + ServiceBuilderCommon callback(String callback); + + /** + * Configures the api key + * + * @param apiKey The api key for your application + * @return the {@link ServiceBuilder} instance for method chaining + */ + ServiceBuilderCommon apiKey(String apiKey); + + /** + * Configures the api secret + * + * @param apiSecret The api secret for your application + * @return the {@link ServiceBuilder} instance for method chaining + */ + ServiceBuilderCommon apiSecret(String apiSecret); + + /** + * Configures the api secret as "" (empty string). + * + * Used usually for a test environments or another strange cases. Not all providers support empty string as api key + * and will throw an Exception in such cases. + * + * @return the {@link ServiceBuilder} instance for method chaining + */ + ServiceBuilderCommon apiSecretIsEmptyStringUnsafe(); + + ServiceBuilderCommon httpClientConfig(HttpClientConfig httpClientConfig); + + /** + * takes precedence over httpClientConfig + * + * @param httpClient externally created HTTP client + * @return the {@link ServiceBuilder} instance for method chaining + */ + ServiceBuilderCommon httpClient(HttpClient httpClient); + + ServiceBuilderCommon userAgent(String userAgent); + + ServiceBuilderCommon debugStream(OutputStream debugStream); + + ServiceBuilderCommon debug(); +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/builder/ServiceBuilderOAuth10a.java b/scribejava-core/src/main/java/com/github/scribejava/core/builder/ServiceBuilderOAuth10a.java new file mode 100644 index 000000000..8c7027cca --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/builder/ServiceBuilderOAuth10a.java @@ -0,0 +1,47 @@ +package com.github.scribejava.core.builder; + +import com.github.scribejava.core.builder.api.DefaultApi10a; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.oauth.OAuth10aService; +import java.io.OutputStream; + +public interface ServiceBuilderOAuth10a extends ServiceBuilderCommon { + + @Override + ServiceBuilderOAuth10a callback(String callback); + + @Override + ServiceBuilderOAuth10a apiKey(String apiKey); + + @Override + ServiceBuilderOAuth10a apiSecret(String apiSecret); + + @Override + ServiceBuilderOAuth10a apiSecretIsEmptyStringUnsafe(); + + @Override + ServiceBuilderOAuth10a httpClientConfig(HttpClientConfig httpClientConfig); + + @Override + ServiceBuilderOAuth10a httpClient(HttpClient httpClient); + + @Override + ServiceBuilderOAuth10a userAgent(String userAgent); + + @Override + ServiceBuilderOAuth10a debugStream(OutputStream debugStream); + + @Override + ServiceBuilderOAuth10a debug(); + + /** + * Configures the OAuth 1.0a scope. This is only necessary in some APIs + * + * @param scope The OAuth scope + * @return the {@link ServiceBuilder} instance for method chaining + */ + ServiceBuilderOAuth10a withScope(String scope); + + OAuth10aService build(DefaultApi10a api); +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/builder/ServiceBuilderOAuth20.java b/scribejava-core/src/main/java/com/github/scribejava/core/builder/ServiceBuilderOAuth20.java new file mode 100644 index 000000000..bcf119db9 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/builder/ServiceBuilderOAuth20.java @@ -0,0 +1,57 @@ +package com.github.scribejava.core.builder; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.oauth.OAuth20Service; +import java.io.OutputStream; + +public interface ServiceBuilderOAuth20 extends ServiceBuilderCommon { + + @Override + ServiceBuilderOAuth20 callback(String callback); + + @Override + ServiceBuilderOAuth20 apiKey(String apiKey); + + @Override + ServiceBuilderOAuth20 apiSecret(String apiSecret); + + @Override + ServiceBuilderOAuth20 apiSecretIsEmptyStringUnsafe(); + + @Override + ServiceBuilderOAuth20 httpClientConfig(HttpClientConfig httpClientConfig); + + @Override + ServiceBuilderOAuth20 httpClient(HttpClient httpClient); + + @Override + ServiceBuilderOAuth20 userAgent(String userAgent); + + @Override + ServiceBuilderOAuth20 debugStream(OutputStream debugStream); + + @Override + ServiceBuilderOAuth20 debug(); + + ServiceBuilderOAuth20 responseType(String responseType); + + /** + * Configures the default OAuth 2.0 scope.
+ * + * You can request any uniq scope per each access token request using + * {@link com.github.scribejava.core.oauth.AuthorizationUrlBuilder#scope(java.lang.String) }.

+ * + * In case you're requesting always the same scope,
+ * you can just set it here and do not provide scope param nowhere more. + * + * @param defaultScope The OAuth scope, used as deafult + * @return the {@link ServiceBuilder} instance for method chaining + */ + ServiceBuilderOAuth20 defaultScope(String defaultScope); + + ServiceBuilderOAuth20 defaultScope(ScopeBuilder scopeBuilder); + + OAuth20Service build(DefaultApi20 api); +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/builder/api/DefaultApi10a.java b/scribejava-core/src/main/java/com/github/scribejava/core/builder/api/DefaultApi10a.java new file mode 100644 index 000000000..2ea470110 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/builder/api/DefaultApi10a.java @@ -0,0 +1,161 @@ +package com.github.scribejava.core.builder.api; + +import com.github.scribejava.core.extractors.BaseStringExtractor; +import com.github.scribejava.core.extractors.BaseStringExtractorImpl; +import com.github.scribejava.core.extractors.HeaderExtractor; +import com.github.scribejava.core.extractors.HeaderExtractorImpl; +import com.github.scribejava.core.extractors.OAuth1AccessTokenExtractor; +import com.github.scribejava.core.extractors.OAuth1RequestTokenExtractor; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth10aService; +import com.github.scribejava.core.services.HMACSha1SignatureService; +import com.github.scribejava.core.services.SignatureService; +import com.github.scribejava.core.services.TimestampService; +import com.github.scribejava.core.services.TimestampServiceImpl; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.ParameterList; +import java.io.OutputStream; + +/** + * Default implementation of the OAuth protocol, version 1.0a + * + * This class is meant to be extended by concrete implementations of the API, providing the endpoints and + * endpoint-http-verbs. + * + * If your Api adheres to the 1.0a protocol correctly, you just need to extend this class and define the getters for + * your endpoints. + * + * If your Api does something a bit different, you can override the different extractors or services, in order to + * fine-tune the process. Please read the javadocs of the interfaces to get an idea of what to do. + * + */ +public abstract class DefaultApi10a { + + /** + * Returns the access token extractor. + * + * @return access token extractor + */ + public TokenExtractor getAccessTokenExtractor() { + return OAuth1AccessTokenExtractor.instance(); + } + + /** + * Returns the base string extractor. + * + * @return base string extractor + */ + public BaseStringExtractor getBaseStringExtractor() { + return new BaseStringExtractorImpl(); + } + + /** + * Returns the header extractor. + * + * @return header extractor + */ + public HeaderExtractor getHeaderExtractor() { + return new HeaderExtractorImpl(); + } + + /** + * Returns the request token extractor. + * + * @return request token extractor + */ + public TokenExtractor getRequestTokenExtractor() { + return OAuth1RequestTokenExtractor.instance(); + } + + /** + * Returns the signature service. + * + * @return signature service + */ + public SignatureService getSignatureService() { + return new HMACSha1SignatureService(); + } + + /** + * @return the signature type, choose between header, querystring, etc. Defaults to Header + */ + public OAuth1SignatureType getSignatureType() { + return OAuth1SignatureType.HEADER; + } + + /** + * Returns the timestamp service. + * + * @return timestamp service + */ + public TimestampService getTimestampService() { + return new TimestampServiceImpl(); + } + + /** + * Returns the verb for the access token endpoint (defaults to POST) + * + * @return access token endpoint verb + */ + public Verb getAccessTokenVerb() { + return Verb.POST; + } + + /** + * Returns the verb for the request token endpoint (defaults to POST) + * + * @return request token endpoint verb + */ + public Verb getRequestTokenVerb() { + return Verb.POST; + } + + /** + * Returns the URL that receives the request token requests. + * + * @return request token URL + */ + public abstract String getRequestTokenEndpoint(); + + /** + * Returns the URL that receives the access token requests. + * + * @return access token URL + */ + public abstract String getAccessTokenEndpoint(); + + protected abstract String getAuthorizationBaseUrl(); + + /** + * Returns the URL where you should redirect your users to authenticate your application. + * + * @param requestToken the request token you need to authorize + * @return the URL where you should redirect your users + */ + public String getAuthorizationUrl(OAuth1RequestToken requestToken) { + final ParameterList parameters = new ParameterList(); + parameters.add(OAuthConstants.TOKEN, requestToken.getToken()); + return parameters.appendTo(getAuthorizationBaseUrl()); + } + + public OAuth10aService createService(String apiKey, String apiSecret, String callback, String scope, + OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, HttpClient httpClient) { + return new OAuth10aService(this, apiKey, apiSecret, callback, scope, debugStream, userAgent, httpClientConfig, + httpClient); + } + + /** + * http://tools.ietf.org/html/rfc5849 says that "The client MAY omit the empty "oauth_token" protocol parameter from + * the request", but not all oauth servers are good boys. + * + * @return whether to inlcude empty oauth_token param to the request + */ + public boolean isEmptyOAuthTokenParamIsRequired() { + return false; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/builder/api/DefaultApi20.java b/scribejava-core/src/main/java/com/github/scribejava/core/builder/api/DefaultApi20.java new file mode 100644 index 000000000..76ef6dbce --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/builder/api/DefaultApi20.java @@ -0,0 +1,140 @@ +package com.github.scribejava.core.builder.api; + +import com.github.scribejava.core.extractors.DeviceAuthorizationJsonExtractor; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.ParameterList; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureAuthorizationRequestHeaderField; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.HttpBasicAuthenticationScheme; + +import java.io.OutputStream; +import java.util.Map; + +/** + * Default implementation of the OAuth protocol, version 2.0 + * + * This class is meant to be extended by concrete implementations of the API, providing the endpoints and + * endpoint-http-verbs. + * + * If your API adheres to the 2.0 protocol correctly, you just need to extend this class and define the getters for your + * endpoints. + * + * If your API does something a bit different, you can override the different extractors or services, in order to + * fine-tune the process. Please read the javadocs of the interfaces to get an idea of what to do. + * + */ +public abstract class DefaultApi20 { + + /** + * Returns the access token extractor. + * + * @return access token extractor + */ + public TokenExtractor getAccessTokenExtractor() { + return OAuth2AccessTokenJsonExtractor.instance(); + } + + /** + * Returns the verb for the access token endpoint (defaults to POST) + * + * @return access token endpoint verb + */ + public Verb getAccessTokenVerb() { + return Verb.POST; + } + + /** + * Returns the URL that receives the access token requests. + * + * @return access token URL + */ + public abstract String getAccessTokenEndpoint(); + + public String getRefreshTokenEndpoint() { + return getAccessTokenEndpoint(); + } + + /** + * As stated in RFC 7009 OAuth 2.0 Token Revocation + * + * @return endpoint, which allows clients to notify the authorization server that a previously obtained refresh or + * access token is no longer needed. + * @see RFC 7009 + */ + public String getRevokeTokenEndpoint() { + throw new UnsupportedOperationException( + "This API doesn't support revoking tokens or we have no info about this"); + } + + protected abstract String getAuthorizationBaseUrl(); + + /** + * Returns the URL where you should redirect your users to authenticate your application. + * + * @param responseType responseType + * @param apiKey apiKey + * @param additionalParams any additional GET params to add to the URL + * @param callback callback + * @param state state + * @param scope scope + * @return the URL where you should redirect your users + */ + public String getAuthorizationUrl(String responseType, String apiKey, String callback, String scope, String state, + Map additionalParams) { + final ParameterList parameters = new ParameterList(additionalParams); + parameters.add(OAuthConstants.RESPONSE_TYPE, responseType); + parameters.add(OAuthConstants.CLIENT_ID, apiKey); + + if (callback != null) { + parameters.add(OAuthConstants.REDIRECT_URI, callback); + } + + if (scope != null) { + parameters.add(OAuthConstants.SCOPE, scope); + } + + if (state != null) { + parameters.add(OAuthConstants.STATE, state); + } + + return parameters.appendTo(getAuthorizationBaseUrl()); + } + + public OAuth20Service createService(String apiKey, String apiSecret, String callback, String defaultScope, + String responseType, OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, + HttpClient httpClient) { + return new OAuth20Service(this, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, userAgent, + httpClientConfig, httpClient); + } + + public BearerSignature getBearerSignature() { + return BearerSignatureAuthorizationRequestHeaderField.instance(); + } + + public ClientAuthentication getClientAuthentication() { + return HttpBasicAuthenticationScheme.instance(); + } + + /** + * RFC 8628 OAuth 2.0 Device Authorization Grant + * + * @see RFC 8628 + * @return the device authorization endpoint + */ + public String getDeviceAuthorizationEndpoint() { + throw new UnsupportedOperationException( + "This API doesn't support Device Authorization Grant or we have no info about this"); + } + + public DeviceAuthorizationJsonExtractor getDeviceAuthorizationExtractor() { + return DeviceAuthorizationJsonExtractor.instance(); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/builder/api/OAuth1SignatureType.java b/scribejava-core/src/main/java/com/github/scribejava/core/builder/api/OAuth1SignatureType.java new file mode 100644 index 000000000..7de68ff7b --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/builder/api/OAuth1SignatureType.java @@ -0,0 +1,7 @@ +package com.github.scribejava.core.builder.api; + +public enum OAuth1SignatureType { + + HEADER, + QUERY_STRING +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/exceptions/OAuthException.java b/scribejava-core/src/main/java/com/github/scribejava/core/exceptions/OAuthException.java new file mode 100644 index 000000000..1680b2a44 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/exceptions/OAuthException.java @@ -0,0 +1,38 @@ +package com.github.scribejava.core.exceptions; + +/** + * Default ScribeJava exception. Represents a problem in the OAuth signing + * process + */ +public class OAuthException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + /** + * Default constructor + * + * @param message message explaining what went wrong + * @param e original exception + */ + public OAuthException(String message, Exception e) { + super(message, e); + } + + /** + * No-exception constructor. Used when there is no original exception + * + * @param message message explaining what went wrong + */ + public OAuthException(String message) { + super(message, null); + } + + /** + * Exception constructor. Used to simply wrap an exception. + * + * @param e original exception + */ + public OAuthException(Exception e) { + super(e); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/exceptions/OAuthParametersMissingException.java b/scribejava-core/src/main/java/com/github/scribejava/core/exceptions/OAuthParametersMissingException.java new file mode 100644 index 000000000..2d4a5dfc4 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/exceptions/OAuthParametersMissingException.java @@ -0,0 +1,22 @@ +package com.github.scribejava.core.exceptions; + +import com.github.scribejava.core.model.OAuthRequest; + +/** + * Specialized exception that represents a missing OAuth parameter. + */ +public class OAuthParametersMissingException extends OAuthException { + + private static final long serialVersionUID = 1745308760111976671L; + private static final String MSG = "Could not find oauth parameters in request: %s. " + + "OAuth parameters must be specified with the addOAuthParameter() method"; + + /** + * Default constructor. + * + * @param request OAuthRequest that caused the error + */ + public OAuthParametersMissingException(OAuthRequest request) { + super(String.format(MSG, request)); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/exceptions/OAuthSignatureException.java b/scribejava-core/src/main/java/com/github/scribejava/core/exceptions/OAuthSignatureException.java new file mode 100644 index 000000000..53bffbb7c --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/exceptions/OAuthSignatureException.java @@ -0,0 +1,21 @@ +package com.github.scribejava.core.exceptions; + +/** + * Specialized exception that represents a problem in the signature + */ +public class OAuthSignatureException extends OAuthException { + + private static final long serialVersionUID = 1L; + private static final String MSG = "Error while signing string: %s"; + + /** + * Default constructor + * + * @param stringToSign plain string that gets signed (HMAC-SHA, etc) + * @param e original exception + */ + public OAuthSignatureException(String stringToSign, Exception e) { + super(String.format(MSG, stringToSign), e); + } + +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/extractors/AbstractJsonExtractor.java b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/AbstractJsonExtractor.java new file mode 100644 index 000000000..4a592a706 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/AbstractJsonExtractor.java @@ -0,0 +1,22 @@ +package com.github.scribejava.core.extractors; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.scribejava.core.exceptions.OAuthException; + +public abstract class AbstractJsonExtractor { + + protected static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + protected static JsonNode extractRequiredParameter(JsonNode errorNode, String parameterName, String rawResponse) + throws OAuthException { + final JsonNode value = errorNode.get(parameterName); + + if (value == null) { + throw new OAuthException("Response body is incorrect. Can't extract a '" + parameterName + + "' from this: '" + rawResponse + "'", null); + } + + return value; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/extractors/AbstractOAuth1JSONTokenExtractor.java b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/AbstractOAuth1JSONTokenExtractor.java new file mode 100644 index 000000000..5c42e812a --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/AbstractOAuth1JSONTokenExtractor.java @@ -0,0 +1,38 @@ +package com.github.scribejava.core.extractors; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.scribejava.core.exceptions.OAuthException; +import com.github.scribejava.core.model.OAuth1Token; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.utils.Preconditions; + +import java.io.IOException; + + +public abstract class AbstractOAuth1JSONTokenExtractor implements TokenExtractor { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + @Override + public T extract(Response response) throws IOException { + final String rawBody = response.getBody(); + Preconditions.checkEmptyString(rawBody, + "Response body is incorrect. Can't extract a token from an empty string"); + + final JsonNode body = OBJECT_MAPPER.readTree(rawBody); + + final JsonNode token = body.get(OAuthConstants.TOKEN); + final JsonNode secret = body.get(OAuthConstants.TOKEN_SECRET); + + if (token == null || secret == null) { + throw new OAuthException("Response body is incorrect. Can't extract token and secret from this: '" + + rawBody + '\'', null); + } + + return createToken(token.asText(), secret.asText(), rawBody); + } + + protected abstract T createToken(String token, String secret, String response); +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/extractors/AbstractOAuth1TokenExtractor.java b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/AbstractOAuth1TokenExtractor.java new file mode 100644 index 000000000..61578d01b --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/AbstractOAuth1TokenExtractor.java @@ -0,0 +1,48 @@ +package com.github.scribejava.core.extractors; + +import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import com.github.scribejava.core.exceptions.OAuthException; +import com.github.scribejava.core.model.OAuth1Token; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.utils.OAuthEncoder; +import com.github.scribejava.core.utils.Preconditions; + +/** + * Abstract base implementation of {@link TokenExtractor} for OAuth 1.0a + * + * The process for extracting access and request tokens is similar so this class can do both things. + * + * @param concrete type of OAuth1Token. access or request + */ +public abstract class AbstractOAuth1TokenExtractor implements TokenExtractor { + + private static final Pattern OAUTH_TOKEN_REGEXP_PATTERN = Pattern.compile("oauth_token=([^&]+)"); + private static final Pattern OAUTH_TOKEN_SECRET_REGEXP_PATTERN = Pattern.compile("oauth_token_secret=([^&]*)"); + + /** + * {@inheritDoc} + */ + @Override + public T extract(Response response) throws IOException { + final String body = response.getBody(); + Preconditions.checkEmptyString(body, + "Response body is incorrect. Can't extract a token from an empty string"); + final String token = extract(body, OAUTH_TOKEN_REGEXP_PATTERN); + final String secret = extract(body, OAUTH_TOKEN_SECRET_REGEXP_PATTERN); + return createToken(token, secret, body); + } + + private String extract(String response, Pattern p) { + final Matcher matcher = p.matcher(response); + if (matcher.find() && matcher.groupCount() >= 1) { + return OAuthEncoder.decode(matcher.group(1)); + } else { + throw new OAuthException("Response body is incorrect. Can't extract token and secret from this: '" + + response + "'", null); + } + } + + protected abstract T createToken(String token, String secret, String response); +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/extractors/BaseStringExtractor.java b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/BaseStringExtractor.java new file mode 100644 index 000000000..21cb3431b --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/BaseStringExtractor.java @@ -0,0 +1,19 @@ +package com.github.scribejava.core.extractors; + +import com.github.scribejava.core.model.OAuthRequest; + +/** + * Simple command object that extracts a base string from a {@link OAuthRequest} + */ +public interface BaseStringExtractor { + + /** + * Extracts an url-encoded base string from the {@link OAuthRequest}. + * + * See the oauth spec for more info on this. + * + * @param request the OAuthRequest + * @return the url-encoded base string + */ + String extract(OAuthRequest request); +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/extractors/BaseStringExtractorImpl.java b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/BaseStringExtractorImpl.java new file mode 100644 index 000000000..3547fbcac --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/BaseStringExtractorImpl.java @@ -0,0 +1,57 @@ +package com.github.scribejava.core.extractors; + +import com.github.scribejava.core.exceptions.OAuthParametersMissingException; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.ParameterList; +import com.github.scribejava.core.utils.OAuthEncoder; +import com.github.scribejava.core.utils.Preconditions; + +/** + * Default implementation of {@link BaseStringExtractor}. Conforms to OAuth 1.0a + * https://tools.ietf.org/html/rfc5849#section-3.4.1.1 + */ +public class BaseStringExtractorImpl implements BaseStringExtractor { + + protected static final String AMPERSAND_SEPARATED_STRING = "%s&%s&%s"; + + /** + * {@inheritDoc} + */ + @Override + public String extract(OAuthRequest request) { + checkPreconditions(request); + final String verb = OAuthEncoder.encode(getVerb(request)); + final String url = OAuthEncoder.encode(getUrl(request)); + final String params = getSortedAndEncodedParams(request); + return String.format(AMPERSAND_SEPARATED_STRING, verb, url, params); + } + + protected String getVerb(OAuthRequest request) { + return request.getVerb().name(); + } + + /** + * https://tools.ietf.org/html/rfc5849#section-3.4.1.2 + * @param request request + * @return url + */ + protected String getUrl(OAuthRequest request) { + return request.getSanitizedUrl(); + } + + protected String getSortedAndEncodedParams(OAuthRequest request) { + final ParameterList params = new ParameterList(); + params.addAll(request.getQueryStringParams()); + params.addAll(request.getBodyParams()); + params.addAll(new ParameterList(request.getOauthParameters())); + return params.sort().asOauthBaseString(); + } + + protected void checkPreconditions(OAuthRequest request) { + Preconditions.checkNotNull(request, "Cannot extract base string from a null object"); + + if (request.getOauthParameters() == null || request.getOauthParameters().size() <= 0) { + throw new OAuthParametersMissingException(request); + } + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/extractors/DeviceAuthorizationJsonExtractor.java b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/DeviceAuthorizationJsonExtractor.java new file mode 100644 index 000000000..5b4fa248b --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/DeviceAuthorizationJsonExtractor.java @@ -0,0 +1,61 @@ +package com.github.scribejava.core.extractors; + +import static com.github.scribejava.core.extractors.AbstractJsonExtractor.OBJECT_MAPPER; +import static com.github.scribejava.core.extractors.AbstractJsonExtractor.extractRequiredParameter; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.scribejava.core.model.DeviceAuthorization; +import java.io.IOException; +import com.github.scribejava.core.model.Response; + +public class DeviceAuthorizationJsonExtractor extends AbstractJsonExtractor { + + protected DeviceAuthorizationJsonExtractor() { + } + + private static class InstanceHolder { + + private static final DeviceAuthorizationJsonExtractor INSTANCE = new DeviceAuthorizationJsonExtractor(); + } + + public static DeviceAuthorizationJsonExtractor instance() { + return InstanceHolder.INSTANCE; + } + + public DeviceAuthorization extract(Response response) throws IOException { + if (response.getCode() != 200) { + generateError(response); + } + return createDeviceAuthorization(response.getBody()); + } + + public void generateError(Response response) throws IOException { + OAuth2AccessTokenJsonExtractor.instance().generateError(response); + } + + private DeviceAuthorization createDeviceAuthorization(String rawResponse) throws IOException { + + final JsonNode response = OBJECT_MAPPER.readTree(rawResponse); + + final DeviceAuthorization deviceAuthorization = new DeviceAuthorization( + extractRequiredParameter(response, "device_code", rawResponse).textValue(), + extractRequiredParameter(response, "user_code", rawResponse).textValue(), + extractRequiredParameter(response, getVerificationUriParamName(), rawResponse).textValue(), + extractRequiredParameter(response, "expires_in", rawResponse).intValue()); + + final JsonNode intervalSeconds = response.get("interval"); + if (intervalSeconds != null) { + deviceAuthorization.setIntervalSeconds(intervalSeconds.asInt(5)); + } + + final JsonNode verificationUriComplete = response.get("verification_uri_complete"); + if (verificationUriComplete != null) { + deviceAuthorization.setVerificationUriComplete(verificationUriComplete.asText()); + } + + return deviceAuthorization; + } + + protected String getVerificationUriParamName() { + return "verification_uri"; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/extractors/HeaderExtractor.java b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/HeaderExtractor.java new file mode 100644 index 000000000..e6e6156e4 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/HeaderExtractor.java @@ -0,0 +1,17 @@ +package com.github.scribejava.core.extractors; + +import com.github.scribejava.core.model.OAuthRequest; + +/** + * Simple command object that generates an OAuth Authorization header to include in the request. + */ +public interface HeaderExtractor { + + /** + * Generates an OAuth 'Authorization' Http header to include in requests as the signature. + * + * @param request the AbstractRequest to inspect and generate the header + * @return the Http header value + */ + String extract(OAuthRequest request); +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/extractors/HeaderExtractorImpl.java b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/HeaderExtractorImpl.java new file mode 100644 index 000000000..5ffe0c023 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/HeaderExtractorImpl.java @@ -0,0 +1,56 @@ +package com.github.scribejava.core.extractors; + +import java.util.Map; +import com.github.scribejava.core.exceptions.OAuthParametersMissingException; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.utils.OAuthEncoder; +import com.github.scribejava.core.utils.Preconditions; + +/** + * Default implementation of {@link HeaderExtractor}. Conforms to OAuth 1.0a + */ +public class HeaderExtractorImpl implements HeaderExtractor { + + private static final String PARAM_SEPARATOR = ", "; + private static final String PREAMBLE = "OAuth "; + + /** + * {@inheritDoc} + */ + @Override + public String extract(OAuthRequest request) { + checkPreconditions(request); + final Map parameters = request.getOauthParameters(); + + final StringBuilder header = new StringBuilder(PREAMBLE); + + for (Map.Entry parameter : parameters.entrySet()) { + if (header.length() > PREAMBLE.length()) { + header.append(PARAM_SEPARATOR); + } + header.append(parameter.getKey()) + .append("=\"") + .append(OAuthEncoder.encode(parameter.getValue())) + .append('"'); + } + + if (request.getRealm() != null && !request.getRealm().isEmpty()) { + header.append(PARAM_SEPARATOR) + .append(OAuthConstants.REALM) + .append("=\"") + .append(request.getRealm()) + .append('"'); + } + return header.toString(); + } + + private void checkPreconditions(OAuthRequest request) { + Preconditions.checkNotNull(request, "Cannot extract a header from a null object"); + + if (request.getOauthParameters() == null || request.getOauthParameters().size() <= 0) { + throw new OAuthParametersMissingException(request); + } + } + +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth1AccessTokenExtractor.java b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth1AccessTokenExtractor.java new file mode 100644 index 000000000..33c9c2e35 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth1AccessTokenExtractor.java @@ -0,0 +1,24 @@ +package com.github.scribejava.core.extractors; + +import com.github.scribejava.core.model.OAuth1AccessToken; + +public class OAuth1AccessTokenExtractor extends AbstractOAuth1TokenExtractor { + + protected OAuth1AccessTokenExtractor() { + } + + private static class InstanceHolder { + + private static final OAuth1AccessTokenExtractor INSTANCE = new OAuth1AccessTokenExtractor(); + } + + public static OAuth1AccessTokenExtractor instance() { + return InstanceHolder.INSTANCE; + } + + @Override + protected OAuth1AccessToken createToken(String token, String secret, String response) { + return new OAuth1AccessToken(token, secret, response); + } + +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth1AccessTokenJSONExtractor.java b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth1AccessTokenJSONExtractor.java new file mode 100644 index 000000000..9267f80b4 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth1AccessTokenJSONExtractor.java @@ -0,0 +1,23 @@ +package com.github.scribejava.core.extractors; + +import com.github.scribejava.core.model.OAuth1AccessToken; + +public class OAuth1AccessTokenJSONExtractor extends AbstractOAuth1JSONTokenExtractor { + + protected OAuth1AccessTokenJSONExtractor() { + } + + @Override + protected OAuth1AccessToken createToken(String token, String secret, String response) { + return new OAuth1AccessToken(token, secret, response); + } + + private static class InstanceHolder { + + private static final OAuth1AccessTokenJSONExtractor INSTANCE = new OAuth1AccessTokenJSONExtractor(); + } + + public static OAuth1AccessTokenJSONExtractor instance() { + return InstanceHolder.INSTANCE; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth1RequestTokenExtractor.java b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth1RequestTokenExtractor.java new file mode 100644 index 000000000..516612713 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth1RequestTokenExtractor.java @@ -0,0 +1,23 @@ +package com.github.scribejava.core.extractors; + +import com.github.scribejava.core.model.OAuth1RequestToken; + +public class OAuth1RequestTokenExtractor extends AbstractOAuth1TokenExtractor { + + protected OAuth1RequestTokenExtractor() { + } + + private static class InstanceHolder { + + private static final OAuth1RequestTokenExtractor INSTANCE = new OAuth1RequestTokenExtractor(); + } + + public static OAuth1RequestTokenExtractor instance() { + return InstanceHolder.INSTANCE; + } + + @Override + protected OAuth1RequestToken createToken(String token, String secret, String response) { + return new OAuth1RequestToken(token, secret, response); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth1RequestTokenJSONExtractor.java b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth1RequestTokenJSONExtractor.java new file mode 100644 index 000000000..875337a82 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth1RequestTokenJSONExtractor.java @@ -0,0 +1,23 @@ +package com.github.scribejava.core.extractors; + +import com.github.scribejava.core.model.OAuth1RequestToken; + +public class OAuth1RequestTokenJSONExtractor extends AbstractOAuth1JSONTokenExtractor { + + protected OAuth1RequestTokenJSONExtractor() { + } + + @Override + protected OAuth1RequestToken createToken(String token, String secret, String response) { + return new OAuth1RequestToken(token, secret, response); + } + + private static class InstanceHolder { + + private static final OAuth1RequestTokenJSONExtractor INSTANCE = new OAuth1RequestTokenJSONExtractor(); + } + + public static OAuth1RequestTokenJSONExtractor instance() { + return InstanceHolder.INSTANCE; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth2AccessTokenExtractor.java b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth2AccessTokenExtractor.java new file mode 100644 index 000000000..855a03c43 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth2AccessTokenExtractor.java @@ -0,0 +1,76 @@ +package com.github.scribejava.core.extractors; + +import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.github.scribejava.core.exceptions.OAuthException; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.utils.OAuthEncoder; +import com.github.scribejava.core.utils.Preconditions; + +/** + * Custom implementation of {@link TokenExtractor} for OAuth 2.0 + */ +public class OAuth2AccessTokenExtractor implements TokenExtractor { + + private static final Pattern ACCESS_TOKEN_REGEX_PATTERN = Pattern.compile("access_token=([^&]+)"); + private static final Pattern TOKEN_TYPE_REGEX_PATTERN = Pattern.compile("token_type=([^&]+)"); + private static final Pattern EXPIRES_IN_REGEX_PATTERN = Pattern.compile("expires_in=([^&]+)"); + private static final Pattern REFRESH_TOKEN_REGEX_PATTERN = Pattern.compile("refresh_token=([^&]+)"); + private static final Pattern SCOPE_REGEX_PATTERN = Pattern.compile("scope=([^&]+)"); + + protected OAuth2AccessTokenExtractor() { + } + + private static class InstanceHolder { + + private static final OAuth2AccessTokenExtractor INSTANCE = new OAuth2AccessTokenExtractor(); + } + + public static OAuth2AccessTokenExtractor instance() { + return InstanceHolder.INSTANCE; + } + + /** + * {@inheritDoc} + */ + @Override + public OAuth2AccessToken extract(Response response) throws IOException { + if (response.getCode() != 200) { + throw new OAuthException("Response code is not 200 but '" + response.getCode() + '\''); + } + final String body = response.getBody(); + Preconditions.checkEmptyString(body, + "Response body is incorrect. Can't extract a token from an empty string"); + + final String accessToken = extractParameter(body, ACCESS_TOKEN_REGEX_PATTERN, true); + final String tokenType = extractParameter(body, TOKEN_TYPE_REGEX_PATTERN, false); + final String expiresInString = extractParameter(body, EXPIRES_IN_REGEX_PATTERN, false); + Integer expiresIn; + try { + expiresIn = expiresInString == null ? null : Integer.valueOf(expiresInString); + } catch (NumberFormatException nfe) { + expiresIn = null; + } + final String refreshToken = extractParameter(body, REFRESH_TOKEN_REGEX_PATTERN, false); + final String scope = extractParameter(body, SCOPE_REGEX_PATTERN, false); + + return new OAuth2AccessToken(accessToken, tokenType, expiresIn, refreshToken, scope, body); + } + + private static String extractParameter(String response, Pattern regexPattern, boolean required) + throws OAuthException { + + final Matcher matcher = regexPattern.matcher(response); + if (matcher.find()) { + return OAuthEncoder.decode(matcher.group(1)); + } else if (required) { + throw new OAuthException("Response body is incorrect. Can't extract a '" + regexPattern.pattern() + + "' from this: '" + response + "'", null); + } else { + return null; + } + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth2AccessTokenJsonExtractor.java b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth2AccessTokenJsonExtractor.java new file mode 100644 index 000000000..b9bfd6cba --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth2AccessTokenJsonExtractor.java @@ -0,0 +1,100 @@ +package com.github.scribejava.core.extractors; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import java.io.IOException; +import java.net.URI; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuth2AccessTokenErrorResponse; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.oauth2.OAuth2Error; +import com.github.scribejava.core.utils.Preconditions; + +/** + * JSON (default) implementation of {@link TokenExtractor} for OAuth 2.0 + */ +public class OAuth2AccessTokenJsonExtractor extends AbstractJsonExtractor implements TokenExtractor { + + protected OAuth2AccessTokenJsonExtractor() { + } + + private static class InstanceHolder { + + private static final OAuth2AccessTokenJsonExtractor INSTANCE = new OAuth2AccessTokenJsonExtractor(); + } + + public static OAuth2AccessTokenJsonExtractor instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public OAuth2AccessToken extract(Response response) throws IOException { + final String body = response.getBody(); + Preconditions.checkEmptyString(body, "Response body is incorrect. Can't extract a token from an empty string"); + + if (response.getCode() != 200) { + generateError(response); + } + return createToken(body); + } + + /** + * Related documentation: https://tools.ietf.org/html/rfc6749#section-5.2 + * + * @param response response + * @throws java.io.IOException IOException + * + */ + public void generateError(Response response) throws IOException { + final String responseBody = response.getBody(); + final JsonNode responseBodyJson; + try { + responseBodyJson = OBJECT_MAPPER.readTree(responseBody); + } catch (JsonProcessingException ex) { + throw new OAuth2AccessTokenErrorResponse(null, null, null, response); + } + + final JsonNode errorUriInString = responseBodyJson.get("error_uri"); + URI errorUri; + try { + errorUri = errorUriInString == null ? null : URI.create(errorUriInString.asText()); + } catch (IllegalArgumentException iae) { + errorUri = null; + } + + OAuth2Error errorCode; + try { + errorCode = OAuth2Error + .parseFrom(extractRequiredParameter(responseBodyJson, "error", responseBody).asText()); + } catch (IllegalArgumentException iaE) { + //non oauth standard error code + errorCode = null; + } + + final JsonNode errorDescription = responseBodyJson.get("error_description"); + + throw new OAuth2AccessTokenErrorResponse(errorCode, errorDescription == null ? null : errorDescription.asText(), + errorUri, response); + } + + private OAuth2AccessToken createToken(String rawResponse) throws IOException { + + final JsonNode response = OBJECT_MAPPER.readTree(rawResponse); + + final JsonNode expiresInNode = response.get("expires_in"); + final JsonNode refreshToken = response.get(OAuthConstants.REFRESH_TOKEN); + final JsonNode scope = response.get(OAuthConstants.SCOPE); + final JsonNode tokenType = response.get("token_type"); + + return createToken(extractRequiredParameter(response, OAuthConstants.ACCESS_TOKEN, rawResponse).asText(), + tokenType == null ? null : tokenType.asText(), expiresInNode == null ? null : expiresInNode.asInt(), + refreshToken == null ? null : refreshToken.asText(), scope == null ? null : scope.asText(), response, + rawResponse); + } + + protected OAuth2AccessToken createToken(String accessToken, String tokenType, Integer expiresIn, + String refreshToken, String scope, JsonNode response, String rawResponse) { + return new OAuth2AccessToken(accessToken, tokenType, expiresIn, refreshToken, scope, rawResponse); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/extractors/TokenExtractor.java b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/TokenExtractor.java new file mode 100644 index 000000000..00c662d81 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/extractors/TokenExtractor.java @@ -0,0 +1,23 @@ +package com.github.scribejava.core.extractors; + +import com.github.scribejava.core.exceptions.OAuthException; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Token; + +import java.io.IOException; + +/** + * Simple command object that extracts a concrete {@link Token} from a String + * @param concrete type of Token + */ +public interface TokenExtractor { + + /** + * Extracts the concrete type of token from the contents of an Http Response + * + * @param response the whole response + * @return OAuth access token + * @throws java.io.IOException in case of troubles while getting body from the response + */ + T extract(Response response) throws IOException, OAuthException; +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/AbstractAsyncOnlyHttpClient.java b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/AbstractAsyncOnlyHttpClient.java new file mode 100644 index 000000000..10b3d5faa --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/AbstractAsyncOnlyHttpClient.java @@ -0,0 +1,102 @@ +package com.github.scribejava.core.httpclient; + +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import java.io.File; +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +public abstract class AbstractAsyncOnlyHttpClient implements HttpClient { + + @Override + public Response execute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + byte[] bodyContents) throws InterruptedException, ExecutionException, IOException { + + final OAuthAsyncRequestThrowableHolderCallback oAuthAsyncRequestThrowableHolderCallback + = new OAuthAsyncRequestThrowableHolderCallback(); + + final Response response = executeAsync(userAgent, headers, httpVerb, completeUrl, bodyContents, + oAuthAsyncRequestThrowableHolderCallback, null).get(); + + final Throwable throwable = oAuthAsyncRequestThrowableHolderCallback.getThrowable(); + if (throwable != null) { + throw new ExecutionException(throwable); + } + return response; + } + + @Override + public Response execute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + com.github.scribejava.core.httpclient.multipart.MultipartPayload bodyContents) + throws InterruptedException, ExecutionException, IOException { + + final OAuthAsyncRequestThrowableHolderCallback oAuthAsyncRequestThrowableHolderCallback + = new OAuthAsyncRequestThrowableHolderCallback(); + + final Response response = executeAsync(userAgent, headers, httpVerb, completeUrl, bodyContents, + oAuthAsyncRequestThrowableHolderCallback, null).get(); + + final Throwable throwable = oAuthAsyncRequestThrowableHolderCallback.getThrowable(); + if (throwable != null) { + throw new ExecutionException(throwable); + } + + return response; + } + + @Override + public Response execute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + String bodyContents) throws InterruptedException, ExecutionException, IOException { + + final OAuthAsyncRequestThrowableHolderCallback oAuthAsyncRequestThrowableHolderCallback + = new OAuthAsyncRequestThrowableHolderCallback(); + + final Response response = executeAsync(userAgent, headers, httpVerb, completeUrl, bodyContents, + oAuthAsyncRequestThrowableHolderCallback, null).get(); + + final Throwable throwable = oAuthAsyncRequestThrowableHolderCallback.getThrowable(); + if (throwable != null) { + throw new ExecutionException(throwable); + } + + return response; + } + + @Override + public Response execute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + File bodyContents) throws InterruptedException, ExecutionException, IOException { + + final OAuthAsyncRequestThrowableHolderCallback oAuthAsyncRequestThrowableHolderCallback + = new OAuthAsyncRequestThrowableHolderCallback(); + + final Response response = executeAsync(userAgent, headers, httpVerb, completeUrl, bodyContents, + oAuthAsyncRequestThrowableHolderCallback, null).get(); + + final Throwable throwable = oAuthAsyncRequestThrowableHolderCallback.getThrowable(); + if (throwable != null) { + throw new ExecutionException(throwable); + } + + return response; + } + + private class OAuthAsyncRequestThrowableHolderCallback implements OAuthAsyncRequestCallback { + + private Throwable throwable; + + @Override + public void onCompleted(Response response) { + } + + @Override + public void onThrowable(Throwable t) { + throwable = t; + } + + public Throwable getThrowable() { + return throwable; + } + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/HttpClient.java b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/HttpClient.java new file mode 100644 index 000000000..821c9b194 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/HttpClient.java @@ -0,0 +1,45 @@ +package com.github.scribejava.core.httpclient; + +import com.github.scribejava.core.httpclient.multipart.MultipartPayload; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +public interface HttpClient extends Closeable { + + String DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded"; + String CONTENT_TYPE = "Content-Type"; + String CONTENT_LENGTH = "Content-Length"; + + Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + byte[] bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter); + + Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + MultipartPayload bodyContents, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter); + + Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + String bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter); + + Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + File bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter); + + Response execute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + byte[] bodyContents) throws InterruptedException, ExecutionException, IOException; + + Response execute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + MultipartPayload bodyContents) throws InterruptedException, ExecutionException, IOException; + + Response execute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + String bodyContents) throws InterruptedException, ExecutionException, IOException; + + Response execute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + File bodyContents) throws InterruptedException, ExecutionException, IOException; +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/HttpClientConfig.java b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/HttpClientConfig.java new file mode 100644 index 000000000..3c28d6249 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/HttpClientConfig.java @@ -0,0 +1,6 @@ +package com.github.scribejava.core.httpclient; + +public interface HttpClientConfig { + + HttpClientConfig createDefaultConfig(); +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/HttpClientProvider.java b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/HttpClientProvider.java new file mode 100644 index 000000000..5b69156d2 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/HttpClientProvider.java @@ -0,0 +1,6 @@ +package com.github.scribejava.core.httpclient; + +public interface HttpClientProvider { + + HttpClient createClient(HttpClientConfig httpClientConfig); +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/jdk/JDKHttpClient.java b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/jdk/JDKHttpClient.java new file mode 100644 index 000000000..b500ba997 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/jdk/JDKHttpClient.java @@ -0,0 +1,234 @@ +package com.github.scribejava.core.httpclient.jdk; + +import com.github.scribejava.core.exceptions.OAuthException; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.multipart.MultipartPayload; +import com.github.scribejava.core.httpclient.multipart.MultipartUtils; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +public class JDKHttpClient implements HttpClient { + + private final JDKHttpClientConfig config; + + public JDKHttpClient() { + this(JDKHttpClientConfig.defaultConfig()); + } + + public JDKHttpClient(JDKHttpClientConfig clientConfig) { + config = clientConfig; + } + + @Override + public void close() { + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + byte[] bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter) { + + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodyType.BYTE_ARRAY, bodyContents, callback, + converter); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + MultipartPayload bodyContents, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodyType.MULTIPART, bodyContents, callback, + converter); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + String bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter) { + + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodyType.STRING, bodyContents, callback, + converter); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + File bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter) { + throw new UnsupportedOperationException("JDKHttpClient does not support File payload for the moment"); + } + + private Future doExecuteAsync(String userAgent, Map headers, Verb httpVerb, + String completeUrl, BodyType bodyType, Object bodyContents, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + try { + final Response response = doExecute(userAgent, headers, httpVerb, completeUrl, bodyType, bodyContents); + @SuppressWarnings("unchecked") + final T t = converter == null ? (T) response : converter.convert(response); + if (callback != null) { + callback.onCompleted(t); + } + return new JDKHttpFuture<>(t); + } catch (IOException | RuntimeException e) { + if (callback != null) { + callback.onThrowable(e); + } + return new JDKHttpFuture<>(e); + } + } + + @Override + public Response execute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + byte[] bodyContents) throws InterruptedException, ExecutionException, IOException { + return doExecute(userAgent, headers, httpVerb, completeUrl, BodyType.BYTE_ARRAY, bodyContents); + } + + @Override + public Response execute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + MultipartPayload multipartPayloads) throws InterruptedException, ExecutionException, IOException { + return doExecute(userAgent, headers, httpVerb, completeUrl, BodyType.MULTIPART, multipartPayloads); + } + + @Override + public Response execute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + String bodyContents) throws InterruptedException, ExecutionException, IOException { + return doExecute(userAgent, headers, httpVerb, completeUrl, BodyType.STRING, bodyContents); + } + + @Override + public Response execute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + File bodyContents) throws InterruptedException, ExecutionException, IOException { + throw new UnsupportedOperationException("JDKHttpClient does not support File payload for the moment"); + } + + private Response doExecute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + BodyType bodyType, Object bodyContents) throws IOException { + final URL url = new URL(completeUrl); + final HttpURLConnection connection; + if (config.getProxy() == null) { + connection = (HttpURLConnection) url.openConnection(); + } else { + connection = (HttpURLConnection) url.openConnection(config.getProxy()); + } + connection.setInstanceFollowRedirects(config.isFollowRedirects()); + connection.setRequestMethod(httpVerb.name()); + if (config.getConnectTimeout() != null) { + connection.setConnectTimeout(config.getConnectTimeout()); + } + if (config.getReadTimeout() != null) { + connection.setReadTimeout(config.getReadTimeout()); + } + addHeaders(connection, headers, userAgent); + if (httpVerb.isPermitBody()) { + bodyType.setBody(connection, bodyContents, httpVerb.isRequiresBody()); + } + + try { + connection.connect(); + final int responseCode = connection.getResponseCode(); + return new Response(responseCode, connection.getResponseMessage(), parseHeaders(connection), + responseCode >= 200 && responseCode < 400 ? connection.getInputStream() + : connection.getErrorStream()); + } catch (UnknownHostException e) { + throw new OAuthException("The IP address of a host could not be determined.", e); + } + } + + private enum BodyType { + BYTE_ARRAY { + @Override + void setBody(HttpURLConnection connection, Object bodyContents, boolean requiresBody) throws IOException { + addBody(connection, (byte[]) bodyContents, requiresBody); + } + }, + MULTIPART { + @Override + void setBody(HttpURLConnection connection, Object bodyContents, boolean requiresBody) throws IOException { + addBody(connection, (MultipartPayload) bodyContents, requiresBody); + } + }, + STRING { + @Override + void setBody(HttpURLConnection connection, Object bodyContents, boolean requiresBody) throws IOException { + addBody(connection, ((String) bodyContents).getBytes(), requiresBody); + } + }; + + abstract void setBody(HttpURLConnection connection, Object bodyContents, boolean requiresBody) + throws IOException; + } + + private static Map parseHeaders(HttpURLConnection conn) { + final Map headers = new HashMap<>(); + + for (Map.Entry> headerField : conn.getHeaderFields().entrySet()) { + final String key = headerField.getKey(); + final String value = headerField.getValue().get(0); + if ("Content-Encoding".equalsIgnoreCase(key)) { + headers.put("Content-Encoding", value); + } else { + headers.put(key, value); + } + } + return headers; + } + + private static void addHeaders(HttpURLConnection connection, Map headers, String userAgent) { + for (Map.Entry header : headers.entrySet()) { + connection.setRequestProperty(header.getKey(), header.getValue()); + } + + if (userAgent != null) { + connection.setRequestProperty(OAuthConstants.USER_AGENT_HEADER_NAME, userAgent); + } + } + + private static void addBody(HttpURLConnection connection, byte[] content, boolean requiresBody) throws IOException { + final int contentLength = content.length; + if (requiresBody || contentLength > 0) { + final OutputStream outputStream = prepareConnectionForBodyAndGetOutputStream(connection, contentLength); + if (contentLength > 0) { + outputStream.write(content); + } + } + } + + private static void addBody(HttpURLConnection connection, MultipartPayload multipartPayload, boolean requiresBody) + throws IOException { + + for (Map.Entry header : multipartPayload.getHeaders().entrySet()) { + connection.setRequestProperty(header.getKey(), header.getValue()); + } + + if (requiresBody) { + final ByteArrayOutputStream os = MultipartUtils.getPayload(multipartPayload); + final int contentLength = os.size(); + final OutputStream outputStream = prepareConnectionForBodyAndGetOutputStream(connection, contentLength); + if (contentLength > 0) { + os.writeTo(outputStream); + } + } + } + + private static OutputStream prepareConnectionForBodyAndGetOutputStream(HttpURLConnection connection, + int contentLength) throws IOException { + + connection.setRequestProperty(CONTENT_LENGTH, String.valueOf(contentLength)); + if (connection.getRequestProperty(CONTENT_TYPE) == null) { + connection.setRequestProperty(CONTENT_TYPE, DEFAULT_CONTENT_TYPE); + } + connection.setDoOutput(true); + return connection.getOutputStream(); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/jdk/JDKHttpClientConfig.java b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/jdk/JDKHttpClientConfig.java new file mode 100644 index 000000000..3b322b0af --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/jdk/JDKHttpClientConfig.java @@ -0,0 +1,93 @@ +package com.github.scribejava.core.httpclient.jdk; + +import java.net.Proxy; + +import com.github.scribejava.core.httpclient.HttpClientConfig; + +public class JDKHttpClientConfig implements HttpClientConfig { + + private Integer connectTimeout; + private Integer readTimeout; + private boolean followRedirects = true; + private Proxy proxy; + + @Override + public JDKHttpClientConfig createDefaultConfig() { + return defaultConfig(); + } + + public static JDKHttpClientConfig defaultConfig() { + return new JDKHttpClientConfig(); + } + + public Integer getConnectTimeout() { + return connectTimeout; + } + + public void setConnectTimeout(Integer connectTimeout) { + this.connectTimeout = connectTimeout; + } + + public JDKHttpClientConfig withConnectTimeout(Integer connectTimeout) { + this.connectTimeout = connectTimeout; + return this; + } + + public Integer getReadTimeout() { + return readTimeout; + } + + public void setReadTimeout(Integer readTimeout) { + this.readTimeout = readTimeout; + } + + public JDKHttpClientConfig withReadTimeout(Integer readTimeout) { + this.readTimeout = readTimeout; + return this; + } + + public void setProxy(Proxy proxy) { + this.proxy = proxy; + } + + public Proxy getProxy() { + return proxy; + } + + public JDKHttpClientConfig withProxy(Proxy proxy) { + this.proxy = proxy; + return this; + } + + public boolean isFollowRedirects() { + return followRedirects; + } + + /** + * Sets whether the underlying Http Connection follows redirects or not. + * + * Defaults to true (follow redirects) + * + * @see http://docs.oracle.com/javase/6/docs/api/java/net/HttpURLConnection.html#setInstanceFollowRedirects(boolean) + * @param followRedirects boolean + */ + public void setFollowRedirects(boolean followRedirects) { + this.followRedirects = followRedirects; + } + + /** + * Sets whether the underlying Http Connection follows redirects or not. + * + * Defaults to true (follow redirects) + * + * @see http://docs.oracle.com/javase/6/docs/api/java/net/HttpURLConnection.html#setInstanceFollowRedirects(boolean) + * @param followRedirects boolean + * @return this for chaining methods invocations + */ + public JDKHttpClientConfig withFollowRedirects(boolean followRedirects) { + this.followRedirects = followRedirects; + return this; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/jdk/JDKHttpFuture.java b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/jdk/JDKHttpFuture.java new file mode 100644 index 000000000..c4443cc87 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/jdk/JDKHttpFuture.java @@ -0,0 +1,60 @@ +package com.github.scribejava.core.httpclient.jdk; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +/** + * Fake Future. Just to have Future API for the default JDK Http client. It's NOT Async in any way. Just facade.
+ * That's it. Sync execution with Async methods. This class does NOT provide any async executions. + * + * @param + */ +public class JDKHttpFuture implements Future { + + private final Exception exception; + private final V response; + + public JDKHttpFuture(Exception exception) { + this(null, exception); + } + + public JDKHttpFuture(V response) { + this(response, null); + } + + private JDKHttpFuture(V response, Exception exception) { + this.response = response; + this.exception = exception; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return false; + } + + @Override + public boolean isCancelled() { + return false; + } + + @Override + public boolean isDone() { + return true; + } + + @Override + public V get() throws InterruptedException, ExecutionException { + if (exception != null) { + throw new ExecutionException(exception); + } + + return response; + } + + @Override + public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + return get(); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/jdk/JDKHttpProvider.java b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/jdk/JDKHttpProvider.java new file mode 100644 index 000000000..04472e78a --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/jdk/JDKHttpProvider.java @@ -0,0 +1,16 @@ +package com.github.scribejava.core.httpclient.jdk; + +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.httpclient.HttpClientProvider; + +public class JDKHttpProvider implements HttpClientProvider { + + @Override + public HttpClient createClient(HttpClientConfig config) { + if (config instanceof JDKHttpClientConfig) { + return new JDKHttpClient((JDKHttpClientConfig) config); + } + return null; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/multipart/BodyPartPayload.java b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/multipart/BodyPartPayload.java new file mode 100644 index 000000000..ddd6e9cb2 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/multipart/BodyPartPayload.java @@ -0,0 +1,30 @@ +package com.github.scribejava.core.httpclient.multipart; + +import com.github.scribejava.core.httpclient.HttpClient; +import java.util.Collections; +import java.util.Map; + +public abstract class BodyPartPayload { + + private final Map headers; + + public BodyPartPayload() { + this((Map) null); + } + + public BodyPartPayload(String contentType) { + this(convertContentTypeToHeaders(contentType)); + } + + public BodyPartPayload(Map headers) { + this.headers = headers; + } + + public Map getHeaders() { + return headers; + } + + protected static Map convertContentTypeToHeaders(String contentType) { + return contentType == null ? null : Collections.singletonMap(HttpClient.CONTENT_TYPE, contentType); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/multipart/ByteArrayBodyPartPayload.java b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/multipart/ByteArrayBodyPartPayload.java new file mode 100644 index 000000000..c706d7481 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/multipart/ByteArrayBodyPartPayload.java @@ -0,0 +1,50 @@ +package com.github.scribejava.core.httpclient.multipart; + +import java.util.Map; + +public class ByteArrayBodyPartPayload extends BodyPartPayload { + + private final byte[] payload; + private final int off; + private final int len; + + public ByteArrayBodyPartPayload(byte[] payload, int off, int len, Map headers) { + super(headers); + this.payload = payload; + this.off = off; + this.len = len; + } + + public ByteArrayBodyPartPayload(byte[] payload, Map headers) { + this(payload, 0, payload.length, headers); + } + + public ByteArrayBodyPartPayload(byte[] payload, String contentType) { + this(payload, convertContentTypeToHeaders(contentType)); + } + + public ByteArrayBodyPartPayload(byte[] payload, int off, int len, String contentType) { + this(payload, off, len, convertContentTypeToHeaders(contentType)); + } + + public ByteArrayBodyPartPayload(byte[] payload) { + this(payload, (Map) null); + } + + public ByteArrayBodyPartPayload(byte[] payload, int off, int len) { + this(payload, off, len, (Map) null); + } + + public byte[] getPayload() { + return payload; + } + + public int getOff() { + return off; + } + + public int getLen() { + return len; + } + +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/multipart/FileByteArrayBodyPartPayload.java b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/multipart/FileByteArrayBodyPartPayload.java new file mode 100644 index 000000000..41b3e72bf --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/multipart/FileByteArrayBodyPartPayload.java @@ -0,0 +1,77 @@ +package com.github.scribejava.core.httpclient.multipart; + +import com.github.scribejava.core.httpclient.HttpClient; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class FileByteArrayBodyPartPayload extends ByteArrayBodyPartPayload { + + public FileByteArrayBodyPartPayload(byte[] payload) { + this(payload, null); + } + + public FileByteArrayBodyPartPayload(byte[] payload, int off, int len) { + this(payload, off, len, null); + } + + public FileByteArrayBodyPartPayload(byte[] payload, String name) { + this(payload, name, null); + } + + public FileByteArrayBodyPartPayload(byte[] payload, int off, int len, String name) { + this(payload, off, len, name, null); + } + + public FileByteArrayBodyPartPayload(byte[] payload, String name, String filename) { + this(null, payload, name, filename); + } + + public FileByteArrayBodyPartPayload(byte[] payload, int off, int len, String name, String filename) { + this(null, payload, off, len, name, filename); + } + + public FileByteArrayBodyPartPayload(String contentType, byte[] payload) { + this(contentType, payload, null); + } + + public FileByteArrayBodyPartPayload(String contentType, byte[] payload, int off, int len) { + this(contentType, payload, off, len, null); + } + + public FileByteArrayBodyPartPayload(String contentType, byte[] payload, String name) { + this(contentType, payload, name, null); + } + + public FileByteArrayBodyPartPayload(String contentType, byte[] payload, int off, int len, String name) { + this(contentType, payload, off, len, name, null); + } + + public FileByteArrayBodyPartPayload(String contentType, byte[] payload, String name, String filename) { + super(payload, composeHeaders(contentType, name, filename)); + } + + public FileByteArrayBodyPartPayload(String contentType, byte[] payload, int off, int len, String name, + String filename) { + super(payload, off, len, composeHeaders(contentType, name, filename)); + } + + private static Map composeHeaders(String contentType, String name, String filename) { + + String contentDispositionHeader = "form-data"; + if (name != null) { + contentDispositionHeader += "; name=\"" + name + '"'; + } + if (filename != null) { + contentDispositionHeader += "; filename=\"" + filename + '"'; + } + if (contentType == null) { + return Collections.singletonMap("Content-Disposition", contentDispositionHeader); + } else { + final Map headers = new HashMap<>(); + headers.put(HttpClient.CONTENT_TYPE, contentType); + headers.put("Content-Disposition", contentDispositionHeader); + return headers; + } + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/multipart/MultipartPayload.java b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/multipart/MultipartPayload.java new file mode 100644 index 000000000..9d60e0caa --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/multipart/MultipartPayload.java @@ -0,0 +1,110 @@ +package com.github.scribejava.core.httpclient.multipart; + +import com.github.scribejava.core.httpclient.HttpClient; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class MultipartPayload extends BodyPartPayload { + + private static final String DEFAULT_SUBTYPE = "form-data"; + + private final String boundary; + private String preamble; + private final List bodyParts = new ArrayList<>(); + private String epilogue; + + public MultipartPayload() { + this(null, MultipartUtils.generateDefaultBoundary(), null); + } + + public MultipartPayload(String boundary) { + this(null, boundary, null); + } + + public MultipartPayload(String subtype, String boundary) { + this(subtype, boundary, null); + } + + public MultipartPayload(Map headers) { + this(null, parseOrGenerateBoundary(headers), headers); + } + + public MultipartPayload(String boundary, Map headers) { + this(null, boundary, headers); + } + + public MultipartPayload(String subtype, String boundary, Map headers) { + super(composeHeaders(subtype, boundary, headers)); + this.boundary = boundary; + } + + private static Map composeHeaders(String subtype, String boundary, Map headersIn) + throws IllegalArgumentException { + MultipartUtils.checkBoundarySyntax(boundary); + final Map headersOut; + String contentTypeHeader = headersIn == null ? null : headersIn.get(HttpClient.CONTENT_TYPE); + if (contentTypeHeader == null) { + contentTypeHeader = "multipart/" + (subtype == null ? DEFAULT_SUBTYPE : subtype) + + "; boundary=\"" + boundary + '"'; + if (headersIn == null) { + headersOut = Collections.singletonMap(HttpClient.CONTENT_TYPE, contentTypeHeader); + } else { + headersOut = headersIn; + headersOut.put(HttpClient.CONTENT_TYPE, contentTypeHeader); + } + } else { + headersOut = headersIn; + final String parsedBoundary = MultipartUtils.parseBoundaryFromHeader(contentTypeHeader); + if (parsedBoundary == null) { + headersOut.put(HttpClient.CONTENT_TYPE, contentTypeHeader + "; boundary=\"" + boundary + '"'); + } else if (!parsedBoundary.equals(boundary)) { + throw new IllegalArgumentException( + "Different boundaries was passed in constructors. One as argument, second as header"); + } + } + return headersOut; + } + + private static String parseOrGenerateBoundary(Map headers) { + final String parsedBoundary = MultipartUtils.parseBoundaryFromHeader(headers.get(HttpClient.CONTENT_TYPE)); + return parsedBoundary == null ? MultipartUtils.generateDefaultBoundary() : parsedBoundary; + } + + public void addBodyPart(BodyPartPayload bodyPartPayload) { + bodyParts.add(bodyPartPayload); + } + + public void addBodyPart(MultipartPayload multipartPayload) { + if (multipartPayload.getBoundary().equals(boundary)) { + throw new IllegalArgumentException("{'boundary'}={'" + boundary + + "'} is the same for parent MultipartPayload and child"); + } + bodyParts.add(multipartPayload); + } + + public List getBodyParts() { + return bodyParts; + } + + public String getBoundary() { + return boundary; + } + + public String getPreamble() { + return preamble; + } + + public void setPreamble(String preamble) { + this.preamble = preamble; + } + + public String getEpilogue() { + return epilogue; + } + + public void setEpilogue(String epilogue) { + this.epilogue = epilogue; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/multipart/MultipartUtils.java b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/multipart/MultipartUtils.java new file mode 100644 index 000000000..bdbeaf542 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/httpclient/multipart/MultipartUtils.java @@ -0,0 +1,84 @@ +package com.github.scribejava.core.httpclient.multipart; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class MultipartUtils { + + private static final String B_CHARS_NO_SPACE_PATTERN = "0-9a-zA-Z'()+_,-./:=?"; + private static final String B_CHARS_PATTERN = B_CHARS_NO_SPACE_PATTERN + " "; + private static final String BOUNDARY_PATTERN = '[' + B_CHARS_PATTERN + "]{0,69}[" + B_CHARS_NO_SPACE_PATTERN + ']'; + private static final Pattern BOUNDARY_REGEXP = Pattern.compile(BOUNDARY_PATTERN); + private static final Pattern BOUNDARY_FROM_HEADER_REGEXP + = Pattern.compile("; boundary=\"?(" + BOUNDARY_PATTERN + ")\"?"); + + private MultipartUtils() { + } + + public static void checkBoundarySyntax(String boundary) { + if (boundary == null || !BOUNDARY_REGEXP.matcher(boundary).matches()) { + throw new IllegalArgumentException("{'boundary'='" + boundary + "'} has invalid syntax. Should be '" + + BOUNDARY_PATTERN + "'."); + } + } + + public static String parseBoundaryFromHeader(String contentTypeHeader) { + if (contentTypeHeader == null) { + return null; + } + final Matcher matcher = BOUNDARY_FROM_HEADER_REGEXP.matcher(contentTypeHeader); + return matcher.find() ? matcher.group(1) : null; + } + + public static String generateDefaultBoundary() { + return "----ScribeJava----" + System.currentTimeMillis(); + } + + public static ByteArrayOutputStream getPayload(MultipartPayload multipartPayload) throws IOException { + final ByteArrayOutputStream os = new ByteArrayOutputStream(); + + final String preamble = multipartPayload.getPreamble(); + if (preamble != null) { + os.write((preamble + "\r\n").getBytes()); + } + final List bodyParts = multipartPayload.getBodyParts(); + if (!bodyParts.isEmpty()) { + final String boundary = multipartPayload.getBoundary(); + final byte[] startBoundary = ("--" + boundary + "\r\n").getBytes(); + + for (BodyPartPayload bodyPart : bodyParts) { + os.write(startBoundary); + + final Map bodyPartHeaders = bodyPart.getHeaders(); + if (bodyPartHeaders != null) { + for (Map.Entry header : bodyPartHeaders.entrySet()) { + os.write((header.getKey() + ": " + header.getValue() + "\r\n").getBytes()); + } + } + + os.write("\r\n".getBytes()); + if (bodyPart instanceof MultipartPayload) { + getPayload((MultipartPayload) bodyPart).writeTo(os); + } else if (bodyPart instanceof ByteArrayBodyPartPayload) { + final ByteArrayBodyPartPayload byteArrayBodyPart = (ByteArrayBodyPartPayload) bodyPart; + os.write(byteArrayBodyPart.getPayload(), byteArrayBodyPart.getOff(), byteArrayBodyPart.getLen()); + } else { + throw new AssertionError(bodyPart.getClass()); + } + os.write("\r\n".getBytes()); //CRLF for the next (starting or closing) boundary + } + + os.write(("--" + boundary + "--").getBytes()); + final String epilogue = multipartPayload.getEpilogue(); + if (epilogue != null) { + os.write(("\r\n" + epilogue).getBytes()); + } + + } + return os; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/model/DeviceAuthorization.java b/scribejava-core/src/main/java/com/github/scribejava/core/model/DeviceAuthorization.java new file mode 100644 index 000000000..dfdc42c36 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/model/DeviceAuthorization.java @@ -0,0 +1,105 @@ +package com.github.scribejava.core.model; + +/** + * Device Authorization Response + * + * @see rfc8628 + */ +public class DeviceAuthorization { + + /** + * device_code + * + * REQUIRED. The device verification code. + */ + private final String deviceCode; + + /** + * user_code + * + * REQUIRED. The end-user verification code. + */ + private final String userCode; + + /** + * verification_uri + * + * REQUIRED. The end-user verification URI on the authorization server. The URI should be short and easy to remember + * as end users will be asked to manually type it into their user agent. + */ + private final String verificationUri; + + /** + * verification_uri_complete + * + * OPTIONAL. A verification URI that includes the "user_code" (or other information with the same function as the + * "user_code"), which is designed for non-textual transmission. + */ + private String verificationUriComplete; + + /** + * expires_in + * + * REQUIRED. The lifetime in seconds of the "device_code" and "user_code". + */ + private final int expiresInSeconds; + + /** + * interval + * + * OPTIONAL. The minimum amount of time in seconds that the client SHOULD wait between polling requests to the token + * endpoint. If no value is provided, clients MUST use 5 as the default. + */ + private int intervalSeconds = 5; + + public DeviceAuthorization(String deviceCode, String userCode, String verificationUri, int expiresInSeconds) { + this.deviceCode = deviceCode; + this.userCode = userCode; + this.verificationUri = verificationUri; + this.expiresInSeconds = expiresInSeconds; + } + + public void setVerificationUriComplete(String verificationUriComplete) { + this.verificationUriComplete = verificationUriComplete; + } + + public void setIntervalSeconds(int intervalSeconds) { + this.intervalSeconds = intervalSeconds; + } + + public String getDeviceCode() { + return deviceCode; + } + + public String getUserCode() { + return userCode; + } + + public String getVerificationUri() { + return verificationUri; + } + + public String getVerificationUriComplete() { + return verificationUriComplete; + } + + public long getExpiresInSeconds() { + return expiresInSeconds; + } + + public int getIntervalSeconds() { + return intervalSeconds; + } + + @Override + public String toString() { + return "DeviceAuthorization{" + + "'deviceCode'='" + deviceCode + + "', 'userCode'='" + userCode + + "', 'verificationUri'='" + verificationUri + + "', 'verificationUriComplete'='" + verificationUriComplete + + "', 'expiresInSeconds'='" + expiresInSeconds + + "', 'intervalSeconds'='" + intervalSeconds + "'}"; + } + +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth1AccessToken.java b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth1AccessToken.java new file mode 100644 index 000000000..dd145e5c7 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth1AccessToken.java @@ -0,0 +1,65 @@ +package com.github.scribejava.core.model; + +import java.util.Objects; + +/** + * Represents an OAuth 1 Access Token http://tools.ietf.org/html/rfc5849#section-2.3 + */ +public class OAuth1AccessToken extends OAuth1Token { + + private static final long serialVersionUID = -103999293167210966L; + + public OAuth1AccessToken(String token, String tokenSecret) { + this(token, tokenSecret, null); + } + + public OAuth1AccessToken(String token, String tokenSecret, String rawResponse) { + super(token, tokenSecret, rawResponse); + } + + /** + * The token identifier. + * + * @return oauth_token + */ + @Override + public String getToken() { + return super.getToken(); + } + + /** + * The token shared-secret. + * + * @return oauth_token_secret + */ + @Override + public String getTokenSecret() { + return super.getTokenSecret(); + } + + @Override + public int hashCode() { + int hash = 3; + hash = 73 * hash + Objects.hashCode(getToken()); + hash = 73 * hash + Objects.hashCode(getTokenSecret()); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final OAuth1AccessToken other = (OAuth1AccessToken) obj; + if (!Objects.equals(getToken(), other.getToken())) { + return false; + } + return Objects.equals(getTokenSecret(), other.getTokenSecret()); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth1RequestToken.java b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth1RequestToken.java new file mode 100644 index 000000000..b8b3d2be4 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth1RequestToken.java @@ -0,0 +1,86 @@ +package com.github.scribejava.core.model; + +import java.util.Objects; + +/** + * Represents an OAuth 1 Request Token http://tools.ietf.org/html/rfc5849#section-2.1 + */ +public class OAuth1RequestToken extends OAuth1Token { + + private static final long serialVersionUID = 6185104114662587991L; + + /** + * oauth_callback_confirmed: + *

+ * MUST be present and set to "true". The parameter is used to differentiate from previous versions of the protocol. + *

+ */ + private final boolean oauthCallbackConfirmed; + + public OAuth1RequestToken(String token, String tokenSecret) { + this(token, tokenSecret, null); + } + + public OAuth1RequestToken(String token, String tokenSecret, String rawResponse) { + this(token, tokenSecret, true, rawResponse); + } + + public OAuth1RequestToken(String token, String tokenSecret, boolean oauthCallbackConfirmed, String rawResponse) { + super(token, tokenSecret, rawResponse); + this.oauthCallbackConfirmed = oauthCallbackConfirmed; + } + + /** + * The temporary credentials identifier. + * + * @return oauth_token + */ + @Override + public String getToken() { + return super.getToken(); + } + + /** + * The temporary credentials shared-secret. + * + * @return oauth_token_secret + */ + @Override + public String getTokenSecret() { + return super.getTokenSecret(); + } + + public boolean isOauthCallbackConfirmed() { + return oauthCallbackConfirmed; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 83 * hash + Objects.hashCode(getToken()); + hash = 83 * hash + Objects.hashCode(getTokenSecret()); + hash = 83 * hash + (oauthCallbackConfirmed ? 1 : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final OAuth1RequestToken other = (OAuth1RequestToken) obj; + if (oauthCallbackConfirmed != other.isOauthCallbackConfirmed()) { + return false; + } + if (!Objects.equals(getToken(), other.getToken())) { + return false; + } + return Objects.equals(getTokenSecret(), other.getTokenSecret()); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth1Token.java b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth1Token.java new file mode 100644 index 000000000..3d02f49aa --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth1Token.java @@ -0,0 +1,38 @@ +package com.github.scribejava.core.model; + +import com.github.scribejava.core.utils.Preconditions; + +/** + * Represents an abstract OAuth 1 Token (either request or access token) + */ +public abstract class OAuth1Token extends Token { + + private static final long serialVersionUID = 6285873427974823019L; + + private final String token; + + private final String tokenSecret; + + public OAuth1Token(String token, String tokenSecret, String rawResponse) { + super(rawResponse); + Preconditions.checkNotNull(token, "oauth_token can't be null"); + Preconditions.checkNotNull(tokenSecret, "oauth_token_secret can't be null"); + this.token = token; + this.tokenSecret = tokenSecret; + } + + public String getToken() { + return token; + } + + public String getTokenSecret() { + return tokenSecret; + } + + /** + * @return true if the token is empty (oauth_token = "", oauth_token_secret = "") + */ + public boolean isEmpty() { + return "".equals(token) && "".equals(tokenSecret); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth2AccessToken.java b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth2AccessToken.java new file mode 100644 index 000000000..f02bc57c6 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth2AccessToken.java @@ -0,0 +1,132 @@ +package com.github.scribejava.core.model; + +import com.github.scribejava.core.utils.Preconditions; +import java.util.Objects; + +/** + * Represents an OAuth 2 Access token. + * http://tools.ietf.org/html/rfc6749#section-5.1 + * + * @see OAuth 2 Access Token Specification + */ +public class OAuth2AccessToken extends Token { + + private static final long serialVersionUID = 8901381135476613449L; + + /** + * access_token + *

+ * REQUIRED. The access token issued by the authorization server.

+ */ + private String accessToken; + + /** + * token_type + *

+ * REQUIRED. The type of the token issued as described in http://tools.ietf.org/html/rfc6749#section-7.1 Value is + * case insensitive.

+ */ + private String tokenType; + + /** + * expires_in + *

+ * RECOMMENDED. The lifetime in seconds of the access token. For example, the value "3600" denotes that the access + * token will expire in one hour from the time the response was generated. If omitted, the authorization server + * SHOULD provide the expiration time via other means or document the default value.

+ */ + private Integer expiresIn; + + /** + * refresh_token + *

+ * OPTIONAL. The refresh token, which can be used to obtain new access tokens using the same authorization grant as + * described in http://tools.ietf.org/html/rfc6749#section-6

+ */ + private String refreshToken; + + /** + * scope + *

+ * OPTIONAL, if identical to the scope requested by the client; otherwise, REQUIRED. The scope of the access token + * as described by http://tools.ietf.org/html/rfc6749#section-3.3

+ */ + private String scope; + + public OAuth2AccessToken(String accessToken) { + this(accessToken, null); + } + + public OAuth2AccessToken(String accessToken, String rawResponse) { + this(accessToken, null, null, null, null, rawResponse); + } + + public OAuth2AccessToken(String accessToken, String tokenType, Integer expiresIn, String refreshToken, String scope, + String rawResponse) { + super(rawResponse); + Preconditions.checkNotNull(accessToken, "access_token can't be null"); + this.accessToken = accessToken; + this.tokenType = tokenType; + this.expiresIn = expiresIn; + this.refreshToken = refreshToken; + this.scope = scope; + } + + public String getAccessToken() { + return accessToken; + } + + public String getTokenType() { + return tokenType; + } + + public Integer getExpiresIn() { + return expiresIn; + } + + public String getRefreshToken() { + return refreshToken; + } + + public String getScope() { + return scope; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 41 * hash + Objects.hashCode(accessToken); + hash = 41 * hash + Objects.hashCode(tokenType); + hash = 41 * hash + Objects.hashCode(expiresIn); + hash = 41 * hash + Objects.hashCode(refreshToken); + hash = 41 * hash + Objects.hashCode(scope); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final OAuth2AccessToken other = (OAuth2AccessToken) obj; + if (!Objects.equals(accessToken, other.getAccessToken())) { + return false; + } + if (!Objects.equals(tokenType, other.getTokenType())) { + return false; + } + if (!Objects.equals(refreshToken, other.getRefreshToken())) { + return false; + } + if (!Objects.equals(scope, other.getScope())) { + return false; + } + return Objects.equals(expiresIn, other.getExpiresIn()); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth2AccessTokenErrorResponse.java b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth2AccessTokenErrorResponse.java new file mode 100644 index 000000000..5c4a65a19 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth2AccessTokenErrorResponse.java @@ -0,0 +1,39 @@ +package com.github.scribejava.core.model; + +import com.github.scribejava.core.oauth2.OAuth2Error; +import java.io.IOException; + +import java.net.URI; + +/** + * Representing "5.2. Error Response" + */ +public class OAuth2AccessTokenErrorResponse extends OAuthResponseException { + + private static final long serialVersionUID = 2309424849700276816L; + + private final OAuth2Error error; + private final String errorDescription; + private final URI errorUri; + + public OAuth2AccessTokenErrorResponse(OAuth2Error error, String errorDescription, URI errorUri, + Response rawResponse) throws IOException { + super(rawResponse); + this.error = error; + this.errorDescription = errorDescription; + this.errorUri = errorUri; + } + + public OAuth2Error getError() { + return error; + } + + public String getErrorDescription() { + return errorDescription; + } + + public URI getErrorUri() { + return errorUri; + } + +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth2Authorization.java b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth2Authorization.java new file mode 100644 index 000000000..8c99f395b --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuth2Authorization.java @@ -0,0 +1,43 @@ +package com.github.scribejava.core.model; + +/** + * represents Authorization Response http://tools.ietf.org/html/rfc6749#section-4.1.2 + * + * If the resource owner grants the access request, the authorization server issues an authorization code and delivers + * it to the client by adding the following parameters to the query component of the redirection URI using the + * "application/x-www-form-urlencoded" format. + * + */ +public class OAuth2Authorization { + + /** + * REQUIRED. The authorization code generated by the authorization server. The authorization code MUST expire + * shortly after it is issued to mitigate the risk of leaks. A maximum authorization code lifetime of 10 minutes is + * RECOMMENDED. The client MUST NOT use the authorization code more than once. If an authorization code is used more + * than once, the authorization server MUST deny the request and SHOULD revoke (when possible) all tokens previously + * issued based on that authorization code. The authorization code is bound to the client identifier and redirection + * URI. + */ + private String code; + /** + * REQUIRED if the "state" parameter was present in the client authorization request. The exact value received from + * the client. + */ + private String state; + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuthAsyncRequestCallback.java b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuthAsyncRequestCallback.java new file mode 100644 index 000000000..7719314d2 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuthAsyncRequestCallback.java @@ -0,0 +1,13 @@ +package com.github.scribejava.core.model; + +public interface OAuthAsyncRequestCallback { + + /** + * Implementations of this method should close provided response in case it implements {@link java.io.Closeable} + * + * @param response response + */ + void onCompleted(T response); + + void onThrowable(Throwable t); +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuthConstants.java b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuthConstants.java new file mode 100644 index 000000000..268e5f435 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuthConstants.java @@ -0,0 +1,50 @@ +package com.github.scribejava.core.model; + +/** + * This class contains OAuth constants, used project-wide + */ +public interface OAuthConstants { + + String TIMESTAMP = "oauth_timestamp"; + String SIGN_METHOD = "oauth_signature_method"; + String SIGNATURE = "oauth_signature"; + String CONSUMER_SECRET = "oauth_consumer_secret"; + String CONSUMER_KEY = "oauth_consumer_key"; + String CALLBACK = "oauth_callback"; + String VERSION = "oauth_version"; + String NONCE = "oauth_nonce"; + String REALM = "realm"; + String PARAM_PREFIX = "oauth_"; + String TOKEN = "oauth_token"; + String TOKEN_SECRET = "oauth_token_secret"; + String VERIFIER = "oauth_verifier"; + String HEADER = "Authorization"; + String SCOPE = "scope"; + String BASIC = "Basic"; + + // OAuth 1.0 + /** + * to indicate an out-of-band configuration + * @see The OAuth 1.0 Protocol + */ + String OOB = "oob"; + + // OAuth 2.0 + String ACCESS_TOKEN = "access_token"; + String CLIENT_ID = "client_id"; + String CLIENT_SECRET = "client_secret"; + String REDIRECT_URI = "redirect_uri"; + String CODE = "code"; + String REFRESH_TOKEN = "refresh_token"; + String GRANT_TYPE = "grant_type"; + String AUTHORIZATION_CODE = "authorization_code"; + String CLIENT_CREDENTIALS = "client_credentials"; + String STATE = "state"; + String USERNAME = "username"; + String PASSWORD = "password"; + String RESPONSE_TYPE = "response_type"; + String RESPONSE_TYPE_CODE = "code"; + + //not OAuth specific + String USER_AGENT_HEADER_NAME = "User-Agent"; +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuthRequest.java b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuthRequest.java new file mode 100644 index 000000000..ccf26157c --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuthRequest.java @@ -0,0 +1,330 @@ +package com.github.scribejava.core.model; + +import com.github.scribejava.core.exceptions.OAuthException; +import com.github.scribejava.core.httpclient.multipart.BodyPartPayload; +import com.github.scribejava.core.httpclient.multipart.MultipartPayload; +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +/** + * The representation of an OAuth HttpRequest. + */ +public class OAuthRequest { + + private static final String OAUTH_PREFIX = "oauth_"; + + private final String url; + private final Verb verb; + private final ParameterList querystringParams = new ParameterList(); + private final ParameterList bodyParams = new ParameterList(); + private final Map headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + private String charset; + + private String stringPayload; + private byte[] byteArrayPayload; + private File filePayload; + private MultipartPayload multipartPayload; + + private final Map oauthParameters = new HashMap<>(); + + private String realm; + + /** + * Default constructor. + * + * @param verb Http verb/method + * @param url resource URL + */ + public OAuthRequest(Verb verb, String url) { + this.verb = verb; + this.url = url; + } + + /** + * Adds an OAuth parameter. + * + * @param key name of the parameter + * @param value value of the parameter + * @throws IllegalArgumentException if the parameter is not an OAuth parameter + */ + public void addOAuthParameter(String key, String value) { + oauthParameters.put(checkKey(key), value); + } + + private String checkKey(String key) { + if (key.startsWith(OAUTH_PREFIX) || key.equals(OAuthConstants.SCOPE) || key.equals(OAuthConstants.REALM)) { + return key; + } else { + throw new IllegalArgumentException( + String.format("OAuth parameters must either be '%s', '%s' or start with '%s'", OAuthConstants.SCOPE, + OAuthConstants.REALM, OAUTH_PREFIX)); + } + } + + public Map getOauthParameters() { + return oauthParameters; + } + + public void setRealm(String realm) { + this.realm = realm; + } + + public String getRealm() { + return realm; + } + + /** + * Returns the complete url (host + resource + encoded querystring parameters). + * + * @return the complete url. + */ + public String getCompleteUrl() { + return querystringParams.appendTo(url); + } + + /** + * Add an HTTP Header to the Request + * + * @param key the header name + * @param value the header value + */ + public void addHeader(String key, String value) { + headers.put(key, value); + } + + /** + * Add a body Parameter (for POST/ PUT Requests) + * + * @param key the parameter name + * @param value the parameter value + */ + public void addBodyParameter(String key, String value) { + bodyParams.add(key, value); + } + + /** + * Add a QueryString parameter + * + * @param key the parameter name + * @param value the parameter value + */ + public void addQuerystringParameter(String key, String value) { + querystringParams.add(key, value); + } + + public void addParameter(String key, String value) { + if (verb.isPermitBody()) { + bodyParams.add(key, value); + } else { + querystringParams.add(key, value); + } + } + + public MultipartPayload getMultipartPayload() { + return multipartPayload; + } + + public void setMultipartPayload(MultipartPayload multipartPayload) { + this.multipartPayload = multipartPayload; + } + + public void initMultipartPayload() { + this.multipartPayload = new MultipartPayload(); + } + + public void initMultipartPayload(String boundary) { + this.multipartPayload = new MultipartPayload(boundary); + } + + public void initMultipartPayload(String subtype, String boundary) { + this.multipartPayload = new MultipartPayload(subtype, boundary); + } + + public void initMultipartPayload(Map headers) { + this.multipartPayload = new MultipartPayload(headers); + } + + public void initMultipartPayload(String boundary, Map headers) { + this.multipartPayload = new MultipartPayload(boundary, headers); + } + + public void initMultipartPayload(String subtype, String boundary, Map headers) { + this.multipartPayload = new MultipartPayload(subtype, boundary, headers); + } + + public void setBodyPartPayloadInMultipartPayload(BodyPartPayload bodyPartPayload) { + initMultipartPayload(); + addBodyPartPayloadInMultipartPayload(bodyPartPayload); + } + + public void addBodyPartPayloadInMultipartPayload(BodyPartPayload bodyPartPayload) { + multipartPayload.addBodyPart(bodyPartPayload); + } + + /** + * Set body payload. This method is used when the HTTP body is not a form-url-encoded string, but another thing. + * Like for example XML. Note: The contents are not part of the OAuth signature + * + * @param payload the body of the request + */ + public void setPayload(String payload) { + resetPayload(); + stringPayload = payload; + } + + /** + * Overloaded version for byte arrays + * + * @param payload byte[] + */ + public void setPayload(byte[] payload) { + resetPayload(); + byteArrayPayload = payload.clone(); + } + + /** + * Overloaded version for File + * + * @param payload File + */ + public void setPayload(File payload) { + resetPayload(); + filePayload = payload; + } + + private void resetPayload() { + stringPayload = null; + byteArrayPayload = null; + filePayload = null; + multipartPayload = null; + } + + /** + * Get a {@link ParameterList} with the query string parameters. + * + * @return a {@link ParameterList} containing the query string parameters. + * @throws OAuthException if the request URL is not valid. + */ + public ParameterList getQueryStringParams() { + try { + final ParameterList result = new ParameterList(); + final String queryString = new URL(url).getQuery(); + result.addQuerystring(queryString); + result.addAll(querystringParams); + return result; + } catch (MalformedURLException mue) { + throw new OAuthException("Malformed URL", mue); + } + } + + /** + * Obtains a {@link ParameterList} of the body parameters. + * + * @return a {@link ParameterList}containing the body parameters. + */ + public ParameterList getBodyParams() { + return bodyParams; + } + + /** + * Obtains the URL of the HTTP Request. + * + * @return the original URL of the HTTP Request + */ + public String getUrl() { + return url; + } + + /** + * Returns the URL without the port and the query string part. + * + * @return the OAuth-sanitized URL + */ + public String getSanitizedUrl() { + if (url.startsWith("http://") && (url.endsWith(":80") || url.contains(":80/"))) { + return url.replaceAll("\\?.*", "").replaceAll(":80", ""); + } else if (url.startsWith("https://") && (url.endsWith(":443") || url.contains(":443/"))) { + return url.replaceAll("\\?.*", "").replaceAll(":443", ""); + } else { + return url.replaceAll("\\?.*", ""); + } + } + + /** + * Returns the body of the request (set in {@link #setPayload(java.lang.String)}) + * + * @return form encoded string + */ + public String getStringPayload() { + return stringPayload; + } + + /** + * @return the body of the request (set in {@link #setPayload(byte[])} or in + * {@link #addBodyParameter(java.lang.String, java.lang.String)} ) + */ + public byte[] getByteArrayPayload() { + if (byteArrayPayload != null) { + return byteArrayPayload; + } + final String body = bodyParams.asFormUrlEncodedString(); + try { + return body.getBytes(getCharset()); + } catch (UnsupportedEncodingException uee) { + throw new OAuthException("Unsupported Charset: " + getCharset(), uee); + } + } + + public File getFilePayload() { + return filePayload; + } + + @Override + public String toString() { + return String.format("@Request(%s %s)", getVerb(), getUrl()); + } + + public Verb getVerb() { + return verb; + } + + public Map getHeaders() { + return headers; + } + + public String getCharset() { + return charset == null ? Charset.defaultCharset().name() : charset; + } + + /** + * Set the charset of the body of the request + * + * @param charsetName name of the charset of the request + */ + public void setCharset(String charsetName) { + charset = charsetName; + } + + public interface ResponseConverter { + + /** + * Implementations of this method should close provided Response in case response is not included in the return + * Object of type <T> Then responsibility to close response is in on the + * {@link com.github.scribejava.core.model.OAuthAsyncRequestCallback#onCompleted(java.lang.Object) } + * + * @param response response + * @return T + * @throws IOException IOException + */ + T convert(Response response) throws IOException; + } + +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuthResponseException.java b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuthResponseException.java new file mode 100644 index 000000000..5b6da25cf --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/model/OAuthResponseException.java @@ -0,0 +1,44 @@ +package com.github.scribejava.core.model; + +import com.github.scribejava.core.exceptions.OAuthException; +import java.io.IOException; +import java.util.Objects; + +public class OAuthResponseException extends OAuthException { + + private static final long serialVersionUID = 1309424849700276816L; + + private final transient Response response; + + public OAuthResponseException(Response rawResponse) throws IOException { + super(rawResponse.getBody()); + this.response = rawResponse; + } + + public Response getResponse() { + return response; + } + + @Override + public int hashCode() { + int hash = 5; + hash = 29 * hash + Objects.hashCode(response); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final OAuthResponseException other = (OAuthResponseException) obj; + return Objects.equals(this.response, other.response); + } + +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/model/Parameter.java b/scribejava-core/src/main/java/com/github/scribejava/core/model/Parameter.java new file mode 100644 index 000000000..9397cb773 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/model/Parameter.java @@ -0,0 +1,54 @@ +package com.github.scribejava.core.model; + +import com.github.scribejava.core.utils.OAuthEncoder; + +public class Parameter implements Comparable { + + private final String key; + private final String value; + + public Parameter(String key, String value) { + this.key = key; + this.value = value; + } + + public String asUrlEncodedPair() { + return OAuthEncoder.encode(key).concat("=").concat(OAuthEncoder.encode(value)); + } + + @Override + public boolean equals(Object other) { + if (other == null) { + return false; + } + if (other == this) { + return true; + } + if (!(other instanceof Parameter)) { + return false; + } + + final Parameter otherParam = (Parameter) other; + return otherParam.getKey().equals(key) && otherParam.getValue().equals(value); + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + + @Override + public int hashCode() { + return key.hashCode() + value.hashCode(); + } + + @Override + public int compareTo(Parameter parameter) { + final int keyDiff = key.compareTo(parameter.getKey()); + + return keyDiff == 0 ? value.compareTo(parameter.getValue()) : keyDiff; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/model/ParameterList.java b/scribejava-core/src/main/java/com/github/scribejava/core/model/ParameterList.java new file mode 100644 index 000000000..39d806652 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/model/ParameterList.java @@ -0,0 +1,100 @@ +package com.github.scribejava.core.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import com.github.scribejava.core.utils.OAuthEncoder; +import com.github.scribejava.core.utils.Preconditions; + +public class ParameterList { + + private static final char QUERY_STRING_SEPARATOR = '?'; + private static final String PARAM_SEPARATOR = "&"; + private static final String PAIR_SEPARATOR = "="; + private static final String EMPTY_STRING = ""; + + private final List params; + + public ParameterList() { + params = new ArrayList<>(); + } + + ParameterList(List params) { + this.params = new ArrayList<>(params); + } + + public ParameterList(Map map) { + this(); + if (map != null && !map.isEmpty()) { + for (Map.Entry entry : map.entrySet()) { + params.add(new Parameter(entry.getKey(), entry.getValue())); + } + } + } + + public void add(String key, String value) { + params.add(new Parameter(key, value)); + } + + public String appendTo(String url) { + Preconditions.checkNotNull(url, "Cannot append to null URL"); + final String queryString = asFormUrlEncodedString(); + if (queryString.equals(EMPTY_STRING)) { + return url; + } else { + return url + + (url.indexOf(QUERY_STRING_SEPARATOR) == -1 ? QUERY_STRING_SEPARATOR : PARAM_SEPARATOR) + + queryString; + } + } + + public String asOauthBaseString() { + return OAuthEncoder.encode(asFormUrlEncodedString()); + } + + public String asFormUrlEncodedString() { + if (params.isEmpty()) { + return EMPTY_STRING; + } + + final StringBuilder builder = new StringBuilder(); + for (Parameter p : params) { + builder.append(PARAM_SEPARATOR).append(p.asUrlEncodedPair()); + } + return builder.substring(1); + } + + public void addAll(ParameterList other) { + params.addAll(other.getParams()); + } + + public void addQuerystring(String queryString) { + if (queryString != null && !queryString.isEmpty()) { + for (String param : queryString.split(PARAM_SEPARATOR)) { + final String[] pair = param.split(PAIR_SEPARATOR); + final String key = OAuthEncoder.decode(pair[0]); + final String value = pair.length > 1 ? OAuthEncoder.decode(pair[1]) : EMPTY_STRING; + params.add(new Parameter(key, value)); + } + } + } + + public boolean contains(Parameter param) { + return params.contains(param); + } + + public int size() { + return params.size(); + } + + public List getParams() { + return params; + } + + public ParameterList sort() { + final ParameterList sorted = new ParameterList(params); + Collections.sort(sorted.getParams()); + return sorted; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/model/Response.java b/scribejava-core/src/main/java/com/github/scribejava/core/model/Response.java new file mode 100644 index 000000000..553c6cda5 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/model/Response.java @@ -0,0 +1,154 @@ +package com.github.scribejava.core.model; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import com.github.scribejava.core.utils.StreamUtils; +import java.io.Closeable; + +/** + * An HTTP response. + * + *

+ * This response may contain a non-null body stream of the HttpUrlConnection. If so, this body must be closed to avoid + * leaking resources. Use either {@link #getBody()} or {@link #close()} to close the body. + */ +public class Response implements Closeable { + + private final int code; + private final String message; + private final Map headers; + private String body; + private InputStream stream; + private Closeable[] closeables; + private boolean closed; + + private Response(int code, String message, Map headers) { + this.code = code; + this.message = message; + this.headers = headers; + } + + public Response(int code, String message, Map headers, InputStream stream, + Closeable... closeables) { + this(code, message, headers); + this.stream = stream; + this.closeables = closeables; + } + + public Response(int code, String message, Map headers, String body) { + this(code, message, headers); + this.body = body; + } + + private String parseBodyContents() throws IOException { + if (stream == null) { + return null; + } + if ("gzip".equals(getHeader("Content-Encoding"))) { + body = StreamUtils.getGzipStreamContents(stream); + } else { + body = StreamUtils.getStreamContents(stream); + } + return body; + } + + public boolean isSuccessful() { + return code >= 200 && code < 400; + } + + /** + * Returns the response body as a string, closing the stream that backs it. Idempotent. + * + * @return body as string + * @throws IOException IO Exception + */ + public String getBody() throws IOException { + return body == null ? parseBodyContents() : body; + } + + /** + * Obtains the meaningful stream of the HttpUrlConnection, either inputStream or errorInputStream, depending on the + * status code + * + * @return input stream / error stream + */ + public InputStream getStream() { + return stream; + } + + /** + * Obtains the HTTP status code + * + * @return the status code + */ + public int getCode() { + return code; + } + + /** + * Obtains the HTTP status message. Returns null if the message can not be discerned from the response + * (not valid HTTP) + * + * @return the status message + */ + public String getMessage() { + return message; + } + + /** + * Obtains a {@link Map} containing the HTTP Response Headers + * + * @return headers + */ + public Map getHeaders() { + return headers; + } + + /** + * Obtains a single HTTP Header value, or null if undefined + * + * @param name the header name. + * + * @return header value or null. + */ + public String getHeader(String name) { + return headers.get(name); + } + + @Override + public String toString() { + return "Response{" + + "code=" + code + + ", message='" + message + '\'' + + ", body='" + body + '\'' + + ", headers=" + headers + + '}'; + } + + @Override + public void close() throws IOException { + if (closed) { + return; + } + IOException ioException = null; + if (closeables != null) { + for (Closeable closeable : closeables) { + if (closeable == null) { + continue; + } + try { + closeable.close(); + } catch (IOException ioE) { + if (ioException != null) { + ioException = ioE; + } + } + } + } + if (ioException != null) { + throw ioException; + } + closed = true; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/model/Token.java b/scribejava-core/src/main/java/com/github/scribejava/core/model/Token.java new file mode 100644 index 000000000..ede417c03 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/model/Token.java @@ -0,0 +1,39 @@ +package com.github.scribejava.core.model; + +import java.io.Serializable; + +/** + * Represents an abstract OAuth (1 and 2) token (either request or access token) + */ +public abstract class Token implements Serializable { + + private static final long serialVersionUID = -8409640649946468092L; + + private final String rawResponse; + + protected Token(String rawResponse) { + this.rawResponse = rawResponse; + } + + public String getRawResponse() { + if (rawResponse == null) { + throw new IllegalStateException( + "This token object was not constructed by ScribeJava and does not have a rawResponse"); + } + return rawResponse; + } + + public String getParameter(String parameter) { + String value = null; + for (String str : rawResponse.split("&")) { + if (str.startsWith(parameter + '=')) { + final String[] part = str.split("="); + if (part.length > 1) { + value = part[1].trim(); + } + break; + } + } + return value; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/model/Verb.java b/scribejava-core/src/main/java/com/github/scribejava/core/model/Verb.java new file mode 100644 index 000000000..8df5fd3f3 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/model/Verb.java @@ -0,0 +1,32 @@ +package com.github.scribejava.core.model; + +/** + * An enumeration containing the most common HTTP Verbs. + */ +public enum Verb { + + GET(false), POST(true), PUT(true), DELETE(false, true), HEAD(false), OPTIONS(false), TRACE(false), PATCH(true); + + private final boolean requiresBody; + private final boolean permitBody; + + Verb(boolean requiresBody) { + this(requiresBody, requiresBody); + } + + Verb(boolean requiresBody, boolean permitBody) { + if (requiresBody && !permitBody) { + throw new IllegalArgumentException(); + } + this.requiresBody = requiresBody; + this.permitBody = permitBody; + } + + public boolean isRequiresBody() { + return requiresBody; + } + + public boolean isPermitBody() { + return permitBody; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/oauth/AccessTokenRequestParams.java b/scribejava-core/src/main/java/com/github/scribejava/core/oauth/AccessTokenRequestParams.java new file mode 100644 index 000000000..d45377a56 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/oauth/AccessTokenRequestParams.java @@ -0,0 +1,79 @@ +package com.github.scribejava.core.oauth; + +import com.github.scribejava.core.builder.ScopeBuilder; +import java.util.HashMap; +import java.util.Map; + +/** + * not thread safe + */ +public class AccessTokenRequestParams { + + private final String code; + private String pkceCodeVerifier; + private String scope; + private Map extraParameters; + + public AccessTokenRequestParams(String code) { + this.code = code; + } + + public static AccessTokenRequestParams create(String code) { + return new AccessTokenRequestParams(code); + } + + public AccessTokenRequestParams pkceCodeVerifier(String pkceCodeVerifier) { + this.pkceCodeVerifier = pkceCodeVerifier; + return this; + } + + public AccessTokenRequestParams scope(String scope) { + this.scope = scope; + return this; + } + + public AccessTokenRequestParams scope(ScopeBuilder scope) { + this.scope = scope.build(); + return this; + } + + public AccessTokenRequestParams addExtraParameters(Map extraParameters) { + if (extraParameters == null || extraParameters.isEmpty()) { + return this; + } + if (this.extraParameters == null) { + extraParameters = new HashMap<>(); + } + this.extraParameters.putAll(extraParameters); + return this; + } + + public AccessTokenRequestParams addExtraParameter(String name, String value) { + if (this.extraParameters == null) { + extraParameters = new HashMap<>(); + } + this.extraParameters.put(name, value); + return this; + } + + public AccessTokenRequestParams setExtraParameters(Map extraParameters) { + this.extraParameters = extraParameters; + return this; + } + + public Map getExtraParameters() { + return extraParameters; + } + + public String getCode() { + return code; + } + + public String getPkceCodeVerifier() { + return pkceCodeVerifier; + } + + public String getScope() { + return scope; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/oauth/AuthorizationUrlBuilder.java b/scribejava-core/src/main/java/com/github/scribejava/core/oauth/AuthorizationUrlBuilder.java new file mode 100644 index 000000000..fd02f60dd --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/oauth/AuthorizationUrlBuilder.java @@ -0,0 +1,61 @@ +package com.github.scribejava.core.oauth; + +import com.github.scribejava.core.pkce.PKCE; +import com.github.scribejava.core.pkce.PKCEService; +import java.util.HashMap; +import java.util.Map; + +public class AuthorizationUrlBuilder { + + private final OAuth20Service oauth20Service; + + private String state; + private Map additionalParams; + private PKCE pkce; + private String scope; + + public AuthorizationUrlBuilder(OAuth20Service oauth20Service) { + this.oauth20Service = oauth20Service; + } + + public AuthorizationUrlBuilder state(String state) { + this.state = state; + return this; + } + + public AuthorizationUrlBuilder additionalParams(Map additionalParams) { + this.additionalParams = additionalParams; + return this; + } + + public AuthorizationUrlBuilder pkce(PKCE pkce) { + this.pkce = pkce; + return this; + } + + public AuthorizationUrlBuilder initPKCE() { + this.pkce = PKCEService.defaultInstance().generatePKCE(); + return this; + } + + public AuthorizationUrlBuilder scope(String scope) { + this.scope = scope; + return this; + } + + public PKCE getPkce() { + return pkce; + } + + public String build() { + final Map params; + if (pkce == null) { + params = additionalParams; + } else { + params = additionalParams == null ? new HashMap() : new HashMap<>(additionalParams); + params.putAll(pkce.getAuthorizationUrlParams()); + } + return oauth20Service.getApi().getAuthorizationUrl(oauth20Service.getResponseType(), oauth20Service.getApiKey(), + oauth20Service.getCallback(), scope == null ? oauth20Service.getDefaultScope() : scope, state, params); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuth10aService.java b/scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuth10aService.java new file mode 100644 index 000000000..f48308b2e --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuth10aService.java @@ -0,0 +1,220 @@ +package com.github.scribejava.core.oauth; + +import java.io.IOException; +import java.util.concurrent.Future; +import com.github.scribejava.core.builder.api.DefaultApi10a; +import com.github.scribejava.core.builder.api.OAuth1SignatureType; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.OAuth1AccessToken; +import com.github.scribejava.core.model.OAuth1RequestToken; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import java.io.OutputStream; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +/** + * OAuth 1.0a implementation of {@link OAuthService} + */ +public class OAuth10aService extends OAuthService { + + private static final String VERSION = "1.0"; + private final DefaultApi10a api; + private final String scope; + + public OAuth10aService(DefaultApi10a api, String apiKey, String apiSecret, String callback, String scope, + OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, HttpClient httpClient) { + super(apiKey, apiSecret, callback, debugStream, userAgent, httpClientConfig, httpClient); + this.api = api; + this.scope = scope; + } + + public OAuth1RequestToken getRequestToken() throws IOException, InterruptedException, ExecutionException { + if (isDebug()) { + log("obtaining request token from %s", api.getRequestTokenEndpoint()); + } + final OAuthRequest request = prepareRequestTokenRequest(); + + log("sending request..."); + try ( Response response = execute(request)) { + if (isDebug()) { + final String body = response.getBody(); + log("response status code: %s", response.getCode()); + log("response body: %s", body); + } + return api.getRequestTokenExtractor().extract(response); + } + } + + public Future getRequestTokenAsync() { + return getRequestTokenAsync(null); + } + + public Future getRequestTokenAsync(OAuthAsyncRequestCallback callback) { + if (isDebug()) { + log("async obtaining request token from %s", api.getRequestTokenEndpoint()); + } + final OAuthRequest request = prepareRequestTokenRequest(); + return execute(request, callback, new OAuthRequest.ResponseConverter() { + @Override + public OAuth1RequestToken convert(Response response) throws IOException { + final OAuth1RequestToken token = getApi().getRequestTokenExtractor().extract(response); + response.close(); + return token; + } + }); + } + + protected OAuthRequest prepareRequestTokenRequest() { + final OAuthRequest request = new OAuthRequest(api.getRequestTokenVerb(), api.getRequestTokenEndpoint()); + String callback = getCallback(); + if (callback == null) { + callback = OAuthConstants.OOB; + } + if (isDebug()) { + log("setting oauth_callback to %s", callback); + } + request.addOAuthParameter(OAuthConstants.CALLBACK, callback); + addOAuthParams(request, ""); + appendSignature(request); + return request; + } + + protected void addOAuthParams(OAuthRequest request, String tokenSecret) { + request.addOAuthParameter(OAuthConstants.TIMESTAMP, api.getTimestampService().getTimestampInSeconds()); + request.addOAuthParameter(OAuthConstants.NONCE, api.getTimestampService().getNonce()); + request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, getApiKey()); + request.addOAuthParameter(OAuthConstants.SIGN_METHOD, api.getSignatureService().getSignatureMethod()); + request.addOAuthParameter(OAuthConstants.VERSION, getVersion()); + if (scope != null) { + request.addOAuthParameter(OAuthConstants.SCOPE, scope); + } + request.addOAuthParameter(OAuthConstants.SIGNATURE, getSignature(request, tokenSecret)); + + if (isDebug()) { + log("appended additional OAuth parameters: %s", request.getOauthParameters()); + } + } + + public OAuth1AccessToken getAccessToken(OAuth1RequestToken requestToken, String oauthVerifier) + throws IOException, InterruptedException, ExecutionException { + if (isDebug()) { + log("obtaining access token from %s", api.getAccessTokenEndpoint()); + } + final OAuthRequest request = prepareAccessTokenRequest(requestToken, oauthVerifier); + try ( Response response = execute(request)) { + return api.getAccessTokenExtractor().extract(response); + } + } + + public Future getAccessTokenAsync(OAuth1RequestToken requestToken, String oauthVerifier) { + return getAccessTokenAsync(requestToken, oauthVerifier, null); + } + + /** + * Start the request to retrieve the access token. The optionally provided callback will be called with the Token + * when it is available. + * + * @param requestToken request token (obtained previously or null) + * @param oauthVerifier oauth_verifier + * @param callback optional callback + * @return Future + */ + public Future getAccessTokenAsync(OAuth1RequestToken requestToken, String oauthVerifier, + OAuthAsyncRequestCallback callback) { + if (isDebug()) { + log("async obtaining access token from %s", api.getAccessTokenEndpoint()); + } + final OAuthRequest request = prepareAccessTokenRequest(requestToken, oauthVerifier); + return execute(request, callback, new OAuthRequest.ResponseConverter() { + @Override + public OAuth1AccessToken convert(Response response) throws IOException { + final OAuth1AccessToken token = getApi().getAccessTokenExtractor().extract(response); + response.close(); + return token; + } + }); + } + + protected OAuthRequest prepareAccessTokenRequest(OAuth1RequestToken requestToken, String oauthVerifier) { + final OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint()); + request.addOAuthParameter(OAuthConstants.TOKEN, requestToken.getToken()); + request.addOAuthParameter(OAuthConstants.VERIFIER, oauthVerifier); + if (isDebug()) { + log("setting token to: %s and verifier to: %s", requestToken, oauthVerifier); + } + addOAuthParams(request, requestToken.getTokenSecret()); + appendSignature(request); + return request; + } + + public void signRequest(OAuth1AccessToken token, OAuthRequest request) { + if (isDebug()) { + log("signing request: %s", request.getCompleteUrl()); + } + + if (!token.isEmpty() || api.isEmptyOAuthTokenParamIsRequired()) { + request.addOAuthParameter(OAuthConstants.TOKEN, token.getToken()); + } + if (isDebug()) { + log("setting token to: %s", token); + } + addOAuthParams(request, token.getTokenSecret()); + appendSignature(request); + } + + @Override + public String getVersion() { + return VERSION; + } + + /** + * Returns the URL where you should redirect your users to authenticate your application. + * + * @param requestToken the request token you need to authorize + * @return the URL where you should redirect your users + */ + public String getAuthorizationUrl(OAuth1RequestToken requestToken) { + return api.getAuthorizationUrl(requestToken); + } + + private String getSignature(OAuthRequest request, String tokenSecret) { + log("generating signature..."); + final String baseString = api.getBaseStringExtractor().extract(request); + final String signature = api.getSignatureService().getSignature(baseString, getApiSecret(), tokenSecret); + + if (isDebug()) { + log("base string is: %s", baseString); + log("signature is: %s", signature); + } + return signature; + } + + protected void appendSignature(OAuthRequest request) { + final OAuth1SignatureType signatureType = api.getSignatureType(); + switch (signatureType) { + case HEADER: + log("using Http Header signature"); + + final String oauthHeader = api.getHeaderExtractor().extract(request); + request.addHeader(OAuthConstants.HEADER, oauthHeader); + break; + case QUERY_STRING: + log("using Querystring signature"); + + for (Map.Entry oauthParameter : request.getOauthParameters().entrySet()) { + request.addQuerystringParameter(oauthParameter.getKey(), oauthParameter.getValue()); + } + break; + default: + throw new IllegalStateException("Unknown new Signature Type '" + signatureType + "'."); + } + } + + public DefaultApi10a getApi() { + return api; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuth20Service.java b/scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuth20Service.java new file mode 100644 index 000000000..82052e351 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuth20Service.java @@ -0,0 +1,676 @@ +package com.github.scribejava.core.oauth; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.DeviceAuthorization; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuth2AccessTokenErrorResponse; +import com.github.scribejava.core.model.OAuth2Authorization; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth2.OAuth2Error; +import com.github.scribejava.core.pkce.PKCE; +import com.github.scribejava.core.revoke.TokenTypeHint; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +public class OAuth20Service extends OAuthService { + + private static final String VERSION = "2.0"; + private final DefaultApi20 api; + private final String responseType; + private final String defaultScope; + + public OAuth20Service(DefaultApi20 api, String apiKey, String apiSecret, String callback, String defaultScope, + String responseType, OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, + HttpClient httpClient) { + super(apiKey, apiSecret, callback, debugStream, userAgent, httpClientConfig, httpClient); + this.responseType = responseType; + this.api = api; + this.defaultScope = defaultScope; + } + + // ===== common OAuth methods ===== + /** + * {@inheritDoc} + */ + @Override + public String getVersion() { + return VERSION; + } + + public void signRequest(String accessToken, OAuthRequest request) { + api.getBearerSignature().signRequest(accessToken, request); + } + + public void signRequest(OAuth2AccessToken accessToken, OAuthRequest request) { + signRequest(accessToken == null ? null : accessToken.getAccessToken(), request); + } + + /** + * Returns the URL where you should redirect your users to authenticate your application. + * + * @return the URL where you should redirect your users + */ + public String getAuthorizationUrl() { + return createAuthorizationUrlBuilder().build(); + } + + public String getAuthorizationUrl(String state) { + return createAuthorizationUrlBuilder() + .state(state) + .build(); + } + + /** + * Returns the URL where you should redirect your users to authenticate your application. + * + * @param additionalParams any additional GET params to add to the URL + * @return the URL where you should redirect your users + */ + public String getAuthorizationUrl(Map additionalParams) { + return createAuthorizationUrlBuilder() + .additionalParams(additionalParams) + .build(); + } + + public String getAuthorizationUrl(PKCE pkce) { + return createAuthorizationUrlBuilder() + .pkce(pkce) + .build(); + } + + public AuthorizationUrlBuilder createAuthorizationUrlBuilder() { + return new AuthorizationUrlBuilder(this); + } + + public DefaultApi20 getApi() { + return api; + } + + public OAuth2Authorization extractAuthorization(String redirectLocation) { + final OAuth2Authorization authorization = new OAuth2Authorization(); + int end = redirectLocation.indexOf('#'); + if (end == -1) { + end = redirectLocation.length(); + } + for (String param : redirectLocation.substring(redirectLocation.indexOf('?') + 1, end).split("&")) { + final String[] keyValue = param.split("="); + if (keyValue.length == 2) { + try { + switch (keyValue[0]) { + case "code": + authorization.setCode(URLDecoder.decode(keyValue[1], "UTF-8")); + break; + case "state": + authorization.setState(URLDecoder.decode(keyValue[1], "UTF-8")); + break; + default: //just ignore any other param; + } + } catch (UnsupportedEncodingException ueE) { + throw new IllegalStateException("jvm without UTF-8, really?", ueE); + } + } + } + return authorization; + } + + public String getResponseType() { + return responseType; + } + + public String getDefaultScope() { + return defaultScope; + } + + protected void logRequestWithParams(String requestDescription, OAuthRequest request) { + if (isDebug()) { + log("created " + requestDescription + " request with body params [%s], query string params [%s]", + request.getBodyParams().asFormUrlEncodedString(), + request.getQueryStringParams().asFormUrlEncodedString()); + } + } + + // ===== common AccessToken request methods ===== + //protected to facilitate mocking + protected OAuth2AccessToken sendAccessTokenRequestSync(OAuthRequest request) + throws IOException, InterruptedException, ExecutionException { + if (isDebug()) { + log("send request for access token synchronously to %s", request.getCompleteUrl()); + } + try (Response response = execute(request)) { + if (isDebug()) { + log("response status code: %s", response.getCode()); + log("response body: %s", response.getBody()); + } + + return api.getAccessTokenExtractor().extract(response); + } + } + + //protected to facilitate mocking + protected Future sendAccessTokenRequestAsync(OAuthRequest request) { + return sendAccessTokenRequestAsync(request, null); + } + + //protected to facilitate mocking + protected Future sendAccessTokenRequestAsync(OAuthRequest request, + OAuthAsyncRequestCallback callback) { + if (isDebug()) { + log("send request for access token asynchronously to %s", request.getCompleteUrl()); + } + + return execute(request, callback, new OAuthRequest.ResponseConverter() { + @Override + public OAuth2AccessToken convert(Response response) throws IOException { + log("received response for access token"); + if (isDebug()) { + log("response status code: %s", response.getCode()); + log("response body: %s", response.getBody()); + } + final OAuth2AccessToken token = api.getAccessTokenExtractor().extract(response); + response.close(); + return token; + } + }); + } + + // ===== get AccessToken authorisation code flow methods ===== + protected OAuthRequest createAccessTokenRequest(AccessTokenRequestParams params) { + final OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint()); + + api.getClientAuthentication().addClientAuthentication(request, getApiKey(), getApiSecret()); + + request.addParameter(OAuthConstants.CODE, params.getCode()); + final String callback = getCallback(); + if (callback != null) { + request.addParameter(OAuthConstants.REDIRECT_URI, callback); + } + final String scope = params.getScope(); + if (scope != null) { + request.addParameter(OAuthConstants.SCOPE, scope); + } else if (defaultScope != null) { + request.addParameter(OAuthConstants.SCOPE, defaultScope); + } + request.addParameter(OAuthConstants.GRANT_TYPE, OAuthConstants.AUTHORIZATION_CODE); + + final String pkceCodeVerifier = params.getPkceCodeVerifier(); + if (pkceCodeVerifier != null) { + request.addParameter(PKCE.PKCE_CODE_VERIFIER_PARAM, pkceCodeVerifier); + } + + final Map extraParameters = params.getExtraParameters(); + if (extraParameters != null && !extraParameters.isEmpty()) { + for (Map.Entry extraParameter : extraParameters.entrySet()) { + request.addParameter(extraParameter.getKey(), extraParameter.getValue()); + } + } + + logRequestWithParams("access token", request); + return request; + } + + public Future getAccessTokenAsync(String code) { + return getAccessToken(AccessTokenRequestParams.create(code), null); + } + + public Future getAccessTokenAsync(AccessTokenRequestParams params) { + return getAccessToken(params, null); + } + + public OAuth2AccessToken getAccessToken(String code) throws IOException, InterruptedException, ExecutionException { + return getAccessToken(AccessTokenRequestParams.create(code)); + } + + public OAuth2AccessToken getAccessToken(AccessTokenRequestParams params) + throws IOException, InterruptedException, ExecutionException { + return sendAccessTokenRequestSync(createAccessTokenRequest(params)); + } + + /** + * Start the request to retrieve the access token. The optionally provided callback will be called with the Token + * when it is available. + * + * @param params params + * @param callback optional callback + * @return Future + */ + public Future getAccessToken(AccessTokenRequestParams params, + OAuthAsyncRequestCallback callback) { + return sendAccessTokenRequestAsync(createAccessTokenRequest(params), callback); + } + + public Future getAccessToken(String code, + OAuthAsyncRequestCallback callback) { + return getAccessToken(AccessTokenRequestParams.create(code), callback); + } + + // ===== refresh AccessToken methods ===== + protected OAuthRequest createRefreshTokenRequest(String refreshToken, String scope) { + if (refreshToken == null || refreshToken.isEmpty()) { + throw new IllegalArgumentException("The refreshToken cannot be null or empty"); + } + final OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getRefreshTokenEndpoint()); + + api.getClientAuthentication().addClientAuthentication(request, getApiKey(), getApiSecret()); + + if (scope != null) { + request.addParameter(OAuthConstants.SCOPE, scope); + } else if (defaultScope != null) { + request.addParameter(OAuthConstants.SCOPE, defaultScope); + } + + request.addParameter(OAuthConstants.REFRESH_TOKEN, refreshToken); + request.addParameter(OAuthConstants.GRANT_TYPE, OAuthConstants.REFRESH_TOKEN); + + logRequestWithParams("refresh token", request); + + return request; + } + + public Future refreshAccessTokenAsync(String refreshToken) { + return refreshAccessToken(refreshToken, (OAuthAsyncRequestCallback) null); + } + + public Future refreshAccessTokenAsync(String refreshToken, String scope) { + return refreshAccessToken(refreshToken, scope, null); + } + + public OAuth2AccessToken refreshAccessToken(String refreshToken) + throws IOException, InterruptedException, ExecutionException { + return refreshAccessToken(refreshToken, (String) null); + } + + public OAuth2AccessToken refreshAccessToken(String refreshToken, String scope) + throws IOException, InterruptedException, ExecutionException { + final OAuthRequest request = createRefreshTokenRequest(refreshToken, scope); + + return sendAccessTokenRequestSync(request); + } + + public Future refreshAccessToken(String refreshToken, + OAuthAsyncRequestCallback callback) { + final OAuthRequest request = createRefreshTokenRequest(refreshToken, null); + + return sendAccessTokenRequestAsync(request, callback); + } + + public Future refreshAccessToken(String refreshToken, String scope, + OAuthAsyncRequestCallback callback) { + final OAuthRequest request = createRefreshTokenRequest(refreshToken, scope); + + return sendAccessTokenRequestAsync(request, callback); + } + + // ===== get AccessToken password grant flow methods ===== + protected OAuthRequest createAccessTokenPasswordGrantRequest(String username, String password, String scope) { + final OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint()); + request.addParameter(OAuthConstants.USERNAME, username); + request.addParameter(OAuthConstants.PASSWORD, password); + + if (scope != null) { + request.addParameter(OAuthConstants.SCOPE, scope); + } else if (defaultScope != null) { + request.addParameter(OAuthConstants.SCOPE, defaultScope); + } + + request.addParameter(OAuthConstants.GRANT_TYPE, OAuthConstants.PASSWORD); + + api.getClientAuthentication().addClientAuthentication(request, getApiKey(), getApiSecret()); + + logRequestWithParams("access token password grant", request); + + return request; + } + + public OAuth2AccessToken getAccessTokenPasswordGrant(String username, String password) + throws IOException, InterruptedException, ExecutionException { + final OAuthRequest request = createAccessTokenPasswordGrantRequest(username, password, null); + + return sendAccessTokenRequestSync(request); + } + + public OAuth2AccessToken getAccessTokenPasswordGrant(String username, String password, String scope) + throws IOException, InterruptedException, ExecutionException { + final OAuthRequest request = createAccessTokenPasswordGrantRequest(username, password, scope); + + return sendAccessTokenRequestSync(request); + } + + public Future getAccessTokenPasswordGrantAsync(String username, String password) { + return getAccessTokenPasswordGrantAsync(username, password, + (OAuthAsyncRequestCallback) null); + } + + public Future getAccessTokenPasswordGrantAsync(String username, String password, String scope) { + return getAccessTokenPasswordGrantAsync(username, password, scope, null); + } + + /** + * Request Access Token Password Grant async version + * + * @param username User name + * @param password User password + * @param callback Optional callback + * @return Future + */ + public Future getAccessTokenPasswordGrantAsync(String username, String password, + OAuthAsyncRequestCallback callback) { + final OAuthRequest request = createAccessTokenPasswordGrantRequest(username, password, null); + + return sendAccessTokenRequestAsync(request, callback); + } + + public Future getAccessTokenPasswordGrantAsync(String username, String password, String scope, + OAuthAsyncRequestCallback callback) { + final OAuthRequest request = createAccessTokenPasswordGrantRequest(username, password, scope); + + return sendAccessTokenRequestAsync(request, callback); + } + + // ===== get AccessToken client credentials flow methods ===== + protected OAuthRequest createAccessTokenClientCredentialsGrantRequest(String scope) { + final OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint()); + + api.getClientAuthentication().addClientAuthentication(request, getApiKey(), getApiSecret()); + + if (scope != null) { + request.addParameter(OAuthConstants.SCOPE, scope); + } else if (defaultScope != null) { + request.addParameter(OAuthConstants.SCOPE, defaultScope); + } + request.addParameter(OAuthConstants.GRANT_TYPE, OAuthConstants.CLIENT_CREDENTIALS); + + logRequestWithParams("access token client credentials grant", request); + + return request; + } + + public Future getAccessTokenClientCredentialsGrantAsync() { + return getAccessTokenClientCredentialsGrant((OAuthAsyncRequestCallback) null); + } + + public Future getAccessTokenClientCredentialsGrantAsync(String scope) { + return getAccessTokenClientCredentialsGrant(scope, null); + } + + public OAuth2AccessToken getAccessTokenClientCredentialsGrant() + throws IOException, InterruptedException, ExecutionException { + final OAuthRequest request = createAccessTokenClientCredentialsGrantRequest(null); + + return sendAccessTokenRequestSync(request); + } + + public OAuth2AccessToken getAccessTokenClientCredentialsGrant(String scope) + throws IOException, InterruptedException, ExecutionException { + final OAuthRequest request = createAccessTokenClientCredentialsGrantRequest(scope); + + return sendAccessTokenRequestSync(request); + } + + /** + * Start the request to retrieve the access token using client-credentials grant. The optionally provided callback + * will be called with the Token when it is available. + * + * @param callback optional callback + * @return Future + */ + public Future getAccessTokenClientCredentialsGrant( + OAuthAsyncRequestCallback callback) { + final OAuthRequest request = createAccessTokenClientCredentialsGrantRequest(null); + + return sendAccessTokenRequestAsync(request, callback); + } + + public Future getAccessTokenClientCredentialsGrant(String scope, + OAuthAsyncRequestCallback callback) { + final OAuthRequest request = createAccessTokenClientCredentialsGrantRequest(scope); + + return sendAccessTokenRequestAsync(request, callback); + } + + // ===== revoke AccessToken methods ===== + protected OAuthRequest createRevokeTokenRequest(String tokenToRevoke, TokenTypeHint tokenTypeHint) { + final OAuthRequest request = new OAuthRequest(Verb.POST, api.getRevokeTokenEndpoint()); + + api.getClientAuthentication().addClientAuthentication(request, getApiKey(), getApiSecret()); + + request.addParameter("token", tokenToRevoke); + if (tokenTypeHint != null) { + request.addParameter("token_type_hint", tokenTypeHint.getValue()); + } + + logRequestWithParams("revoke token", request); + + return request; + } + + public Future revokeTokenAsync(String tokenToRevoke) { + return revokeTokenAsync(tokenToRevoke, null); + } + + public Future revokeTokenAsync(String tokenToRevoke, TokenTypeHint tokenTypeHint) { + return revokeToken(tokenToRevoke, null, tokenTypeHint); + } + + public void revokeToken(String tokenToRevoke) throws IOException, InterruptedException, ExecutionException { + revokeToken(tokenToRevoke, (TokenTypeHint) null); + } + + public void revokeToken(String tokenToRevoke, TokenTypeHint tokenTypeHint) + throws IOException, InterruptedException, ExecutionException { + final OAuthRequest request = createRevokeTokenRequest(tokenToRevoke, tokenTypeHint); + + try (Response response = execute(request)) { + checkForErrorRevokeToken(response); + } + } + + public Future revokeToken(String tokenToRevoke, OAuthAsyncRequestCallback callback) { + return revokeToken(tokenToRevoke, callback, null); + } + + public Future revokeToken(String tokenToRevoke, OAuthAsyncRequestCallback callback, + TokenTypeHint tokenTypeHint) { + final OAuthRequest request = createRevokeTokenRequest(tokenToRevoke, tokenTypeHint); + + return execute(request, callback, new OAuthRequest.ResponseConverter() { + @Override + public Void convert(Response response) throws IOException { + checkForErrorRevokeToken(response); + response.close(); + return null; + } + }); + } + + private void checkForErrorRevokeToken(Response response) throws IOException { + if (response.getCode() != 200) { + OAuth2AccessTokenJsonExtractor.instance().generateError(response); + } + } + + // ===== device Authorisation codes methods ===== + protected OAuthRequest createDeviceAuthorizationCodesRequest(String scope) { + final OAuthRequest request = new OAuthRequest(Verb.POST, api.getDeviceAuthorizationEndpoint()); + request.addParameter(OAuthConstants.CLIENT_ID, getApiKey()); + if (scope != null) { + request.addParameter(OAuthConstants.SCOPE, scope); + } else if (defaultScope != null) { + request.addParameter(OAuthConstants.SCOPE, defaultScope); + } + + logRequestWithParams("Device Authorization Codes", request); + + return request; + } + + /** + * Requests a set of verification codes from the authorization server with the default scope + * + * @see RFC 8628 + * + * @return DeviceAuthorization + * @throws InterruptedException InterruptedException + * @throws ExecutionException ExecutionException + * @throws IOException IOException + */ + public DeviceAuthorization getDeviceAuthorizationCodes() + throws InterruptedException, ExecutionException, IOException { + return getDeviceAuthorizationCodes((String) null); + } + + /** + * Requests a set of verification codes from the authorization server + * + * @see RFC 8628 + * + * @param scope scope + * @return DeviceAuthorization + * @throws InterruptedException InterruptedException + * @throws ExecutionException ExecutionException + * @throws IOException IOException + */ + public DeviceAuthorization getDeviceAuthorizationCodes(String scope) + throws InterruptedException, ExecutionException, IOException { + final OAuthRequest request = createDeviceAuthorizationCodesRequest(scope); + + try (Response response = execute(request)) { + if (isDebug()) { + log("got DeviceAuthorizationCodes response"); + log("response status code: %s", response.getCode()); + log("response body: %s", response.getBody()); + } + return api.getDeviceAuthorizationExtractor().extract(response); + } + } + + public Future getDeviceAuthorizationCodes( + OAuthAsyncRequestCallback callback) { + return getDeviceAuthorizationCodes(null, callback); + } + + public Future getDeviceAuthorizationCodes(String scope, + OAuthAsyncRequestCallback callback) { + final OAuthRequest request = createDeviceAuthorizationCodesRequest(scope); + + return execute(request, callback, new OAuthRequest.ResponseConverter() { + @Override + public DeviceAuthorization convert(Response response) throws IOException { + final DeviceAuthorization deviceAuthorization = api.getDeviceAuthorizationExtractor().extract(response); + response.close(); + return deviceAuthorization; + } + }); + } + + public Future getDeviceAuthorizationCodesAsync() { + return getDeviceAuthorizationCodesAsync(null); + } + + public Future getDeviceAuthorizationCodesAsync(String scope) { + return getDeviceAuthorizationCodes(scope, null); + } + + // ===== get AccessToken Device Authorisation grant flow methods ===== + protected OAuthRequest createAccessTokenDeviceAuthorizationGrantRequest(DeviceAuthorization deviceAuthorization) { + final OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint()); + request.addParameter(OAuthConstants.GRANT_TYPE, "urn:ietf:params:oauth:grant-type:device_code"); + request.addParameter("device_code", deviceAuthorization.getDeviceCode()); + api.getClientAuthentication().addClientAuthentication(request, getApiKey(), getApiSecret()); + return request; + } + + /** + * Attempts to get a token from a server. + * + * Function {@link #pollAccessTokenDeviceAuthorizationGrant(com.github.scribejava.core.model.DeviceAuthorization)} + * is usually used instead of this. + * + * @param deviceAuthorization deviceAuthorization + * @return token + * + * @throws java.lang.InterruptedException InterruptedException + * @throws java.util.concurrent.ExecutionException ExecutionException + * @throws java.io.IOException IOException + * @throws OAuth2AccessTokenErrorResponse If {@link OAuth2AccessTokenErrorResponse#getError()} is + * {@link com.github.scribejava.core.oauth2.OAuth2Error#AUTHORIZATION_PENDING} or + * {@link com.github.scribejava.core.oauth2.OAuth2Error#SLOW_DOWN}, another attempt should be made after a while. + * + * @see #getDeviceAuthorizationCodes() + */ + public OAuth2AccessToken getAccessTokenDeviceAuthorizationGrant(DeviceAuthorization deviceAuthorization) + throws InterruptedException, ExecutionException, IOException { + final OAuthRequest request = createAccessTokenDeviceAuthorizationGrantRequest(deviceAuthorization); + + try (Response response = execute(request)) { + if (isDebug()) { + log("got AccessTokenDeviceAuthorizationGrant response"); + log("response status code: %s", response.getCode()); + log("response body: %s", response.getBody()); + } + return api.getAccessTokenExtractor().extract(response); + } + } + + public Future getAccessTokenDeviceAuthorizationGrant(DeviceAuthorization deviceAuthorization, + OAuthAsyncRequestCallback callback) { + final OAuthRequest request = createAccessTokenDeviceAuthorizationGrantRequest(deviceAuthorization); + + return execute(request, callback, new OAuthRequest.ResponseConverter() { + @Override + public OAuth2AccessToken convert(Response response) throws IOException { + final OAuth2AccessToken accessToken = api.getAccessTokenExtractor().extract(response); + response.close(); + return accessToken; + } + }); + } + + public Future getAccessTokenDeviceAuthorizationGrantAsync( + DeviceAuthorization deviceAuthorization) { + return getAccessTokenDeviceAuthorizationGrant(deviceAuthorization, null); + } + + /** + * Periodically tries to get a token from a server (waiting for the user to give consent). Sync only version. No + * Async variants yet, one should implement async scenarios themselves. + * + * @param deviceAuthorization deviceAuthorization + * @return token + * @throws java.lang.InterruptedException InterruptedException + * @throws java.util.concurrent.ExecutionException ExecutionException + * @throws java.io.IOException IOException + * @throws OAuth2AccessTokenErrorResponse Indicates OAuth error. + * + * @see #getDeviceAuthorizationCodes() + */ + public OAuth2AccessToken pollAccessTokenDeviceAuthorizationGrant(DeviceAuthorization deviceAuthorization) + throws InterruptedException, ExecutionException, IOException { + long intervalMillis = deviceAuthorization.getIntervalSeconds() * 1000; + while (true) { + try { + return getAccessTokenDeviceAuthorizationGrant(deviceAuthorization); + } catch (OAuth2AccessTokenErrorResponse e) { + if (e.getError() != OAuth2Error.AUTHORIZATION_PENDING) { + if (e.getError() == OAuth2Error.SLOW_DOWN) { + intervalMillis += 5000; + } else { + throw e; + } + } + } + Thread.sleep(intervalMillis); + } + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuthService.java b/scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuthService.java new file mode 100644 index 000000000..996abee6f --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuthService.java @@ -0,0 +1,148 @@ +package com.github.scribejava.core.oauth; + +import com.github.scribejava.core.httpclient.HttpClientProvider; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.httpclient.jdk.JDKHttpClient; +import com.github.scribejava.core.httpclient.jdk.JDKHttpClientConfig; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import java.io.Closeable; +import java.io.File; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ServiceLoader; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +public abstract class OAuthService implements Closeable { + + private final String apiKey; + private final String apiSecret; + private final String callback; + private final String userAgent; + private final HttpClient httpClient; + private final OutputStream debugStream; + + public OAuthService(String apiKey, String apiSecret, String callback, OutputStream debugStream, + String userAgent, HttpClientConfig httpClientConfig, HttpClient httpClient) { + this.apiKey = apiKey; + this.apiSecret = apiSecret; + this.callback = callback; + this.debugStream = debugStream; + this.userAgent = userAgent; + + if (httpClientConfig == null && httpClient == null) { + this.httpClient = new JDKHttpClient(JDKHttpClientConfig.defaultConfig()); + } else { + this.httpClient = httpClient == null ? getClient(httpClientConfig) : httpClient; + } + } + + private static HttpClient getClient(HttpClientConfig config) { + for (HttpClientProvider provider : ServiceLoader.load(HttpClientProvider.class)) { + final HttpClient client = provider.createClient(config); + if (client != null) { + return client; + } + } + return null; + } + + @Override + public void close() throws IOException { + httpClient.close(); + } + + public String getApiKey() { + return apiKey; + } + + public String getApiSecret() { + return apiSecret; + } + + public String getCallback() { + return callback; + } + + /** + * Returns the OAuth version of the service. + * + * @return OAuth version as string + */ + public abstract String getVersion(); + + public Future executeAsync(OAuthRequest request) { + return execute(request, null); + } + + public Future execute(OAuthRequest request, OAuthAsyncRequestCallback callback) { + return execute(request, callback, null); + } + + public Future execute(OAuthRequest request, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + + final File filePayload = request.getFilePayload(); + if (filePayload != null) { + return httpClient.executeAsync(userAgent, request.getHeaders(), request.getVerb(), request.getCompleteUrl(), + filePayload, callback, converter); + } else if (request.getStringPayload() != null) { + return httpClient.executeAsync(userAgent, request.getHeaders(), request.getVerb(), request.getCompleteUrl(), + request.getStringPayload(), callback, converter); + } else { + return httpClient.executeAsync(userAgent, request.getHeaders(), request.getVerb(), request.getCompleteUrl(), + request.getByteArrayPayload(), callback, converter); + } + } + + public Response execute(OAuthRequest request) throws InterruptedException, ExecutionException, IOException { + final File filePayload = request.getFilePayload(); + if (filePayload != null) { + return httpClient.execute(userAgent, request.getHeaders(), request.getVerb(), request.getCompleteUrl(), + filePayload); + } else if (request.getStringPayload() != null) { + return httpClient.execute(userAgent, request.getHeaders(), request.getVerb(), request.getCompleteUrl(), + request.getStringPayload()); + } else if (request.getMultipartPayload() != null) { + return httpClient.execute(userAgent, request.getHeaders(), request.getVerb(), request.getCompleteUrl(), + request.getMultipartPayload()); + } else { + return httpClient.execute(userAgent, request.getHeaders(), request.getVerb(), request.getCompleteUrl(), + request.getByteArrayPayload()); + } + } + + /** + * No need to wrap usages in {@link #isDebug()}. + * + * @param message message to log + */ + public void log(String message) { + if (debugStream != null) { + log(message, (Object[]) null); + } + } + + /** + * Wrap usages in {@link #isDebug()}. It was made for optimization - to not calculate "params" in production mode. + * + * @param messagePattern messagePattern + * @param params params + */ + public void log(String messagePattern, Object... params) { + final String message = String.format(messagePattern, params) + '\n'; + try { + debugStream.write(message.getBytes("UTF8")); + } catch (IOException | RuntimeException e) { + throw new RuntimeException("there were problems while writting to the debug stream", e); + } + } + + protected boolean isDebug() { + return debugStream != null; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/OAuth2Error.java b/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/OAuth2Error.java new file mode 100644 index 000000000..b1422bcae --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/OAuth2Error.java @@ -0,0 +1,108 @@ +package com.github.scribejava.core.oauth2; + +import java.util.EnumSet; +import java.util.Set; + +public enum OAuth2Error { + /** + * @see RFC 6749, 4.1.2.1 Error Response + * @see RFC 6749, 4.2.2.1 Error Response + * @see RFC 6749, 5.2 Error Response + * @see RFC 6750, 6.2. OAuth Extensions Error + * Registration + */ + INVALID_REQUEST("invalid_request"), + /** + * @see RFC 6749, 4.1.2.1 Error Response + * @see RFC 6749, 4.2.2.1 Error Response + * @see RFC 6749, 5.2 Error Response + */ + UNAUTHORIZED_CLIENT("unauthorized_client"), + /** + * @see RFC 6749, 4.1.2.1 Error Response + * @see RFC 6749, 4.2.2.1 Error Response + * @see RFC 8628, 3.5. Device Access Token Response + */ + ACCESS_DENIED("access_denied"), + /** + * @see RFC 6749, 4.1.2.1 Error Response + * @see RFC 6749, 4.2.2.1 Error Response + */ + UNSUPPORTED_RESPONSE_TYPE("unsupported_response_type"), + /** + * @see RFC 6749, 4.1.2.1 Error Response + * @see RFC 6749, 4.2.2.1 Error Response + * @see RFC 6749, 5.2 Error Response + */ + INVALID_SCOPE("invalid_scope"), + /** + * @see RFC 6749, 4.1.2.1 Error Response + * @see RFC 6749, 4.2.2.1 Error Response + */ + SERVER_ERROR("server_error"), + /** + * @see RFC 6749, 4.1.2.1 Error Response + * @see RFC 6749, 4.2.2.1 Error Response + */ + TEMPORARILY_UNAVAILABLE("temporarily_unavailable"), + /** + * @see RFC 6749, 5.2 Error Response + */ + INVALID_CLIENT("invalid_client"), + /** + * @see RFC 6749, 5.2 Error Response + */ + INVALID_GRANT("invalid_grant"), + /** + * @see RFC 6749, 5.2 Error Response + */ + UNSUPPORTED_GRANT_TYPE("unsupported_grant_type"), + /** + * @see RFC 6750, 6.2. OAuth Extensions Error + * Registration + */ + INVALID_TOKEN("invalid_token"), + /** + * @see RFC 6750, 6.2. OAuth Extensions Error + * Registration + */ + INSUFFICIENT_SCOPE("insufficient_scope"), + /** + * @see RFC 7009, 4.1. OAuth Extensions Error + * Registration + */ + UNSUPPORTED_TOKEN_TYPE("unsupported_token_type"), + /** + * @see RFC 8628, 3.5. Device Access Token Response + */ + AUTHORIZATION_PENDING("authorization_pending"), + /** + * @see RFC 8628, 3.5. Device Access Token Response + */ + SLOW_DOWN("slow_down"), + /** + * @see RFC 8628, 3.5. Device Access Token Response + */ + EXPIRED_TOKEN("expired_token"); + + private static final Set VALUES = EnumSet.allOf(OAuth2Error.class); + + private final String errorString; + + OAuth2Error(String errorString) { + this.errorString = errorString; + } + + public static OAuth2Error parseFrom(String errorString) { + for (OAuth2Error error : VALUES) { + if (error.errorString.equals(errorString)) { + return error; + } + } + throw new IllegalArgumentException("there is no knowlege about '" + errorString + "' Error"); + } + + public String getErrorString() { + return errorString; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/bearersignature/BearerSignature.java b/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/bearersignature/BearerSignature.java new file mode 100644 index 000000000..61739e93e --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/bearersignature/BearerSignature.java @@ -0,0 +1,12 @@ +package com.github.scribejava.core.oauth2.bearersignature; + +import com.github.scribejava.core.model.OAuthRequest; + +/** + * Represents
+ * 2. Authenticated Requests
+ * https://tools.ietf.org/html/rfc6750#section-2 + */ +public interface BearerSignature { + void signRequest(String accessToken, OAuthRequest request); +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/bearersignature/BearerSignatureAuthorizationRequestHeaderField.java b/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/bearersignature/BearerSignatureAuthorizationRequestHeaderField.java new file mode 100644 index 000000000..98196a708 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/bearersignature/BearerSignatureAuthorizationRequestHeaderField.java @@ -0,0 +1,29 @@ +package com.github.scribejava.core.oauth2.bearersignature; + +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; + +/** + * 2.1. Authorization Request Header Field
+ * https://tools.ietf.org/html/rfc6750#section-2.1 + */ +public class BearerSignatureAuthorizationRequestHeaderField implements BearerSignature { + + protected BearerSignatureAuthorizationRequestHeaderField() { + } + + private static class InstanceHolder { + + private static final BearerSignatureAuthorizationRequestHeaderField INSTANCE + = new BearerSignatureAuthorizationRequestHeaderField(); + } + + public static BearerSignatureAuthorizationRequestHeaderField instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public void signRequest(String accessToken, OAuthRequest request) { + request.addHeader(OAuthConstants.HEADER, "Bearer " + accessToken); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/bearersignature/BearerSignatureURIQueryParameter.java b/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/bearersignature/BearerSignatureURIQueryParameter.java new file mode 100644 index 000000000..72cc64b43 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/bearersignature/BearerSignatureURIQueryParameter.java @@ -0,0 +1,27 @@ +package com.github.scribejava.core.oauth2.bearersignature; + +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; + +/** + * 2.3. URI Query Parameter
+ * https://tools.ietf.org/html/rfc6750#section-2.3 + */ +public class BearerSignatureURIQueryParameter implements BearerSignature { + protected BearerSignatureURIQueryParameter() { + } + + private static class InstanceHolder { + + private static final BearerSignatureURIQueryParameter INSTANCE = new BearerSignatureURIQueryParameter(); + } + + public static BearerSignatureURIQueryParameter instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public void signRequest(String accessToken, OAuthRequest request) { + request.addQuerystringParameter(OAuthConstants.ACCESS_TOKEN, accessToken); + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/clientauthentication/ClientAuthentication.java b/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/clientauthentication/ClientAuthentication.java new file mode 100644 index 000000000..54fdb5de6 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/clientauthentication/ClientAuthentication.java @@ -0,0 +1,17 @@ +package com.github.scribejava.core.oauth2.clientauthentication; + +import com.github.scribejava.core.model.OAuthRequest; + +/** + * Represents
+ * 2.3. Client Authentication
+ * https://tools.ietf.org/html/rfc6749#section-2.3 + *
+ * just implement this interface to implement "2.3.2. Other Authentication Methods"
+ * https://tools.ietf.org/html/rfc6749#section-2.3.2 + * + */ +public interface ClientAuthentication { + + void addClientAuthentication(OAuthRequest request, String apiKey, String apiSecret); +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/clientauthentication/HttpBasicAuthenticationScheme.java b/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/clientauthentication/HttpBasicAuthenticationScheme.java new file mode 100644 index 000000000..3931f6f7b --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/clientauthentication/HttpBasicAuthenticationScheme.java @@ -0,0 +1,37 @@ +package com.github.scribejava.core.oauth2.clientauthentication; + +import com.github.scribejava.core.base64.Base64; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import java.nio.charset.Charset; + +/** + * 2.3. Client Authentication
+ * 2.3.1. Client Password
+ * https://tools.ietf.org/html/rfc6749#section-2.3.1 + *
+ * НTTP Basic authentication scheme + */ +public class HttpBasicAuthenticationScheme implements ClientAuthentication { + + protected HttpBasicAuthenticationScheme() { + } + + private static class InstanceHolder { + + private static final HttpBasicAuthenticationScheme INSTANCE = new HttpBasicAuthenticationScheme(); + } + + public static HttpBasicAuthenticationScheme instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public void addClientAuthentication(OAuthRequest request, String apiKey, String apiSecret) { + if (apiKey != null && apiSecret != null) { + request.addHeader(OAuthConstants.HEADER, OAuthConstants.BASIC + ' ' + + Base64.encode(String.format("%s:%s", apiKey, apiSecret).getBytes(Charset.forName("UTF-8")))); + } + } + +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/clientauthentication/RequestBodyAuthenticationScheme.java b/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/clientauthentication/RequestBodyAuthenticationScheme.java new file mode 100644 index 000000000..5e91affa7 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/oauth2/clientauthentication/RequestBodyAuthenticationScheme.java @@ -0,0 +1,34 @@ +package com.github.scribejava.core.oauth2.clientauthentication; + +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; + +/** + * 2.3. Client Authentication
+ * 2.3.1. Client Password
+ * https://tools.ietf.org/html/rfc6749#section-2.3.1 + *
+ * request-body authentication scheme + */ +public class RequestBodyAuthenticationScheme implements ClientAuthentication { + + protected RequestBodyAuthenticationScheme() { + } + + private static class InstanceHolder { + + private static final RequestBodyAuthenticationScheme INSTANCE = new RequestBodyAuthenticationScheme(); + } + + public static RequestBodyAuthenticationScheme instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public void addClientAuthentication(OAuthRequest request, String apiKey, String apiSecret) { + request.addParameter(OAuthConstants.CLIENT_ID, apiKey); + if (apiSecret != null) { + request.addParameter(OAuthConstants.CLIENT_SECRET, apiSecret); + } + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/pkce/PKCE.java b/scribejava-core/src/main/java/com/github/scribejava/core/pkce/PKCE.java new file mode 100644 index 000000000..c8d43d26e --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/pkce/PKCE.java @@ -0,0 +1,49 @@ +package com.github.scribejava.core.pkce; + +import java.util.HashMap; +import java.util.Map; + +/** + * Used to hold code_challenge, code_challenge_method and code_verifier for https://tools.ietf.org/html/rfc7636 + */ +public class PKCE { + + public static final String PKCE_CODE_CHALLENGE_METHOD_PARAM = "code_challenge_method"; + public static final String PKCE_CODE_CHALLENGE_PARAM = "code_challenge"; + public static final String PKCE_CODE_VERIFIER_PARAM = "code_verifier"; + + private String codeChallenge; + private PKCECodeChallengeMethod codeChallengeMethod = PKCECodeChallengeMethod.S256; + private String codeVerifier; + + public String getCodeChallenge() { + return codeChallenge; + } + + public void setCodeChallenge(String codeChallenge) { + this.codeChallenge = codeChallenge; + } + + public PKCECodeChallengeMethod getCodeChallengeMethod() { + return codeChallengeMethod; + } + + public void setCodeChallengeMethod(PKCECodeChallengeMethod codeChallengeMethod) { + this.codeChallengeMethod = codeChallengeMethod; + } + + public String getCodeVerifier() { + return codeVerifier; + } + + public void setCodeVerifier(String codeVerifier) { + this.codeVerifier = codeVerifier; + } + + public Map getAuthorizationUrlParams() { + final Map params = new HashMap<>(); + params.put(PKCE_CODE_CHALLENGE_PARAM, codeChallenge); + params.put(PKCE_CODE_CHALLENGE_METHOD_PARAM, codeChallengeMethod.name()); + return params; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/pkce/PKCECodeChallengeMethod.java b/scribejava-core/src/main/java/com/github/scribejava/core/pkce/PKCECodeChallengeMethod.java new file mode 100644 index 000000000..374f80336 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/pkce/PKCECodeChallengeMethod.java @@ -0,0 +1,24 @@ +package com.github.scribejava.core.pkce; + +import com.github.scribejava.core.base64.Base64; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public enum PKCECodeChallengeMethod { + S256 { + @Override + public String transform2CodeChallenge(String codeVerifier) throws NoSuchAlgorithmException { + return Base64.encodeUrlWithoutPadding( + MessageDigest.getInstance("SHA-256").digest(codeVerifier.getBytes(StandardCharsets.US_ASCII))); + } + }, + PLAIN { + @Override + public String transform2CodeChallenge(String codeVerifier) { + return codeVerifier; + } + }; + + public abstract String transform2CodeChallenge(String codeVerifier) throws NoSuchAlgorithmException; +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/pkce/PKCEService.java b/scribejava-core/src/main/java/com/github/scribejava/core/pkce/PKCEService.java new file mode 100644 index 000000000..23a5347ec --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/pkce/PKCEService.java @@ -0,0 +1,62 @@ +package com.github.scribejava.core.pkce; + +import com.github.scribejava.core.base64.Base64; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +/** + * Used to implement Proof Key for Code Exchange by OAuth Public Clients https://tools.ietf.org/html/rfc7636 + * + */ +public class PKCEService { + + private static final SecureRandom RANDOM = new SecureRandom(); + /** + * number of octets to randomly generate. + */ + private final int numberOFOctets; + + public PKCEService(int numberOFOctets) { + this.numberOFOctets = numberOFOctets; + } + + /** + * will create random generator with recommended params (32 octets) https://tools.ietf.org/html/rfc7636#section-4.1 + */ + public PKCEService() { + this(32); + } + + private static class DefaultInstanceHolder { + + private static final PKCEService INSTANCE = new PKCEService(); + } + + public static PKCEService defaultInstance() { + return DefaultInstanceHolder.INSTANCE; + } + + public PKCE generatePKCE() { + final byte[] bytes = new byte[numberOFOctets]; + RANDOM.nextBytes(bytes); + return generatePKCE(bytes); + } + + public PKCE generatePKCE(byte[] randomBytes) { + final String codeVerifier = Base64.encodeUrlWithoutPadding(randomBytes); + + final PKCE pkce = new PKCE(); + pkce.setCodeVerifier(codeVerifier); + try { + pkce.setCodeChallenge(pkce.getCodeChallengeMethod().transform2CodeChallenge(codeVerifier)); + } catch (NoSuchAlgorithmException nsaE) { + pkce.setCodeChallengeMethod(PKCECodeChallengeMethod.PLAIN); + try { + pkce.setCodeChallenge(PKCECodeChallengeMethod.PLAIN.transform2CodeChallenge(codeVerifier)); + } catch (NoSuchAlgorithmException unrealE) { + throw new IllegalStateException("It's just cannot be", unrealE); + } + } + return pkce; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/revoke/OAuth2RevokeTokenResponseConverter.java b/scribejava-core/src/main/java/com/github/scribejava/core/revoke/OAuth2RevokeTokenResponseConverter.java new file mode 100644 index 000000000..dc595a410 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/revoke/OAuth2RevokeTokenResponseConverter.java @@ -0,0 +1,15 @@ +package com.github.scribejava.core.revoke; + +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.model.Response; +import java.io.IOException; + +public class OAuth2RevokeTokenResponseConverter { + + public Void convert(Response response) throws IOException { + if (response.getCode() != 200) { + OAuth2AccessTokenJsonExtractor.instance().generateError(response); + } + return null; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/revoke/TokenTypeHint.java b/scribejava-core/src/main/java/com/github/scribejava/core/revoke/TokenTypeHint.java new file mode 100644 index 000000000..79de78d26 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/revoke/TokenTypeHint.java @@ -0,0 +1,23 @@ +package com.github.scribejava.core.revoke; + +/** + * + * as stated in RFC 7009
+ * 2.1. Revocation Request + * + * @see RFC 7009, 2.1. Revocation Request + */ +public enum TokenTypeHint { + ACCESS_TOKEN("access_token"), + REFRESH_TOKEN("refresh_token"); + + private final String value; + + TokenTypeHint(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/services/HMACSha1SignatureService.java b/scribejava-core/src/main/java/com/github/scribejava/core/services/HMACSha1SignatureService.java new file mode 100644 index 000000000..363011a13 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/services/HMACSha1SignatureService.java @@ -0,0 +1,54 @@ +package com.github.scribejava.core.services; + +import com.github.scribejava.core.base64.Base64; +import java.io.UnsupportedEncodingException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import com.github.scribejava.core.exceptions.OAuthSignatureException; +import com.github.scribejava.core.utils.OAuthEncoder; +import com.github.scribejava.core.utils.Preconditions; + +/** + * HMAC-SHA1 implementation of {@link SignatureService} https://tools.ietf.org/html/rfc5849#section-3.4.2 + */ +public class HMACSha1SignatureService implements SignatureService { + + private static final String EMPTY_STRING = ""; + private static final String CARRIAGE_RETURN = "\r\n"; + private static final String UTF8 = "UTF-8"; + private static final String HMAC_SHA1 = "HmacSHA1"; + private static final String METHOD = "HMAC-SHA1"; + + /** + * {@inheritDoc} + */ + @Override + public String getSignature(String baseString, String apiSecret, String tokenSecret) { + try { + Preconditions.checkEmptyString(baseString, "Base string can't be null or empty string"); + Preconditions.checkNotNull(apiSecret, "Api secret can't be null"); + return doSign(baseString, OAuthEncoder.encode(apiSecret) + '&' + OAuthEncoder.encode(tokenSecret)); + } catch (UnsupportedEncodingException | NoSuchAlgorithmException | InvalidKeyException | RuntimeException e) { + throw new OAuthSignatureException(baseString, e); + } + } + + private String doSign(String toSign, String keyString) throws UnsupportedEncodingException, + NoSuchAlgorithmException, InvalidKeyException { + final SecretKeySpec key = new SecretKeySpec(keyString.getBytes(UTF8), HMAC_SHA1); + final Mac mac = Mac.getInstance(HMAC_SHA1); + mac.init(key); + final byte[] bytes = mac.doFinal(toSign.getBytes(UTF8)); + return Base64.encode(bytes).replace(CARRIAGE_RETURN, EMPTY_STRING); + } + + /** + * {@inheritDoc} + */ + @Override + public String getSignatureMethod() { + return METHOD; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/services/PlaintextSignatureService.java b/scribejava-core/src/main/java/com/github/scribejava/core/services/PlaintextSignatureService.java new file mode 100644 index 000000000..143348484 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/services/PlaintextSignatureService.java @@ -0,0 +1,34 @@ +package com.github.scribejava.core.services; + +import com.github.scribejava.core.exceptions.OAuthSignatureException; +import com.github.scribejava.core.utils.OAuthEncoder; +import com.github.scribejava.core.utils.Preconditions; + +/** + * plaintext implementation of {@link SignatureService} + */ +public class PlaintextSignatureService implements SignatureService { + + private static final String METHOD = "PLAINTEXT"; + + /** + * {@inheritDoc} + */ + @Override + public String getSignature(String baseString, String apiSecret, String tokenSecret) { + try { + Preconditions.checkNotNull(apiSecret, "Api secret can't be null"); + return OAuthEncoder.encode(apiSecret) + '&' + OAuthEncoder.encode(tokenSecret); + } catch (Exception e) { + throw new OAuthSignatureException(baseString, e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public String getSignatureMethod() { + return METHOD; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/services/RSASha1SignatureService.java b/scribejava-core/src/main/java/com/github/scribejava/core/services/RSASha1SignatureService.java new file mode 100644 index 000000000..dc16eace4 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/services/RSASha1SignatureService.java @@ -0,0 +1,50 @@ +package com.github.scribejava.core.services; + +import com.github.scribejava.core.base64.Base64; +import java.security.PrivateKey; +import java.security.Signature; +import java.security.SignatureException; +import com.github.scribejava.core.exceptions.OAuthSignatureException; +import java.io.UnsupportedEncodingException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +/** + * A signature service that uses the RSA-SHA1 algorithm. + */ +public class RSASha1SignatureService implements SignatureService { + + private static final String METHOD = "RSA-SHA1"; + private static final String RSA_SHA1 = "SHA1withRSA"; + private static final String UTF8 = "UTF-8"; + + private final PrivateKey privateKey; + + public RSASha1SignatureService(PrivateKey privateKey) { + this.privateKey = privateKey; + } + + /** + * {@inheritDoc} + */ + @Override + public String getSignature(String baseString, String apiSecret, String tokenSecret) { + try { + final Signature signature = Signature.getInstance(RSA_SHA1); + signature.initSign(privateKey); + signature.update(baseString.getBytes(UTF8)); + return Base64.encode(signature.sign()); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | UnsupportedEncodingException + | RuntimeException e) { + throw new OAuthSignatureException(baseString, e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public String getSignatureMethod() { + return METHOD; + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/services/SignatureService.java b/scribejava-core/src/main/java/com/github/scribejava/core/services/SignatureService.java new file mode 100644 index 000000000..10c50f3ae --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/services/SignatureService.java @@ -0,0 +1,20 @@ +package com.github.scribejava.core.services; + +/** + * Signs a base string, returning the OAuth signature https://tools.ietf.org/html/rfc5849#section-3.4 + */ +public interface SignatureService { + + /** + * Returns the signature + * + * @param baseString url-encoded string to sign + * @param apiSecret api secret for your app + * @param tokenSecret token secret (empty string for the request token step) + * + * @return signature + */ + String getSignature(String baseString, String apiSecret, String tokenSecret); + + String getSignatureMethod(); +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/services/TimestampService.java b/scribejava-core/src/main/java/com/github/scribejava/core/services/TimestampService.java new file mode 100644 index 000000000..f062b640a --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/services/TimestampService.java @@ -0,0 +1,23 @@ +package com.github.scribejava.core.services; + +/** + * Unix epoch timestamp generator. + * + * This class is useful for stubbing in tests. + */ +public interface TimestampService { + + /** + * Returns the unix epoch timestamp in seconds + * + * @return timestamp + */ + String getTimestampInSeconds(); + + /** + * Returns a nonce (unique value for each request) + * + * @return nonce + */ + String getNonce(); +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/services/TimestampServiceImpl.java b/scribejava-core/src/main/java/com/github/scribejava/core/services/TimestampServiceImpl.java new file mode 100644 index 000000000..76109f10e --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/services/TimestampServiceImpl.java @@ -0,0 +1,60 @@ +package com.github.scribejava.core.services; + +import java.util.Random; + +/** + * Implementation of {@link TimestampService} using plain java classes. + */ +public class TimestampServiceImpl implements TimestampService { + + private Timer timer; + + /** + * Default constructor. + */ + public TimestampServiceImpl() { + timer = new Timer(); + } + + /** + * {@inheritDoc} + */ + @Override + public String getNonce() { + final Long ts = getTs(); + return String.valueOf(ts + timer.getRandomInteger()); + } + + /** + * {@inheritDoc} + */ + @Override + public String getTimestampInSeconds() { + return String.valueOf(getTs()); + } + + private Long getTs() { + return timer.getMilis() / 1000; + } + + void setTimer(Timer timer) { + this.timer = timer; + } + + /** + * Inner class that uses {@link System} for generating the timestamps. + */ + static class Timer { + + private final Random rand = new Random(); + + Long getMilis() { + return System.currentTimeMillis(); + } + + Integer getRandomInteger() { + return rand.nextInt(); + } + } + +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/utils/OAuthEncoder.java b/scribejava-core/src/main/java/com/github/scribejava/core/utils/OAuthEncoder.java new file mode 100644 index 000000000..83918e7af --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/utils/OAuthEncoder.java @@ -0,0 +1,51 @@ +package com.github.scribejava.core.utils; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; +import com.github.scribejava.core.exceptions.OAuthException; + +public abstract class OAuthEncoder { + + private static final String CHARSET = "UTF-8"; + private static final Map ENCODING_RULES; + + static { + final Map rules = new HashMap<>(); + rules.put("*", "%2A"); + rules.put("+", "%20"); + rules.put("%7E", "~"); + ENCODING_RULES = Collections.unmodifiableMap(rules); + } + + public static String encode(String plain) { + Preconditions.checkNotNull(plain, "Cannot encode null object"); + String encoded; + try { + encoded = URLEncoder.encode(plain, CHARSET); + } catch (UnsupportedEncodingException uee) { + throw new OAuthException("Charset not found while encoding string: " + CHARSET, uee); + } + for (Map.Entry rule : ENCODING_RULES.entrySet()) { + encoded = applyRule(encoded, rule.getKey(), rule.getValue()); + } + return encoded; + } + + private static String applyRule(String encoded, String toReplace, String replacement) { + return encoded.replaceAll(Pattern.quote(toReplace), replacement); + } + + public static String decode(String encoded) { + Preconditions.checkNotNull(encoded, "Cannot decode null object"); + try { + return URLDecoder.decode(encoded, CHARSET); + } catch (UnsupportedEncodingException uee) { + throw new OAuthException("Charset not found while decoding string: " + CHARSET, uee); + } + } +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/utils/Preconditions.java b/scribejava-core/src/main/java/com/github/scribejava/core/utils/Preconditions.java new file mode 100644 index 000000000..19e1df083 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/utils/Preconditions.java @@ -0,0 +1,53 @@ +package com.github.scribejava.core.utils; + +/** + * Utils for checking preconditions and invariants + */ +public abstract class Preconditions { + + private static final String DEFAULT_MESSAGE = "Received an invalid parameter"; + + /** + * Checks that an object is not null. + * + * @param object any object + * @param errorMsg error message + * + * @throws IllegalArgumentException if the object is null + */ + public static void checkNotNull(Object object, String errorMsg) { + check(object != null, errorMsg); + } + + /** + * Checks that a string is not null or empty + * + * @param string any string + * @param errorMsg error message + * + * @throws IllegalArgumentException if the string is null or empty + */ + public static void checkEmptyString(String string, String errorMsg) { + check(hasText(string), errorMsg); + } + + public static boolean hasText(String str) { + if (str == null || str.isEmpty()) { + return false; + } + final int strLen = str.length(); + for (int i = 0; i < strLen; i++) { + if (!Character.isWhitespace(str.charAt(i))) { + return true; + } + } + return false; + } + + private static void check(boolean requirements, String error) { + if (!requirements) { + throw new IllegalArgumentException(hasText(error) ? error : DEFAULT_MESSAGE); + } + } + +} diff --git a/scribejava-core/src/main/java/com/github/scribejava/core/utils/StreamUtils.java b/scribejava-core/src/main/java/com/github/scribejava/core/utils/StreamUtils.java new file mode 100644 index 000000000..7a86318d2 --- /dev/null +++ b/scribejava-core/src/main/java/com/github/scribejava/core/utils/StreamUtils.java @@ -0,0 +1,49 @@ +package com.github.scribejava.core.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.zip.GZIPInputStream; + +/** + * Utils to deal with Streams. + */ +public abstract class StreamUtils { + + /** + * Returns the stream contents as an UTF-8 encoded string + * + * @param is input stream + * @return string contents + * @throws java.io.IOException in any. SocketTimeout in example + */ + public static String getStreamContents(InputStream is) throws IOException { + Preconditions.checkNotNull(is, "Cannot get String from a null object"); + final char[] buffer = new char[0x10000]; + final StringBuilder out = new StringBuilder(); + try (Reader in = new InputStreamReader(is, "UTF-8")) { + int read; + do { + read = in.read(buffer, 0, buffer.length); + if (read > 0) { + out.append(buffer, 0, read); + } + } while (read >= 0); + } + return out.toString(); + } + + /** + * Return String content from a gzip stream + * + * @param is input stream + * @return string contents + * @throws java.io.IOException in any. SocketTimeout in example + */ + public static String getGzipStreamContents(InputStream is) throws IOException { + Preconditions.checkNotNull(is, "Cannot get String from a null object"); + final GZIPInputStream gis = new GZIPInputStream(is); + return getStreamContents(gis); + } +} diff --git a/scribejava-core/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider b/scribejava-core/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider new file mode 100644 index 000000000..7df053c24 --- /dev/null +++ b/scribejava-core/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider @@ -0,0 +1,2 @@ +com.github.scribejava.core.httpclient.jdk.JDKHttpProvider + diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/AbstractClientTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/AbstractClientTest.java new file mode 100644 index 000000000..c1bc1967e --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/AbstractClientTest.java @@ -0,0 +1,264 @@ +package com.github.scribejava.core; + +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.core.oauth.OAuthService; +import com.github.scribejava.core.utils.StreamUtils; +import okhttp3.HttpUrl; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNotNull; + +public abstract class AbstractClientTest { + + private OAuthService oAuthService; + + private static class TestCallback implements OAuthAsyncRequestCallback { + + private Response response; + + @Override + public void onCompleted(Response response) { + this.response = response; + } + + @Override + public void onThrowable(Throwable throwable) { + } + + public Response getResponse() { + return response; + } + } + + @Before + public void setUp() { + oAuthService = new OAuth20Service(null, "test", "test", null, null, null, System.out, null, null, + createNewClient()); + } + + @After + public void shutDown() throws Exception { + oAuthService.close(); + } + + protected abstract HttpClient createNewClient(); + + @Test + public void shouldSendGetRequest() throws Exception { + final String expectedResponseBody = "response body for test shouldSendGetRequest"; + + final MockWebServer server = new MockWebServer(); + server.enqueue(new MockResponse().setBody(expectedResponseBody)); + server.start(); + + final HttpUrl baseUrl = server.url("/testUrl"); + + final OAuthRequest request = new OAuthRequest(Verb.GET, baseUrl.toString()); + + try (Response response = oAuthService.execute(request, null).get(30, TimeUnit.SECONDS)) { + assertEquals(expectedResponseBody, response.getBody()); + } + + final RecordedRequest recordedRequest = server.takeRequest(); + assertEquals("GET", recordedRequest.getMethod()); + + server.shutdown(); + } + + @Test + public void shouldSendPostWithApplicationXWwwFormUrlencodedRequestContentTypeHeader() throws Exception { + final MockWebServer server = new MockWebServer(); + server.enqueue(new MockResponse()); + server.start(); + + final HttpUrl baseUrl = server.url("/testUrl"); + + final OAuthRequest request = new OAuthRequest(Verb.POST, baseUrl.toString()); + oAuthService.execute(request, null).get(30, TimeUnit.SECONDS).close(); + + final RecordedRequest recordedRequest = server.takeRequest(); + assertEquals("POST", recordedRequest.getMethod()); + assertEquals(HttpClient.DEFAULT_CONTENT_TYPE, recordedRequest.getHeader(HttpClient.CONTENT_TYPE)); + + server.shutdown(); + } + + @Test + public void shouldSendPostRequestWithEmptyBody() throws Exception { + final String expectedResponseBody = "response body for test shouldSendPostRequest"; + final String expectedRequestBody = ""; + + final MockWebServer server = new MockWebServer(); + server.enqueue(new MockResponse().setBody(expectedResponseBody)); + server.start(); + + final HttpUrl baseUrl = server.url("/testUrl"); + + final OAuthRequest request = new OAuthRequest(Verb.POST, baseUrl.toString()); + try (Response response = oAuthService.execute(request, null).get(30, TimeUnit.SECONDS)) { + assertEquals(expectedResponseBody, response.getBody()); + } + + final RecordedRequest recordedRequest = server.takeRequest(); + assertEquals("POST", recordedRequest.getMethod()); + assertEquals(expectedRequestBody, recordedRequest.getBody().readUtf8()); + assertEquals(HttpClient.DEFAULT_CONTENT_TYPE, recordedRequest.getHeader(HttpClient.CONTENT_TYPE)); + + server.shutdown(); + } + + @Test + public void shouldSendPostRequestWithStringBody() throws Exception { + final String expectedResponseBody = "response body for test shouldSendPostRequest"; + final String expectedRequestBody = "request body"; + + final MockWebServer server = new MockWebServer(); + server.enqueue(new MockResponse().setBody(expectedResponseBody)); + server.start(); + + final HttpUrl baseUrl = server.url("/testUrl"); + + final OAuthRequest request = new OAuthRequest(Verb.POST, baseUrl.toString()); + request.setPayload(expectedRequestBody); + try (Response response = oAuthService.execute(request, null).get(30, TimeUnit.SECONDS)) { + assertEquals(expectedResponseBody, response.getBody()); + } + + final RecordedRequest recordedRequest = server.takeRequest(); + assertEquals("POST", recordedRequest.getMethod()); + assertEquals(expectedRequestBody, recordedRequest.getBody().readUtf8()); + final String contentTypeHeader = recordedRequest.getHeader(HttpClient.CONTENT_TYPE); + assertNotNull(contentTypeHeader); + assertTrue(contentTypeHeader.startsWith(HttpClient.DEFAULT_CONTENT_TYPE)); + + server.shutdown(); + } + + @Test + public void shouldSendPostRequestWithByteBodyBody() throws Exception { + final String expectedResponseBody = "response body for test shouldSendPostRequest"; + final String expectedRequestBody = "request body"; + + final MockWebServer server = new MockWebServer(); + server.enqueue(new MockResponse().setBody(expectedResponseBody)); + server.start(); + + final HttpUrl baseUrl = server.url("/testUrl"); + + final OAuthRequest request = new OAuthRequest(Verb.POST, baseUrl.toString()); + request.setPayload(expectedRequestBody.getBytes()); + try (Response response = oAuthService.execute(request, null).get(30, TimeUnit.SECONDS)) { + assertEquals(expectedResponseBody, response.getBody()); + } + + final RecordedRequest recordedRequest = server.takeRequest(); + assertEquals("POST", recordedRequest.getMethod()); + assertEquals(expectedRequestBody, recordedRequest.getBody().readUtf8()); + assertEquals(HttpClient.DEFAULT_CONTENT_TYPE, recordedRequest.getHeader(HttpClient.CONTENT_TYPE)); + + server.shutdown(); + } + + @Test + public void shouldSendPostRequestWithBodyParamsBody() throws Exception { + final String expectedResponseBody = "response body for test shouldSendPostRequest"; + final String expectedRequestBodyParamName = "request_body_param_name"; + final String expectedRequestBodyParamValue = "request_body_param_value"; + final String expectedRequestBody = expectedRequestBodyParamName + '=' + expectedRequestBodyParamValue; + + final MockWebServer server = new MockWebServer(); + server.enqueue(new MockResponse().setBody(expectedResponseBody)); + server.start(); + + final HttpUrl baseUrl = server.url("/testUrl"); + + final OAuthRequest request = new OAuthRequest(Verb.POST, baseUrl.toString()); + request.addBodyParameter(expectedRequestBodyParamName, expectedRequestBodyParamValue); + try (Response response = oAuthService.execute(request, null).get(30, TimeUnit.SECONDS)) { + assertEquals(expectedResponseBody, response.getBody()); + } + + final RecordedRequest recordedRequest = server.takeRequest(); + assertEquals("POST", recordedRequest.getMethod()); + assertEquals(expectedRequestBody, recordedRequest.getBody().readUtf8()); + assertEquals(HttpClient.DEFAULT_CONTENT_TYPE, recordedRequest.getHeader(HttpClient.CONTENT_TYPE)); + + server.shutdown(); + } + + @Test + public void shouldReadResponseStream() throws Exception { + final String expectedResponseBody = "response body for test shouldReadResponseStream"; + + final MockWebServer server = new MockWebServer(); + server.enqueue(new MockResponse().setBody(expectedResponseBody)); + server.start(); + + final HttpUrl baseUrl = server.url("/testUrl"); + + final OAuthRequest request = new OAuthRequest(Verb.GET, baseUrl.toString()); + try (Response response = oAuthService.execute(request, null).get(30, TimeUnit.SECONDS)) { + assertEquals(expectedResponseBody, StreamUtils.getStreamContents(response.getStream())); + } + + final RecordedRequest recordedRequest = server.takeRequest(); + assertEquals("GET", recordedRequest.getMethod()); + + server.shutdown(); + } + + @Test + public void shouldCallCallback() throws Exception { + final String expectedResponseBody = "response body for test shouldCallCallback"; + + final MockWebServer server = new MockWebServer(); + server.enqueue(new MockResponse().setBody(expectedResponseBody)); + server.start(); + + final HttpUrl baseUrl = server.url("/testUrl"); + + final OAuthRequest request = new OAuthRequest(Verb.GET, baseUrl.toString()); + + final TestCallback callback = new TestCallback(); + oAuthService.execute(request, callback).get(); + + assertEquals(expectedResponseBody, callback.getResponse().getBody()); + + server.shutdown(); + } + + @Test + public void shouldPassErrors() throws Exception { + + final MockWebServer server = new MockWebServer(); + server.enqueue(new MockResponse().setResponseCode(500)); + server.start(); + + final HttpUrl baseUrl = server.url("/testUrl"); + + final OAuthRequest request = new OAuthRequest(Verb.GET, baseUrl.toString()); + + final TestCallback callback = new TestCallback(); + try (Response response = oAuthService.execute(request, callback).get()) { + + assertEquals(500, response.getCode()); + assertEquals(500, callback.getResponse().getCode()); + } + + server.shutdown(); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/ObjectMother.java b/scribejava-core/src/test/java/com/github/scribejava/core/ObjectMother.java new file mode 100644 index 000000000..07e4081ec --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/ObjectMother.java @@ -0,0 +1,62 @@ +package com.github.scribejava.core; + +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Verb; + +public abstract class ObjectMother { + + public static OAuthRequest createSampleOAuthRequest() { + final OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com"); + request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456"); + request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, "AS#$^*@&"); + request.addOAuthParameter(OAuthConstants.CALLBACK, "http://example/callback"); + request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature"); + return request; + } + + public static OAuthRequest createSampleOAuthRequestPort80() { + final OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com:80"); + request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456"); + request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, "AS#$^*@&"); + request.addOAuthParameter(OAuthConstants.CALLBACK, "http://example/callback"); + request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature"); + return request; + } + + public static OAuthRequest createSampleOAuthRequestPort80v2() { + final OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com:80/test"); + request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456"); + request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, "AS#$^*@&"); + request.addOAuthParameter(OAuthConstants.CALLBACK, "http://example/callback"); + request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature"); + return request; + } + + public static OAuthRequest createSampleOAuthRequestPort8080() { + final OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com:8080"); + request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456"); + request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, "AS#$^*@&"); + request.addOAuthParameter(OAuthConstants.CALLBACK, "http://example/callback"); + request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature"); + return request; + } + + public static OAuthRequest createSampleOAuthRequestPort443() { + final OAuthRequest request = new OAuthRequest(Verb.GET, "https://example.com:443"); + request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456"); + request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, "AS#$^*@&"); + request.addOAuthParameter(OAuthConstants.CALLBACK, "http://example/callback"); + request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature"); + return request; + } + + public static OAuthRequest createSampleOAuthRequestPort443v2() { + final OAuthRequest request = new OAuthRequest(Verb.GET, "https://example.com:443/test"); + request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456"); + request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, "AS#$^*@&"); + request.addOAuthParameter(OAuthConstants.CALLBACK, "http://example/callback"); + request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature"); + return request; + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/base64/Base64Test.java b/scribejava-core/src/test/java/com/github/scribejava/core/base64/Base64Test.java new file mode 100644 index 000000000..4d345b77d --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/base64/Base64Test.java @@ -0,0 +1,213 @@ +package com.github.scribejava.core.base64; + +import java.io.UnsupportedEncodingException; +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; + +public class Base64Test { + + private Base64 java8Base64; + private Base64 commonsCodecBase64; + private Base64 jaxbBase64; + private Base64 jaxb230Base64; + private byte[] helloWorldBytes; + private byte[] helloWorldTwoLinesBytes; + private byte[] helloWorldTwoLinesAndNewLineBytes; + private byte[] helloWorldDifferentCharsBytes; + private byte[] bytes; + private byte[] allBytes; + + @Before + public void setUp() throws UnsupportedEncodingException { + helloWorldBytes = "Hello World".getBytes("UTF-8"); + helloWorldTwoLinesBytes = "Hello World\r\nNew Line2".getBytes("UTF-8"); + helloWorldTwoLinesAndNewLineBytes = "Hello World\r\nSecond Line\r\n".getBytes("UTF-8"); + helloWorldDifferentCharsBytes = ("`1234567890-=~!@#$%^&*()_+ёЁ\"№;:?qwertyuiop[]asdfghjkl;'zxcvbnm,./QWERTYUIOP" + + "{}|ASDFGHJKL:ZXCVBNM<>?йфяцычувскамепинртгоьшлбщдюзж.хэъ\\ЙФЯЦЫЧУВСКАМЕПИНРТГОЬШЛБЩДЮЗЖ,ХЭЪ/\r\t\f\'" + + "\b\n").getBytes("UTF-8"); + bytes = new byte[]{48, -126, 2, 118, 2, 1, 0, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 4, -126, + 2, 96, 48, -126, 2, 92, 2, 1, 0, 2, -127, -127, 0, -61, -48, -28, 16, -116, -58, 85, 42, -39, 54, 50, -119, + 18, 40, 17, 75, 51, -24, 113, -109, 38, 17, -18, 106, -60, -74, -97, 29, 82, 123, -128, -88, -34, 92, 112, + -57, 43, -101, 85, -47, 99, -16, 11, -95, 28, -46, 82, -104, -101, -29, -106, -106, -45, -80, 99, -93, 45, + -102, 107, 31, 32, -60, 13, -46, 102, 127, 81, 94, -98, -56, 117, 50, 21, 39, 5, -98, 26, -18, -30, -21, + 102, -78, -77, 20, 113, -55, 117, -87, -105, -10, -100, 90, -92, 31, 61, -68, -73, -121, -108, 42, 45, -10, + 21, 87, 118, -74, 71, -100, -37, 96, -24, 87, 102, 68, -95, -1, -14, 6, -20, -14, 32, -14, 33, -84, -123, + -65, 54, 3, 2, 3, 1, 0, 1, 2, -127, -128, 62, 115, -45, 41, 76, 28, -67, 113, 11, 17, -12, 16, 47, -112, 67, + -29, -66, 76, 118, 92, -66, 25, -99, -10, -61, -126, -109, 64, -32, -37, -82, -17, 44, -20, 66, -77, -29, + 62, -119, -94, 92, -61, 100, -110, 32, 5, 28, 126, -69, -55, 92, 112, 2, 88, 17, -113, 43, -82, 66, 88, 13, + 53, 58, 74, -65, 36, 45, 93, -63, -15, 125, -7, -44, -45, -51, -76, 86, 97, 54, -36, -49, -117, -18, 56, 54, + 78, 80, 119, -6, -75, 39, 16, 57, -125, -68, 42, 50, -114, 92, 6, 13, 30, -91, 53, -66, -19, -20, 88, 32, + -38, 36, 126, -119, -86, 47, -46, 37, 115, -49, -23, 125, -61, 75, 37, 70, 92, -122, -79, 2, 65, 0, -11, + -105, 91, 105, -73, 54, 97, 96, -87, -16, -15, -73, 15, 31, -80, -96, -74, -53, -54, 53, -17, -9, 39, 62, + 58, 51, 68, 107, 86, 111, -62, -48, -125, 117, 66, 111, -55, 27, 56, 81, -50, 96, -47, -102, -50, -83, -52, + -17, -20, 3, -42, -94, 11, 23, 104, 127, 29, -25, 32, 43, -41, -112, -83, -99, 2, 65, 0, -52, 29, 122, 9, + 49, -14, -118, 110, -79, 107, 76, -88, 4, -49, 40, 32, 59, 88, 45, -71, 62, 78, 93, -121, -123, 123, 3, 4, + 111, -112, 27, 12, -115, -123, 125, 39, 54, 96, -2, -46, 30, 40, -4, -119, 13, -121, 118, -23, 1, -83, -76, + -26, -117, -86, -79, -121, 113, -26, 33, 30, 124, 35, -16, 31, 2, 65, 0, -47, -113, 111, -81, 75, 104, -103, + -69, 20, 7, -57, 25, -65, 75, -7, 57, -118, 1, 102, -16, -109, 108, -64, 13, -73, 55, -37, -32, 3, -121, + -90, 34, -86, -87, -70, 33, 12, -25, -81, 45, 14, -1, 74, -101, -32, 84, 41, -107, 104, 60, -10, 62, -101, + 92, 68, 12, -124, 5, -98, 76, 10, -53, 39, 121, 2, 64, 7, 106, 102, -67, -96, -57, -20, 9, -101, 126, -121, + 121, 111, 59, 75, 124, -24, 75, 10, -42, 57, 18, 69, -55, -97, -86, -39, 112, 54, -47, 104, 122, 43, 70, 23, + 70, -18, 109, -43, -76, 50, -114, 80, -90, 118, 12, 94, -32, -106, 68, 6, 87, 125, -23, -124, -85, -92, 18, + -75, 79, 83, 57, 71, 7, 2, 64, 73, -64, -3, 78, -90, -122, -64, -99, -29, -71, 75, 21, -74, -24, -43, -37, + 116, -89, 31, -115, -30, 50, 8, 23, 79, -71, -68, -39, 36, -23, 60, 102, -90, -42, 19, -33, -102, -85, -74, + 103, 73, -30, 120, -15, 104, -9, 110, -24, -127, 14, -57, -44, 67, 9, 80, 120, 42, 94, 107, -81, -109, 101, + -1, 91}; + + allBytes = new byte[]{-128, -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, -116, -115, -114, + -113, -112, -111, -110, -109, -108, -107, -106, -105, -104, -103, -102, -101, -100, -99, -98, -97, -96, -95, + -94, -93, -92, -91, -90, -89, -88, -87, -86, -85, -84, -83, -82, -81, -80, -79, -78, -77, -76, -75, -74, + -73, -72, -71, -70, -69, -68, -67, -66, -65, -64, -63, -62, -61, -60, -59, -58, -57, -56, -55, -54, -53, + -52, -51, -50, -49, -48, -47, -46, -45, -44, -43, -42, -41, -40, -39, -38, -37, -36, -35, -34, -33, -32, + -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, + -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 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}; + + java8Base64 = new Java8Base64(); + commonsCodecBase64 = new CommonsCodecBase64(); + jaxbBase64 = new JaxbBase64(); + jaxb230Base64 = new Jaxb230Base64(); + } + + @Test + public void allImplementationsAreAvailable() { + assertTrue(Java8Base64.isAvailable()); + assertTrue(CommonsCodecBase64.isAvailable()); + assertTrue(JaxbBase64.isAvailable()); + assertTrue(Jaxb230Base64.isAvailable()); + } + + @Test + public void testEncode() { + final String helloWorldEncoded = "SGVsbG8gV29ybGQ="; + final String helloWorldTwoLinesEncoded = "SGVsbG8gV29ybGQNCk5ldyBMaW5lMg=="; + final String helloWorldTwoLinesAndNewLineEncoded = "SGVsbG8gV29ybGQNClNlY29uZCBMaW5lDQo="; + final String helloWorldDifferentCharsEncoded = "YDEyMzQ1Njc4OTAtPX4hQCMkJV4mKigpXyvRkdCBIuKEljs6P3F3ZXJ0eXVpb3B" + + "bXWFzZGZnaGprbDsnenhjdmJubSwuL1FXRVJUWVVJT1B7fXxBU0RGR0hKS0w6WlhDVkJOTTw+P9C50YTRj9GG0YvRh9GD0LLRgdC" + + "60LDQvNC10L/QuNC90YDRgtCz0L7RjNGI0LvQsdGJ0LTRjtC30LYu0YXRjdGKXNCZ0KTQr9Cm0KvQp9Cj0JLQodCa0JDQnNCV0J/" + + "QmNCd0KDQotCT0J7QrNCo0JvQkdCp0JTQrtCX0JYs0KXQrdCqLw0JDCcICg=="; + final String str = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMPQ5BCMxlUq2TYy" + + "iRIoEUsz6HGTJhHuasS2nx1Se4Co3lxwxyubVdFj8AuhHNJSmJvjlpbTsGOjLZpr" + + "HyDEDdJmf1Fensh1MhUnBZ4a7uLrZrKzFHHJdamX9pxapB89vLeHlCot9hVXdrZH" + + "nNtg6FdmRKH/8gbs8iDyIayFvzYDAgMBAAECgYA+c9MpTBy9cQsR9BAvkEPjvkx2" + + "XL4ZnfbDgpNA4Nuu7yzsQrPjPomiXMNkkiAFHH67yVxwAlgRjyuuQlgNNTpKvyQt" + + "XcHxffnU0820VmE23M+L7jg2TlB3+rUnEDmDvCoyjlwGDR6lNb7t7Fgg2iR+iaov" + + "0iVzz+l9w0slRlyGsQJBAPWXW2m3NmFgqfDxtw8fsKC2y8o17/cnPjozRGtWb8LQ" + + "g3VCb8kbOFHOYNGazq3M7+wD1qILF2h/HecgK9eQrZ0CQQDMHXoJMfKKbrFrTKgE" + + "zyggO1gtuT5OXYeFewMEb5AbDI2FfSc2YP7SHij8iQ2HdukBrbTmi6qxh3HmIR58" + + "I/AfAkEA0Y9vr0tombsUB8cZv0v5OYoBZvCTbMANtzfb4AOHpiKqqbohDOevLQ7/" + + "SpvgVCmVaDz2PptcRAyEBZ5MCssneQJAB2pmvaDH7Ambfod5bztLfOhLCtY5EkXJ" + + "n6rZcDbRaHorRhdG7m3VtDKOUKZ2DF7glkQGV33phKukErVPUzlHBwJAScD9TqaG" + + "wJ3juUsVtujV23SnH43iMggXT7m82STpPGam1hPfmqu2Z0niePFo927ogQ7H1EMJ" + + "UHgqXmuvk2X/Ww=="; + + final String allBytesStr = "gIGCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnp+goaKjpKWmp6ipqqusra6vsLGys7S1tre4ubq7vL2" + + "+v8DBwsPExcbHyMnKy8zNzs/Q0dLT1NXW19jZ2tvc3d7f4OHi4+Tl5ufo6err7O3u7/Dx8vP09fb3+Pn6+/z9/v8AAQIDBAUGBwg" + + "JCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4/QEFCQ0RFRkdISUpLTE1OT1BRUlN" + + "UVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+fw=="; + + assertEquals(helloWorldEncoded, java8Base64.internalEncode(helloWorldBytes)); + assertEquals(helloWorldTwoLinesEncoded, java8Base64.internalEncode(helloWorldTwoLinesBytes)); + assertEquals(helloWorldTwoLinesAndNewLineEncoded, + java8Base64.internalEncode(helloWorldTwoLinesAndNewLineBytes)); + assertEquals(helloWorldDifferentCharsEncoded, java8Base64.internalEncode(helloWorldDifferentCharsBytes)); + assertEquals(str, java8Base64.internalEncode(bytes)); + assertEquals(allBytesStr, java8Base64.internalEncode(allBytes)); + + assertEquals(helloWorldEncoded, commonsCodecBase64.internalEncode(helloWorldBytes)); + assertEquals(helloWorldTwoLinesEncoded, commonsCodecBase64.internalEncode(helloWorldTwoLinesBytes)); + assertEquals(helloWorldTwoLinesAndNewLineEncoded, + commonsCodecBase64.internalEncode(helloWorldTwoLinesAndNewLineBytes)); + assertEquals(helloWorldDifferentCharsEncoded, commonsCodecBase64.internalEncode(helloWorldDifferentCharsBytes)); + assertEquals(str, commonsCodecBase64.internalEncode(bytes)); + assertEquals(allBytesStr, commonsCodecBase64.internalEncode(allBytes)); + + assertEquals(helloWorldEncoded, jaxbBase64.internalEncode(helloWorldBytes)); + assertEquals(helloWorldTwoLinesEncoded, jaxbBase64.internalEncode(helloWorldTwoLinesBytes)); + assertEquals(helloWorldTwoLinesAndNewLineEncoded, jaxbBase64.internalEncode(helloWorldTwoLinesAndNewLineBytes)); + assertEquals(helloWorldDifferentCharsEncoded, jaxbBase64.internalEncode(helloWorldDifferentCharsBytes)); + assertEquals(str, jaxbBase64.internalEncode(bytes)); + assertEquals(allBytesStr, jaxbBase64.internalEncode(allBytes)); + + assertEquals(helloWorldEncoded, jaxb230Base64.internalEncode(helloWorldBytes)); + assertEquals(helloWorldTwoLinesEncoded, jaxb230Base64.internalEncode(helloWorldTwoLinesBytes)); + assertEquals(helloWorldTwoLinesAndNewLineEncoded, + jaxb230Base64.internalEncode(helloWorldTwoLinesAndNewLineBytes)); + assertEquals(helloWorldDifferentCharsEncoded, jaxb230Base64.internalEncode(helloWorldDifferentCharsBytes)); + assertEquals(str, jaxb230Base64.internalEncode(bytes)); + assertEquals(allBytesStr, jaxb230Base64.internalEncode(allBytes)); + } + + @Test + public void testEncodeUrlWithoutPadding() { + final String helloWorldEncoded = "SGVsbG8gV29ybGQ"; + final String helloWorldTwoLinesEncoded = "SGVsbG8gV29ybGQNCk5ldyBMaW5lMg"; + final String helloWorldTwoLinesAndNewLineEncoded = "SGVsbG8gV29ybGQNClNlY29uZCBMaW5lDQo"; + final String helloWorldDifferentCharsEncoded = "YDEyMzQ1Njc4OTAtPX4hQCMkJV4mKigpXyvRkdCBIuKEljs6P3F3ZXJ0eXVpb3B" + + "bXWFzZGZnaGprbDsnenhjdmJubSwuL1FXRVJUWVVJT1B7fXxBU0RGR0hKS0w6WlhDVkJOTTw-P9C50YTRj9GG0YvRh9GD0LLRgdC" + + "60LDQvNC10L_QuNC90YDRgtCz0L7RjNGI0LvQsdGJ0LTRjtC30LYu0YXRjdGKXNCZ0KTQr9Cm0KvQp9Cj0JLQodCa0JDQnNCV0J_" + + "QmNCd0KDQotCT0J7QrNCo0JvQkdCp0JTQrtCX0JYs0KXQrdCqLw0JDCcICg"; + final String str = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMPQ5BCMxlUq2TYy" + + "iRIoEUsz6HGTJhHuasS2nx1Se4Co3lxwxyubVdFj8AuhHNJSmJvjlpbTsGOjLZpr" + + "HyDEDdJmf1Fensh1MhUnBZ4a7uLrZrKzFHHJdamX9pxapB89vLeHlCot9hVXdrZH" + + "nNtg6FdmRKH_8gbs8iDyIayFvzYDAgMBAAECgYA-c9MpTBy9cQsR9BAvkEPjvkx2" + + "XL4ZnfbDgpNA4Nuu7yzsQrPjPomiXMNkkiAFHH67yVxwAlgRjyuuQlgNNTpKvyQt" + + "XcHxffnU0820VmE23M-L7jg2TlB3-rUnEDmDvCoyjlwGDR6lNb7t7Fgg2iR-iaov" + + "0iVzz-l9w0slRlyGsQJBAPWXW2m3NmFgqfDxtw8fsKC2y8o17_cnPjozRGtWb8LQ" + + "g3VCb8kbOFHOYNGazq3M7-wD1qILF2h_HecgK9eQrZ0CQQDMHXoJMfKKbrFrTKgE" + + "zyggO1gtuT5OXYeFewMEb5AbDI2FfSc2YP7SHij8iQ2HdukBrbTmi6qxh3HmIR58" + + "I_AfAkEA0Y9vr0tombsUB8cZv0v5OYoBZvCTbMANtzfb4AOHpiKqqbohDOevLQ7_" + + "SpvgVCmVaDz2PptcRAyEBZ5MCssneQJAB2pmvaDH7Ambfod5bztLfOhLCtY5EkXJ" + + "n6rZcDbRaHorRhdG7m3VtDKOUKZ2DF7glkQGV33phKukErVPUzlHBwJAScD9TqaG" + + "wJ3juUsVtujV23SnH43iMggXT7m82STpPGam1hPfmqu2Z0niePFo927ogQ7H1EMJ" + + "UHgqXmuvk2X_Ww"; + + final String allBytesStr = "gIGCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnp-goaKjpKWmp6ipqqusra6vsLGys7S1tre4ubq7vL2" + + "-v8DBwsPExcbHyMnKy8zNzs_Q0dLT1NXW19jZ2tvc3d7f4OHi4-Tl5ufo6err7O3u7_Dx8vP09fb3-Pn6-_z9_v8AAQIDBAUGBwg" + + "JCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4_QEFCQ0RFRkdISUpLTE1OT1BRUlN" + + "UVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1-fw"; + + assertEquals(helloWorldEncoded, java8Base64.internalEncodeUrlWithoutPadding(helloWorldBytes)); + assertEquals(helloWorldTwoLinesEncoded, java8Base64.internalEncodeUrlWithoutPadding(helloWorldTwoLinesBytes)); + assertEquals(helloWorldTwoLinesAndNewLineEncoded, + java8Base64.internalEncodeUrlWithoutPadding(helloWorldTwoLinesAndNewLineBytes)); + assertEquals(helloWorldDifferentCharsEncoded, + java8Base64.internalEncodeUrlWithoutPadding(helloWorldDifferentCharsBytes)); + assertEquals(str, java8Base64.internalEncodeUrlWithoutPadding(bytes)); + assertEquals(allBytesStr, java8Base64.internalEncodeUrlWithoutPadding(allBytes)); + + assertEquals(helloWorldEncoded, commonsCodecBase64.internalEncodeUrlWithoutPadding(helloWorldBytes)); + assertEquals(helloWorldTwoLinesEncoded, + commonsCodecBase64.internalEncodeUrlWithoutPadding(helloWorldTwoLinesBytes)); + assertEquals(helloWorldTwoLinesAndNewLineEncoded, + commonsCodecBase64.internalEncodeUrlWithoutPadding(helloWorldTwoLinesAndNewLineBytes)); + assertEquals(helloWorldDifferentCharsEncoded, + commonsCodecBase64.internalEncodeUrlWithoutPadding(helloWorldDifferentCharsBytes)); + assertEquals(str, commonsCodecBase64.internalEncodeUrlWithoutPadding(bytes)); + assertEquals(allBytesStr, commonsCodecBase64.internalEncodeUrlWithoutPadding(allBytes)); + + assertEquals(helloWorldEncoded, jaxbBase64.internalEncodeUrlWithoutPadding(helloWorldBytes)); + assertEquals(helloWorldTwoLinesEncoded, jaxbBase64.internalEncodeUrlWithoutPadding(helloWorldTwoLinesBytes)); + assertEquals(helloWorldTwoLinesAndNewLineEncoded, + jaxbBase64.internalEncodeUrlWithoutPadding(helloWorldTwoLinesAndNewLineBytes)); + assertEquals(helloWorldDifferentCharsEncoded, + jaxbBase64.internalEncodeUrlWithoutPadding(helloWorldDifferentCharsBytes)); + assertEquals(str, jaxbBase64.internalEncodeUrlWithoutPadding(bytes)); + assertEquals(allBytesStr, jaxbBase64.internalEncodeUrlWithoutPadding(allBytes)); + + assertEquals(helloWorldEncoded, jaxb230Base64.internalEncodeUrlWithoutPadding(helloWorldBytes)); + assertEquals(helloWorldTwoLinesEncoded, jaxb230Base64.internalEncodeUrlWithoutPadding(helloWorldTwoLinesBytes)); + assertEquals(helloWorldTwoLinesAndNewLineEncoded, + jaxb230Base64.internalEncodeUrlWithoutPadding(helloWorldTwoLinesAndNewLineBytes)); + assertEquals(helloWorldDifferentCharsEncoded, + jaxb230Base64.internalEncodeUrlWithoutPadding(helloWorldDifferentCharsBytes)); + assertEquals(str, jaxb230Base64.internalEncodeUrlWithoutPadding(bytes)); + assertEquals(allBytesStr, jaxb230Base64.internalEncodeUrlWithoutPadding(allBytes)); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/extractors/BaseStringExtractorTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/extractors/BaseStringExtractorTest.java new file mode 100644 index 000000000..89865a637 --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/extractors/BaseStringExtractorTest.java @@ -0,0 +1,115 @@ +package com.github.scribejava.core.extractors; + +import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Test; +import com.github.scribejava.core.ObjectMother; +import com.github.scribejava.core.exceptions.OAuthParametersMissingException; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Verb; +import static org.junit.Assert.assertThrows; +import org.junit.function.ThrowingRunnable; + +public class BaseStringExtractorTest { + + private BaseStringExtractorImpl extractor; + private OAuthRequest request; + private OAuthRequest requestPort80; + private OAuthRequest requestPort80v2; + private OAuthRequest requestPort8080; + private OAuthRequest requestPort443; + private OAuthRequest requestPort443v2; + + @Before + public void setUp() { + request = ObjectMother.createSampleOAuthRequest(); + requestPort80 = ObjectMother.createSampleOAuthRequestPort80(); + requestPort80v2 = ObjectMother.createSampleOAuthRequestPort80v2(); + requestPort8080 = ObjectMother.createSampleOAuthRequestPort8080(); + requestPort443 = ObjectMother.createSampleOAuthRequestPort443(); + requestPort443v2 = ObjectMother.createSampleOAuthRequestPort443v2(); + extractor = new BaseStringExtractorImpl(); + } + + @Test + public void shouldExtractBaseStringFromOAuthRequest() { + final String expected = "GET&http%3A%2F%2Fexample.com&oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback" + + "%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature" + + "%26oauth_timestamp%3D123456"; + final String baseString = extractor.extract(request); + assertEquals(expected, baseString); + } + + @Test + public void shouldExcludePort80() { + final String expected = "GET&http%3A%2F%2Fexample.com&oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback" + + "%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature" + + "%26oauth_timestamp%3D123456"; + final String baseString = extractor.extract(requestPort80); + assertEquals(expected, baseString); + } + + @Test + public void shouldExcludePort80v2() { + final String expected = "GET&http%3A%2F%2Fexample.com%2Ftest&oauth_callback%3Dhttp%253A%252F%252Fexample" + + "%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature" + + "%3DOAuth-Signature%26oauth_timestamp%3D123456"; + final String baseString = extractor.extract(requestPort80v2); + assertEquals(expected, baseString); + } + + @Test + public void shouldIncludePort8080() { + final String expected = "GET&http%3A%2F%2Fexample.com%3A8080&oauth_callback%3Dhttp%253A%252F%252Fexample" + + "%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature" + + "%3DOAuth-Signature%26oauth_timestamp%3D123456"; + final String baseString = extractor.extract(requestPort8080); + assertEquals(expected, baseString); + } + + @Test + public void shouldExcludePort443() { + final String expected = "GET&https%3A%2F%2Fexample.com&oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback" + + "%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature" + + "%26oauth_timestamp%3D123456"; + final String baseString = extractor.extract(requestPort443); + assertEquals(expected, baseString); + } + + @Test + public void shouldExcludePort443v2() { + final String expected = "GET&https%3A%2F%2Fexample.com%2Ftest&oauth_callback%3Dhttp%253A%252F%252Fexample" + + "%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature" + + "%3DOAuth-Signature%26oauth_timestamp%3D123456"; + final String baseString = extractor.extract(requestPort443v2); + assertEquals(expected, baseString); + } + + public void shouldThrowExceptionIfRquestIsNull() { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.extract(null); + } + }); + } + + public void shouldThrowExceptionIfRquestHasNoOAuthParameters() { + final OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com"); + assertThrows(OAuthParametersMissingException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.extract(request); + } + }); + } + + @Test + public void shouldProperlyEncodeSpaces() { + final String expected = "GET&http%3A%2F%2Fexample.com&body%3Dthis%2520param%2520has%2520whitespace" + + "%26oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback%26oauth_consumer_key" + + "%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature%26oauth_timestamp%3D123456"; + request.addBodyParameter("body", "this param has whitespace"); + assertEquals(expected, extractor.extract(request)); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/extractors/HeaderExtractorTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/extractors/HeaderExtractorTest.java new file mode 100644 index 000000000..b515908c8 --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/extractors/HeaderExtractorTest.java @@ -0,0 +1,66 @@ +package com.github.scribejava.core.extractors; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertThrows; +import org.junit.Before; +import org.junit.Test; +import com.github.scribejava.core.exceptions.OAuthParametersMissingException; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.ObjectMother; +import org.junit.function.ThrowingRunnable; + +public class HeaderExtractorTest { + + private HeaderExtractorImpl extractor; + private OAuthRequest request; + + @Before + public void setUp() { + request = ObjectMother.createSampleOAuthRequest(); + extractor = new HeaderExtractorImpl(); + } + + @Test + public void shouldExtractStandardHeader() { + final String header = extractor.extract(request); + final String oauth = "OAuth "; + final String callback = "oauth_callback=\"http%3A%2F%2Fexample%2Fcallback\""; + final String signature = "oauth_signature=\"OAuth-Signature\""; + final String key = "oauth_consumer_key=\"AS%23%24%5E%2A%40%26\""; + final String timestamp = "oauth_timestamp=\"123456\""; + + assertTrue(header.startsWith(oauth)); + assertTrue(header.contains(callback)); + assertTrue(header.contains(signature)); + assertTrue(header.contains(key)); + assertTrue(header.contains(timestamp)); + // Assert that header only contains the checked elements above and nothing else + assertEquals(", , , ", + header.replaceFirst(oauth, "") + .replaceFirst(callback, "") + .replaceFirst(signature, "") + .replaceFirst(key, "") + .replaceFirst(timestamp, "")); + } + + public void shouldExceptionIfRequestIsNull() { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.extract(null); + } + }); + } + + public void shouldExceptionIfRequestHasNoOAuthParams() { + final OAuthRequest emptyRequest = new OAuthRequest(Verb.GET, "http://example.com"); + assertThrows(OAuthParametersMissingException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.extract(emptyRequest); + } + }); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/extractors/OAuth1AccessTokenExtractorTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/extractors/OAuth1AccessTokenExtractorTest.java new file mode 100644 index 000000000..b62d9bf1e --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/extractors/OAuth1AccessTokenExtractorTest.java @@ -0,0 +1,120 @@ +package com.github.scribejava.core.extractors; + +import com.github.scribejava.core.model.Response; +import org.junit.Before; +import org.junit.Test; +import com.github.scribejava.core.exceptions.OAuthException; +import com.github.scribejava.core.model.OAuth1Token; + +import java.io.IOException; +import java.util.Collections; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import org.junit.function.ThrowingRunnable; + +public class OAuth1AccessTokenExtractorTest { + + private OAuth1AccessTokenExtractor extractor; + + @Before + public void setUp() { + extractor = OAuth1AccessTokenExtractor.instance(); + } + + @Test + public void shouldExtractTokenFromOAuthStandardResponse() throws IOException { + final String responseBody = "oauth_token=hh5s93j4hdidpola&oauth_token_secret=hdhd0244k9j7ao03"; + final OAuth1Token extracted; + try (Response response = ok(responseBody)) { + extracted = extractor.extract(response); + } + assertEquals("hh5s93j4hdidpola", extracted.getToken()); + assertEquals("hdhd0244k9j7ao03", extracted.getTokenSecret()); + } + + @Test + public void shouldExtractTokenFromInvertedOAuthStandardResponse() throws IOException { + final String responseBody = "oauth_token_secret=hh5s93j4hdidpola&oauth_token=hdhd0244k9j7ao03"; + final OAuth1Token extracted; + try (Response response = ok(responseBody)) { + extracted = extractor.extract(response); + } + assertEquals("hh5s93j4hdidpola", extracted.getTokenSecret()); + assertEquals("hdhd0244k9j7ao03", extracted.getToken()); + } + + @Test + public void shouldExtractTokenFromResponseWithCallbackConfirmed() throws IOException { + final String responseBody = "oauth_token=hh5s93j4hdidpola&oauth_token_secret=hdhd0244k9j7ao03" + + "&callback_confirmed=true"; + final OAuth1Token extracted; + try (Response response = ok(responseBody)) { + extracted = extractor.extract(response); + } + assertEquals("hh5s93j4hdidpola", extracted.getToken()); + assertEquals("hdhd0244k9j7ao03", extracted.getTokenSecret()); + } + + @Test + public void shouldExtractTokenWithEmptySecret() throws IOException { + final String responseBody = "oauth_token=hh5s93j4hdidpola&oauth_token_secret="; + final OAuth1Token extracted; + try (Response response = ok(responseBody)) { + extracted = extractor.extract(response); + } + assertEquals("hh5s93j4hdidpola", extracted.getToken()); + assertEquals("", extracted.getTokenSecret()); + } + + public void shouldThrowExceptionIfTokenIsAbsent() throws IOException { + final String responseBody = "oauth_secret=hh5s93j4hdidpola&callback_confirmed=true"; + try (Response response = ok(responseBody)) { + assertThrows(OAuthException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.extract(response); + } + }); + } + } + + public void shouldThrowExceptionIfSecretIsAbsent() throws IOException { + final String responseBody = "oauth_token=hh5s93j4hdidpola&callback_confirmed=true"; + try (Response response = ok(responseBody)) { + assertThrows(OAuthException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.extract(response); + } + }); + } + } + + public void shouldThrowExceptionIfResponseIsNull() throws IOException { + try (Response response = ok(null)) { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.extract(response); + } + }); + } + } + + public void shouldThrowExceptionIfResponseIsEmptyString() throws IOException { + final String responseBody = ""; + try (Response response = ok(responseBody)) { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.extract(response); + } + }); + } + } + + private static Response ok(String body) { + return new Response(200, /* message */ null, /* headers */ Collections.emptyMap(), body); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/extractors/OAuth2AccessTokenExtractorTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/extractors/OAuth2AccessTokenExtractorTest.java new file mode 100644 index 000000000..4f71c011d --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/extractors/OAuth2AccessTokenExtractorTest.java @@ -0,0 +1,129 @@ +package com.github.scribejava.core.extractors; + +import com.github.scribejava.core.model.Response; +import org.junit.Before; +import org.junit.Test; +import com.github.scribejava.core.exceptions.OAuthException; +import com.github.scribejava.core.model.OAuth2AccessToken; + +import java.io.IOException; +import java.util.Collections; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import org.junit.function.ThrowingRunnable; + +public class OAuth2AccessTokenExtractorTest { + + private OAuth2AccessTokenExtractor extractor; + + @Before + public void setUp() { + extractor = OAuth2AccessTokenExtractor.instance(); + } + + @Test + public void shouldExtractTokenFromOAuthStandardResponse() throws IOException { + final String responseBody = "access_token=166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159" + + "|RsXNdKrpxg8L6QNLWcs2TVTmcaE"; + final OAuth2AccessToken extracted; + try (Response response = ok(responseBody)) { + extracted = extractor.extract(response); + } + assertEquals("166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE", + extracted.getAccessToken()); + } + + @Test + public void shouldExtractTokenFromResponseWithExpiresParam() throws IOException { + final String responseBody = "access_token=166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159" + + "|RsXNdKrpxg8L6QNLWcs2TVTmcaE&expires_in=5108"; + final OAuth2AccessToken extracted; + try (Response response = ok(responseBody)) { + extracted = extractor.extract(response); + } + assertEquals("166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE", + extracted.getAccessToken()); + assertEquals(Integer.valueOf(5108), extracted.getExpiresIn()); + } + + @Test + public void shouldExtractTokenFromResponseWithExpiresAndRefreshParam() throws IOException { + final String responseBody = "access_token=166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159" + + "|RsXNdKrpxg8L6QNLWcs2TVTmcaE&expires_in=5108&token_type=bearer&refresh_token=166942940015970"; + final OAuth2AccessToken extracted; + try (Response response = ok(responseBody)) { + extracted = extractor.extract(response); + } + assertEquals("166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE", + extracted.getAccessToken()); + assertEquals(Integer.valueOf(5108), extracted.getExpiresIn()); + assertEquals("bearer", extracted.getTokenType()); + assertEquals("166942940015970", extracted.getRefreshToken()); + } + + @Test + public void shouldExtractTokenFromResponseWithManyParameters() throws IOException { + final String responseBody = "access_token=foo1234&other_stuff=yeah_we_have_this_too&number=42"; + final OAuth2AccessToken extracted; + try (Response response = ok(responseBody)) { + extracted = extractor.extract(response); + } + assertEquals("foo1234", extracted.getAccessToken()); + } + + public void shouldThrowExceptionIfErrorResponse() throws IOException { + final String responseBody = ""; + try (Response response = error(responseBody)) { + assertThrows(OAuthException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.extract(response); + } + }); + } + } + + public void shouldThrowExceptionIfTokenIsAbsent() throws IOException { + final String responseBody = "&expires=5108"; + try (Response response = ok(responseBody)) { + assertThrows(OAuthException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.extract(response); + } + }); + } + } + + public void shouldThrowExceptionIfResponseIsNull() throws IOException { + try (Response response = ok(null)) { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.extract(response); + } + }); + } + } + + public void shouldThrowExceptionIfResponseIsEmptyString() throws IOException { + final String responseBody = ""; + try (Response response = ok(responseBody)) { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.extract(response); + } + }); + } + } + + private static Response ok(String body) { + return new Response(200, /* message */ null, /* headers */ Collections.emptyMap(), body); + } + + private static Response error(String body) { + return new Response(400, /* message */ null, /* headers */ Collections.emptyMap(), body); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/extractors/OAuth2AccessTokenJsonExtractorTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/extractors/OAuth2AccessTokenJsonExtractorTest.java new file mode 100644 index 000000000..6628d1d9b --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/extractors/OAuth2AccessTokenJsonExtractorTest.java @@ -0,0 +1,126 @@ +package com.github.scribejava.core.extractors; + +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuth2AccessTokenErrorResponse; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.oauth2.OAuth2Error; +import org.junit.Test; + +import java.io.IOException; +import java.util.Collections; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import org.junit.function.ThrowingRunnable; + +public class OAuth2AccessTokenJsonExtractorTest { + + private final OAuth2AccessTokenJsonExtractor extractor = OAuth2AccessTokenJsonExtractor.instance(); + + @Test + public void shouldParseResponse() throws IOException { + final String responseBody = "{ \"access_token\":\"I0122HHJKLEM21F3WLPYHDKGKZULAUO4SGMV3ABKFTDT3T3X\", " + + "\"token_type\":\"example\"}"; + final OAuth2AccessToken token; + try (Response response = ok(responseBody)) { + token = extractor.extract(response); + } + assertEquals("I0122HHJKLEM21F3WLPYHDKGKZULAUO4SGMV3ABKFTDT3T3X", token.getAccessToken()); + } + + @Test + public void shouldParseScopeFromResponse() throws IOException { + final String responseBody = "{ \"access_token\":\"I0122HHJKLEM21F3WLPYHDKGKZULAUO4SGMV3ABKFTDT3T4X\", " + + "\"token_type\":\"example\"," + + "\"scope\":\"s1\"}"; + final OAuth2AccessToken token; + try (Response response = ok(responseBody)) { + token = extractor.extract(response); + } + assertEquals("I0122HHJKLEM21F3WLPYHDKGKZULAUO4SGMV3ABKFTDT3T4X", token.getAccessToken()); + assertEquals("s1", token.getScope()); + + final String responseBody2 = "{ \"access_token\":\"I0122HHJKLEM21F3WLPYHDKGKZULAUO4SGMV3ABKFTDT3T5X\", " + + "\"token_type\":\"example\"," + + "\"scope\":\"s1 s2\"}"; + final OAuth2AccessToken token2; + try (Response response = ok(responseBody2)) { + token2 = extractor.extract(response); + } + assertEquals("I0122HHJKLEM21F3WLPYHDKGKZULAUO4SGMV3ABKFTDT3T5X", token2.getAccessToken()); + assertEquals("s1 s2", token2.getScope()); + + final String responseBody3 = "{ \"access_token\":\"I0122HHJKLEM21F3WLPYHDKGKZULAUO4SGMV3ABKFTDT3T6X\", " + + "\"token_type\":\"example\"," + + "\"scope\":\"s3 s4\", " + + "\"refresh_token\":\"refresh_token1\"}"; + final OAuth2AccessToken token3; + try (Response response = ok(responseBody3)) { + token3 = extractor.extract(response); + } + assertEquals("I0122HHJKLEM21F3WLPYHDKGKZULAUO4SGMV3ABKFTDT3T6X", token3.getAccessToken()); + assertEquals("s3 s4", token3.getScope()); + assertEquals("refresh_token1", token3.getRefreshToken()); + } + + public void shouldThrowExceptionIfForNullParameters() throws IOException { + try (Response response = ok(null)) { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.extract(response); + } + }); + } + } + + public void shouldThrowExceptionIfForEmptyStrings() throws IOException { + final String responseBody = ""; + try (Response response = ok(responseBody)) { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.extract(response); + } + }); + } + } + + @Test + public void shouldThrowExceptionIfResponseIsError() throws IOException { + final String responseBody = "{" + + "\"error_description\":\"unknown, invalid, or expired refresh token\"," + + "\"error\":\"invalid_grant\"" + + "}"; + try (Response response = error(responseBody)) { + final OAuth2AccessTokenErrorResponse oaer = assertThrows(OAuth2AccessTokenErrorResponse.class, + new ThrowingRunnable() { + @Override + public void run() throws Throwable { + extractor.extract(response); + } + }); + assertEquals(OAuth2Error.INVALID_GRANT, oaer.getError()); + assertEquals("unknown, invalid, or expired refresh token", oaer.getErrorDescription()); + } + } + + @Test + public void testEscapedJsonInResponse() throws IOException { + final String responseBody = "{ \"access_token\":\"I0122HKLEM2\\/MV3ABKFTDT3T5X\"," + + "\"token_type\":\"example\"}"; + final OAuth2AccessToken token; + try (Response response = ok(responseBody)) { + token = extractor.extract(response); + } + assertEquals("I0122HKLEM2/MV3ABKFTDT3T5X", token.getAccessToken()); + } + + private static Response ok(String body) { + return new Response(200, /* message */ null, /* headers */ Collections.emptyMap(), body); + } + + private static Response error(String body) { + return new Response(400, /* message */ null, /* headers */ Collections.emptyMap(), body); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/httpclient/jdk/JDKHttpClientTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/httpclient/jdk/JDKHttpClientTest.java new file mode 100644 index 000000000..6ac1070fa --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/httpclient/jdk/JDKHttpClientTest.java @@ -0,0 +1,12 @@ +package com.github.scribejava.core.httpclient.jdk; + +import com.github.scribejava.core.AbstractClientTest; +import com.github.scribejava.core.httpclient.HttpClient; + +public class JDKHttpClientTest extends AbstractClientTest { + + @Override + protected HttpClient createNewClient() { + return new JDKHttpClient(); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/httpclient/multipart/MultipartUtilsTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/httpclient/multipart/MultipartUtilsTest.java new file mode 100644 index 000000000..c726dd9a7 --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/httpclient/multipart/MultipartUtilsTest.java @@ -0,0 +1,353 @@ +package com.github.scribejava.core.httpclient.multipart; + +import com.github.scribejava.core.httpclient.HttpClient; +import java.io.IOException; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; +import org.junit.Test; +import org.junit.function.ThrowingRunnable; + +public class MultipartUtilsTest { + + @Test + public void testEmptyMultipartPayload() throws IOException { + final MultipartPayload mP = new MultipartPayload(); + + final StringBuilder headersString = new StringBuilder(); + for (Map.Entry header : mP.getHeaders().entrySet()) { + headersString.append(header.getKey()) + .append(": ") + .append(header.getValue()) + .append("\r\n"); + } + + assertEquals("Content-Type: multipart/form-data; boundary=\"" + mP.getBoundary() + "\"\r\n", + headersString.toString()); + + assertEquals("", MultipartUtils.getPayload(mP).toString()); + } + + @Test + public void testSimpleMultipartPayload() throws IOException { + final Map headers = new LinkedHashMap<>(); + headers.put("X-Header", "X-Value"); + headers.put("Content-Disposition", "Content-Disposition-Value"); + final MultipartPayload mP = new MultipartPayload("mixed", "simple boundary", headers); + mP.setPreamble("This is the preamble. It is to be ignored, though it\n" + + "is a handy place for composition agents to include an\n" + + "explanatory note to non-MIME conformant readers."); + + mP.addBodyPart(new ByteArrayBodyPartPayload(("This is implicitly typed plain US-ASCII text.\n" + + "It does NOT end with a linebreak.").getBytes())); + + final ByteArrayBodyPartPayload bP = new ByteArrayBodyPartPayload( + ("This is explicitly typed plain US-ASCII text.\n" + + "It DOES end with a linebreak.\n").getBytes(), + Collections.singletonMap(HttpClient.CONTENT_TYPE, "text/plain; charset=us-ascii")); + mP.addBodyPart(bP); + + mP.setEpilogue("This is the epilogue. It is also to be ignored."); + + final StringBuilder headersString = new StringBuilder(); + for (Map.Entry header : mP.getHeaders().entrySet()) { + headersString.append(header.getKey()) + .append(": ") + .append(header.getValue()) + .append("\r\n"); + } + + assertEquals("X-Header: X-Value\r\n" + + "Content-Disposition: Content-Disposition-Value\r\n" + + "Content-Type: multipart/mixed; boundary=\"simple boundary\"\r\n", + headersString.toString()); + + assertEquals("This is the preamble. It is to be ignored, though it\n" + + "is a handy place for composition agents to include an\n" + + "explanatory note to non-MIME conformant readers." + + "\r\n--simple boundary\r\n" + + "\r\n" + + "This is implicitly typed plain US-ASCII text.\n" + + "It does NOT end with a linebreak." + + "\r\n--simple boundary\r\n" + + "Content-Type: text/plain; charset=us-ascii\r\n" + + "\r\n" + + "This is explicitly typed plain US-ASCII text.\n" + + "It DOES end with a linebreak.\n" + + "\r\n--simple boundary--" + + "\r\nThis is the epilogue. It is also to be ignored.", + MultipartUtils.getPayload(mP).toString()); + } + + @Test + public void testCRLFMultipartPayload() throws IOException { + final MultipartPayload mP = new MultipartPayload("simple-boundary"); + mP.addBodyPart(new ByteArrayBodyPartPayload("It does NOT end with a linebreak.".getBytes())); + mP.addBodyPart(new ByteArrayBodyPartPayload("It does end with a \\r linebreak.\r".getBytes())); + mP.addBodyPart(new ByteArrayBodyPartPayload("It does end with a \\n linebreak.\n".getBytes())); + mP.addBodyPart(new ByteArrayBodyPartPayload("It does end with a \\r\\n linebreak.\r\n".getBytes())); + mP.addBodyPart(new ByteArrayBodyPartPayload("the last one".getBytes())); + + final StringBuilder headersString = new StringBuilder(); + for (Map.Entry header : mP.getHeaders().entrySet()) { + headersString.append(header.getKey()) + .append(": ") + .append(header.getValue()) + .append("\r\n"); + } + + assertEquals("Content-Type: multipart/form-data; boundary=\"simple-boundary\"\r\n", headersString.toString()); + + assertEquals("--simple-boundary\r\n" + + "\r\n" + + "It does NOT end with a linebreak." + + "\r\n--simple-boundary\r\n" + + "\r\n" + + "It does end with a \\r linebreak.\r" + + "\r\n--simple-boundary\r\n" + + "\r\n" + + "It does end with a \\n linebreak.\n" + + "\r\n--simple-boundary\r\n" + + "\r\n" + + "It does end with a \\r\\n linebreak.\r\n" + + "\r\n--simple-boundary\r\n" + + "\r\n" + + "the last one" + + "\r\n--simple-boundary--", + MultipartUtils.getPayload(mP).toString()); + } + + @Test + public void testFileByteArrayBodyPartPayloadMultipartPayload() throws IOException { + final MultipartPayload mP = new MultipartPayload("testFileByteArrayBodyPartPayloadMultipartPayload boundary"); + mP.addBodyPart(new FileByteArrayBodyPartPayload("fileContent".getBytes(), "name", "filename.ext")); + + final StringBuilder headersString = new StringBuilder(); + for (Map.Entry header : mP.getHeaders().entrySet()) { + headersString.append(header.getKey()) + .append(": ") + .append(header.getValue()) + .append("\r\n"); + } + + assertEquals("Content-Type: multipart/form-data; " + + "boundary=\"testFileByteArrayBodyPartPayloadMultipartPayload boundary\"\r\n", + headersString.toString()); + + assertEquals("--testFileByteArrayBodyPartPayloadMultipartPayload boundary\r\n" + + "Content-Disposition: form-data; name=\"name\"; filename=\"filename.ext\"\r\n" + + "\r\n" + + "fileContent" + + "\r\n--testFileByteArrayBodyPartPayloadMultipartPayload boundary--", + MultipartUtils.getPayload(mP).toString()); + } + + @Test + public void testComplexMultipartPayload() throws IOException { + final MultipartPayload mP = new MultipartPayload("mixed", "unique-boundary-1"); + + mP.setPreamble("This is the preamble area of a multipart message.\n" + + "Mail readers that understand multipart format\n" + + "should ignore this preamble.\n" + + "\n" + + "If you are reading this text, you might want to\n" + + "consider changing to a mail reader that understands\n" + + "how to properly display multipart messages.\n"); + + mP.addBodyPart(new ByteArrayBodyPartPayload("... Some text appears here ...".getBytes())); + + mP.addBodyPart(new ByteArrayBodyPartPayload(("This could have been part of the previous part, but\n" + + "illustrates explicit versus implicit typing of body\n" + + "parts.\n").getBytes(), "text/plain; charset=US-ASCII")); + + final MultipartPayload innerMP = new MultipartPayload("parallel", "unique-boundary-2"); + mP.addBodyPart(innerMP); + + final Map audioHeaders = new LinkedHashMap<>(); + audioHeaders.put("Content-Type", "audio/basic"); + audioHeaders.put("Content-Transfer-Encoding", "base64"); + innerMP.addBodyPart(new ByteArrayBodyPartPayload(("... base64-encoded 8000 Hz single-channel\n" + + " mu-law-format audio data goes here ...").getBytes(), audioHeaders)); + + final Map imageHeaders = new LinkedHashMap<>(); + imageHeaders.put("Content-Type", "image/jpeg"); + imageHeaders.put("Content-Transfer-Encoding", "base64"); + innerMP.addBodyPart(new ByteArrayBodyPartPayload("... base64-encoded image data goes here ...".getBytes(), + imageHeaders)); + + mP.addBodyPart(new ByteArrayBodyPartPayload(("This is enriched.\n" + + "as defined in RFC 1896\n" + + "\n" + + "Isn't it\n" + + "cool?\n").getBytes(), "text/enriched")); + + mP.addBodyPart(new ByteArrayBodyPartPayload(("From: (mailbox in US-ASCII)\n" + + "To: (address in US-ASCII)\n" + + "Subject: (subject in US-ASCII)\n" + + "Content-Type: Text/plain; charset=ISO-8859-1\n" + + "Content-Transfer-Encoding: Quoted-printable\n" + + "\n" + + "... Additional text in ISO-8859-1 goes here ...\n").getBytes(), "message/rfc822")); + + final StringBuilder headersString = new StringBuilder(); + for (Map.Entry header : mP.getHeaders().entrySet()) { + headersString.append(header.getKey()) + .append(": ") + .append(header.getValue()) + .append("\r\n"); + } + assertEquals("Content-Type: multipart/mixed; boundary=\"unique-boundary-1\"\r\n", headersString.toString()); + + assertEquals("This is the preamble area of a multipart message.\n" + + "Mail readers that understand multipart format\n" + + "should ignore this preamble.\n" + + "\n" + + "If you are reading this text, you might want to\n" + + "consider changing to a mail reader that understands\n" + + "how to properly display multipart messages.\n" + + "\r\n--unique-boundary-1\r\n" + + "\r\n" + + "... Some text appears here ..." + + "\r\n--unique-boundary-1\r\n" + + "Content-Type: text/plain; charset=US-ASCII\r\n" + + "\r\n" + + "This could have been part of the previous part, but\n" + + "illustrates explicit versus implicit typing of body\n" + + "parts.\n" + + "\r\n--unique-boundary-1\r\n" + + "Content-Type: multipart/parallel; boundary=\"unique-boundary-2\"\r\n" + + "\r\n--unique-boundary-2\r\n" + + "Content-Type: audio/basic\r\n" + + "Content-Transfer-Encoding: base64\r\n" + + "\r\n" + + "... base64-encoded 8000 Hz single-channel\n" + + " mu-law-format audio data goes here ..." + + "\r\n--unique-boundary-2\r\n" + + "Content-Type: image/jpeg\r\n" + + "Content-Transfer-Encoding: base64\r\n" + + "\r\n" + + "... base64-encoded image data goes here ..." + + "\r\n--unique-boundary-2--" + + "\r\n--unique-boundary-1\r\n" + + "Content-Type: text/enriched\r\n" + + "\r\n" + + "This is enriched.\n" + + "as defined in RFC 1896\n" + + "\n" + + "Isn't it\n" + + "cool?\n" + + "\r\n--unique-boundary-1\r\n" + + "Content-Type: message/rfc822\r\n" + + "\r\n" + + "From: (mailbox in US-ASCII)\n" + + "To: (address in US-ASCII)\n" + + "Subject: (subject in US-ASCII)\n" + + "Content-Type: Text/plain; charset=ISO-8859-1\n" + + "Content-Transfer-Encoding: Quoted-printable\n" + + "\n" + + "... Additional text in ISO-8859-1 goes here ...\n" + + "\r\n--unique-boundary-1--", + MultipartUtils.getPayload(mP).toString()); + } + + @Test + public void testParseBoundaryFromHeader() { + assertNull(MultipartUtils.parseBoundaryFromHeader(null)); + + assertEquals("0aA'()+_,-./:=?", + MultipartUtils.parseBoundaryFromHeader("multipart/subtype; boundary=\"0aA'()+_,-./:=?\"")); + + assertEquals("0aA'()+_, -./:=?", + MultipartUtils.parseBoundaryFromHeader("multipart/subtype; boundary=\"0aA'()+_, -./:=?\"")); + + assertEquals("0aA'()+_, -./:=?", + MultipartUtils.parseBoundaryFromHeader("multipart/subtype; boundary=\"0aA'()+_, -./:=? \"")); + + assertEquals("0aA'()+_,-./:=?", + MultipartUtils.parseBoundaryFromHeader("multipart/subtype; boundary=0aA'()+_,-./:=?")); + + assertEquals("0aA'()+_, -./:=?", + MultipartUtils.parseBoundaryFromHeader("multipart/subtype; boundary=0aA'()+_, -./:=?")); + + assertEquals("0aA'()+_, -./:=?", + MultipartUtils.parseBoundaryFromHeader("multipart/subtype; boundary=0aA'()+_, -./:=? ")); + + assertEquals(" 0aA'()+_, -./:=?", + MultipartUtils.parseBoundaryFromHeader("multipart/subtype; boundary= 0aA'()+_, -./:=?")); + + assertNull(MultipartUtils.parseBoundaryFromHeader("multipart/subtype; boundar=0aA'()+_, -./:=? ")); + assertNull(MultipartUtils.parseBoundaryFromHeader("multipart/subtype; ")); + assertNull(MultipartUtils.parseBoundaryFromHeader("multipart/subtype;")); + assertNull(MultipartUtils.parseBoundaryFromHeader("multipart/subtype")); + assertNull(MultipartUtils.parseBoundaryFromHeader("multipart/subtype; boundary=")); + + assertEquals("0aA'()+_,", + MultipartUtils.parseBoundaryFromHeader("multipart/subtype; boundary=0aA'()+_,; -./:=? ")); + + assertEquals("0aA'()+_, -./:=?", + MultipartUtils.parseBoundaryFromHeader("multipart/subtype; boundary=\"0aA'()+_, -./:=?")); + + assertEquals("0aA'()+_, -./:=?", + MultipartUtils.parseBoundaryFromHeader("multipart/subtype; boundary=0aA'()+_, -./:=?\"")); + + assertEquals("1234567890123456789012345678901234567890123456789012345678901234567890", + MultipartUtils.parseBoundaryFromHeader("multipart/subtype; " + + "boundary=1234567890123456789012345678901234567890123456789012345678901234567890")); + + assertEquals("1234567890123456789012345678901234567890123456789012345678901234567890", + MultipartUtils.parseBoundaryFromHeader("multipart/subtype; " + + "boundary=12345678901234567890123456789012345678901234567890123456789012345678901")); + + assertNull(MultipartUtils.parseBoundaryFromHeader("multipart/subtype; boundary=")); + assertNull(MultipartUtils.parseBoundaryFromHeader("multipart/subtype; boundary=\"\"")); + assertNull(MultipartUtils.parseBoundaryFromHeader("multipart/subtype; boundary=;123")); + assertNull(MultipartUtils.parseBoundaryFromHeader("multipart/subtype; boundary=\"\"123")); + } + + @Test + public void testValidCheckBoundarySyntax() { + MultipartUtils.checkBoundarySyntax("0aA'()+_,-./:=?"); + MultipartUtils.checkBoundarySyntax("0aA'()+_,- ./:=?"); + MultipartUtils.checkBoundarySyntax(" 0aA'()+_,-./:=?"); + MultipartUtils.checkBoundarySyntax("1234567890123456789012345678901234567890123456789012345678901234567890"); + } + + @Test + public void testNonValidLastWhiteSpaceCheckBoundarySyntax() { + testNotValidBoundary("0aA'()+_,-./:=? "); + } + + @Test + public void testNonValidEmptyCheckBoundarySyntax() { + testNotValidBoundary(""); + } + + @Test + public void testNonValidIllegalSymbolCheckBoundarySyntax() { + testNotValidBoundary("0aA'()+_;,-./:=? "); + } + + @Test + public void testNonValidTooLongCheckBoundarySyntax() { + testNotValidBoundary("12345678901234567890123456789012345678901234567890123456789012345678901"); + } + + @Test + public void testNonValidNullCheckBoundarySyntax() { + testNotValidBoundary(null); + } + + private static void testNotValidBoundary(final String boundary) { + final IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + MultipartUtils.checkBoundarySyntax(boundary); + } + }); + assertTrue(thrown.getMessage().startsWith("{'boundary'='" + boundary + "'} has invalid syntax. Should be '")); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/model/OAuthRequestTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/model/OAuthRequestTest.java new file mode 100644 index 000000000..32d5d6731 --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/model/OAuthRequestTest.java @@ -0,0 +1,56 @@ +package com.github.scribejava.core.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; +import org.junit.Before; +import org.junit.Test; +import org.junit.function.ThrowingRunnable; + +public class OAuthRequestTest { + + private OAuthRequest request; + + @Before + public void setUp() { + request = new OAuthRequest(Verb.GET, "http://example.com"); + } + + @Test + public void shouldAddOAuthParamters() { + request.addOAuthParameter(OAuthConstants.TOKEN, "token"); + request.addOAuthParameter(OAuthConstants.NONCE, "nonce"); + request.addOAuthParameter(OAuthConstants.TIMESTAMP, "ts"); + request.addOAuthParameter(OAuthConstants.SCOPE, "feeds"); + request.addOAuthParameter(OAuthConstants.REALM, "some-realm"); + + assertEquals(5, request.getOauthParameters().size()); + } + + public void shouldThrowExceptionIfParameterIsNotOAuth() { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + request.addOAuthParameter("otherParam", "value"); + } + }); + } + + @Test + public void shouldNotSentHeaderTwice() { + assertTrue(request.getHeaders().isEmpty()); + request.addHeader("HEADER-NAME", "first"); + request.addHeader("header-name", "middle"); + request.addHeader("Header-Name", "last"); + + assertEquals(1, request.getHeaders().size()); + + assertTrue(request.getHeaders().containsKey("HEADER-NAME")); + assertTrue(request.getHeaders().containsKey("header-name")); + assertTrue(request.getHeaders().containsKey("Header-Name")); + + assertEquals("last", request.getHeaders().get("HEADER-NAME")); + assertEquals("last", request.getHeaders().get("header-name")); + assertEquals("last", request.getHeaders().get("Header-Name")); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/model/ParameterListTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/model/ParameterListTest.java new file mode 100644 index 000000000..702c66395 --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/model/ParameterListTest.java @@ -0,0 +1,84 @@ +package com.github.scribejava.core.model; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertThrows; +import org.junit.function.ThrowingRunnable; + +public class ParameterListTest { + + private ParameterList params; + + @Before + public void setUp() { + this.params = new ParameterList(); + } + + public void shouldThrowExceptionWhenAppendingNullMapToQuerystring() { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + params.appendTo(null); + } + }); + } + + @Test + public void shouldAppendNothingToQuerystringIfGivenEmptyMap() { + final String url = "http://www.example.com"; + Assert.assertEquals(url, params.appendTo(url)); + } + + @Test + public void shouldAppendParametersToSimpleUrl() { + String url = "http://www.example.com"; + final String expectedUrl = "http://www.example.com?param1=value1¶m2=value%20with%20spaces"; + + params.add("param1", "value1"); + params.add("param2", "value with spaces"); + + url = params.appendTo(url); + Assert.assertEquals(expectedUrl, url); + } + + @Test + public void shouldAppendParametersToUrlWithQuerystring() { + String url = "http://www.example.com?already=present"; + final String expectedUrl = "http://www.example.com?already=present¶m1=value1¶m2=value%20with%20spaces"; + + params.add("param1", "value1"); + params.add("param2", "value with spaces"); + + url = params.appendTo(url); + Assert.assertEquals(expectedUrl, url); + } + + @Test + public void shouldProperlySortParameters() { + params.add("param1", "v1"); + params.add("param6", "v2"); + params.add("a_param", "v3"); + params.add("param2", "v4"); + Assert.assertEquals("a_param=v3¶m1=v1¶m2=v4¶m6=v2", params.sort().asFormUrlEncodedString()); + } + + @Test + public void shouldProperlySortParametersWithTheSameName() { + params.add("param1", "v1"); + params.add("param6", "v2"); + params.add("a_param", "v3"); + params.add("param1", "v4"); + Assert.assertEquals("a_param=v3¶m1=v1¶m1=v4¶m6=v2", params.sort().asFormUrlEncodedString()); + } + + @Test + public void shouldNotModifyTheOriginalParameterList() { + params.add("param1", "v1"); + params.add("param6", "v2"); + + assertNotSame(params, params.sort()); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/model/RequestTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/model/RequestTest.java new file mode 100644 index 000000000..87189632b --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/model/RequestTest.java @@ -0,0 +1,99 @@ +package com.github.scribejava.core.model; + +import static org.junit.Assert.assertTrue; +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertArrayEquals; + +public class RequestTest { + + @Test + public void shouldGetQueryStringParameters() { + final OAuthRequest postRequest = new OAuthRequest(Verb.POST, "http://example.com"); + postRequest.addBodyParameter("param", "value"); + postRequest.addBodyParameter("param with spaces", "value with spaces"); + + final OAuthRequest getRequest + = new OAuthRequest(Verb.GET, "http://example.com?qsparam=value&other+param=value+with+spaces"); + + assertEquals(2, getRequest.getQueryStringParams().size()); + assertEquals(0, postRequest.getQueryStringParams().size()); + assertTrue(getRequest.getQueryStringParams().contains(new Parameter("qsparam", "value"))); + } + + @Test + public void shouldSetBodyParamsAndAddContentLength() { + final OAuthRequest postRequest = new OAuthRequest(Verb.POST, "http://example.com"); + postRequest.addBodyParameter("param", "value"); + postRequest.addBodyParameter("param with spaces", "value with spaces"); + + assertEquals("param=value¶m%20with%20spaces=value%20with%20spaces", + new String(postRequest.getByteArrayPayload())); + } + + @Test + public void shouldSetPayloadAndHeaders() { + final OAuthRequest postRequest = new OAuthRequest(Verb.POST, "http://example.com"); + postRequest.addBodyParameter("param", "value"); + postRequest.addBodyParameter("param with spaces", "value with spaces"); + postRequest.setPayload("PAYLOAD"); + + assertEquals("PAYLOAD", postRequest.getStringPayload()); + } + + @Test + public void shouldAllowAddingQuerystringParametersAfterCreation() { + final OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com?one=val"); + request.addQuerystringParameter("two", "other val"); + request.addQuerystringParameter("more", "params"); + assertEquals(3, request.getQueryStringParams().size()); + } + + @Test + public void shouldReturnTheCompleteUrl() { + final OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com?one=val"); + request.addQuerystringParameter("two", "other val"); + request.addQuerystringParameter("more", "params"); + assertEquals("http://example.com?one=val&two=other%20val&more=params", request.getCompleteUrl()); + } + + @Test + public void shouldHandleQueryStringSpaceEncodingProperly() { + final OAuthRequest getRequest + = new OAuthRequest(Verb.GET, "http://example.com?qsparam=value&other+param=value+with+spaces"); + + assertTrue(getRequest.getQueryStringParams().contains(new Parameter("other param", "value with spaces"))); + } + + @Test + public void shouldNotEncodeInStringPayload() throws Exception { + final String requestBody = "~/!@#$%^&*( )_+//\r\n%2F&"; + + final OAuthRequest postRequest = new OAuthRequest(Verb.POST, "http://example.com"); + postRequest.setPayload(requestBody); + + assertEquals(requestBody, postRequest.getStringPayload()); + } + + @Test + public void shouldNotEncodeInByteBodyPayload() throws Exception { + final byte[] requestBody = "~/!@#$%^&*( )_+//\r\n%2F&".getBytes(); + + final OAuthRequest postRequest = new OAuthRequest(Verb.POST, "http://example.com"); + postRequest.setPayload(requestBody); + + assertArrayEquals(requestBody, postRequest.getByteArrayPayload()); + } + + @Test + public void shouldEncodeInBodyParamsPayload() throws Exception { + final String expectedRequestBodyParamName = "~/!@#$%^&*( )_+//\r\n%2F&name"; + final String expectedRequestBodyParamValue = "~/!@#$%^&*( )_+//\r\n%2F&value"; + final String expectedRequestBody = "~%2F%21%40%23%24%25%5E%26%2A%28%20%29_%2B%2F%2F%0D%0A%252F%26amp%3Bname=" + + "~%2F%21%40%23%24%25%5E%26%2A%28%20%29_%2B%2F%2F%0D%0A%252F%26amp%3Bvalue"; + + final OAuthRequest postRequest = new OAuthRequest(Verb.POST, "http://example.com"); + postRequest.addBodyParameter(expectedRequestBodyParamName, expectedRequestBodyParamValue); + assertArrayEquals(expectedRequestBody.getBytes(), postRequest.getByteArrayPayload()); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/model/TokenTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/model/TokenTest.java new file mode 100644 index 000000000..7c988ae7b --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/model/TokenTest.java @@ -0,0 +1,51 @@ +package com.github.scribejava.core.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import org.junit.Test; + +public class TokenTest { + + @Test + public void shouldTestEqualityBasedOnTokenAndSecret() { + final Token expected = new OAuth1AccessToken("access", "secret"); + final Token actual = new OAuth1AccessToken("access", "secret"); + + assertEquals(expected, actual); + assertEquals(actual, actual); + } + + @Test + public void shouldNotDependOnRawString() { + final Token expected = new OAuth1AccessToken("access", "secret", "raw_string"); + final Token actual = new OAuth1AccessToken("access", "secret", "different_raw_string"); + + assertEquals(expected, actual); + } + + @Test + public void shouldReturnSameHashCodeForEqualObjects() { + final Token expected = new OAuth1AccessToken("access", "secret"); + final Token actual = new OAuth1AccessToken("access", "secret"); + + assertEquals(expected.hashCode(), actual.hashCode()); + } + + @Test + public void shouldNotBeEqualToNullOrOtherObjects() { + final Token expected = new OAuth1AccessToken("access", "secret", "response"); + + assertNotSame(expected, null); + assertNotSame(expected, new Object()); + } + + @Test + public void shouldReturnUrlParam() { + final Token actual = new OAuth1AccessToken("acccess", "secret", + "user_id=3107154759&screen_name=someuser&empty=&="); + assertEquals("someuser", actual.getParameter("screen_name")); + assertEquals("3107154759", actual.getParameter("user_id")); + assertEquals(null, actual.getParameter("empty")); + assertEquals(null, actual.getParameter(null)); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/oauth/CompletedFuture.java b/scribejava-core/src/test/java/com/github/scribejava/core/oauth/CompletedFuture.java new file mode 100644 index 000000000..33919d4bf --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/oauth/CompletedFuture.java @@ -0,0 +1,37 @@ +package com.github.scribejava.core.oauth; + +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +class CompletedFuture implements Future { + private final V result; + + CompletedFuture(V result) { + this.result = result; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return false; + } + + @Override + public boolean isCancelled() { + return false; + } + + @Override + public boolean isDone() { + return true; + } + + @Override + public V get() { + return result; + } + + @Override + public V get(long timeout, TimeUnit unit) { + return result; + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/oauth/OAuth20ApiUnit.java b/scribejava-core/src/test/java/com/github/scribejava/core/oauth/OAuth20ApiUnit.java new file mode 100644 index 000000000..cd9e58550 --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/oauth/OAuth20ApiUnit.java @@ -0,0 +1,35 @@ +package com.github.scribejava.core.oauth; + +import java.io.OutputStream; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; + +class OAuth20ApiUnit extends DefaultApi20 { + + @Override + public String getAccessTokenEndpoint() { + return "http://localhost:8080/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "http://localhost:8080/authorize"; + } + + @Override + public OAuth20ServiceUnit createService(String apiKey, String apiSecret, String callback, String defaultScope, + String responseType, OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, + HttpClient httpClient) { + return new OAuth20ServiceUnit(this, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, + userAgent, httpClientConfig, httpClient); + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/oauth/OAuth20ServiceTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/oauth/OAuth20ServiceTest.java new file mode 100644 index 000000000..3e0024c6c --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/oauth/OAuth20ServiceTest.java @@ -0,0 +1,117 @@ +package com.github.scribejava.core.oauth; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.scribejava.core.base64.Base64; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuth2Authorization; +import com.github.scribejava.core.model.OAuthConstants; +import java.io.IOException; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +import java.nio.charset.Charset; +import java.util.concurrent.ExecutionException; + +public class OAuth20ServiceTest { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + @Test + public void shouldProduceCorrectRequestSync() throws IOException, InterruptedException, ExecutionException { + final OAuth20Service service = new ServiceBuilder("your_api_key") + .apiSecret("your_api_secret") + .build(new OAuth20ApiUnit()); + + final OAuth2AccessToken token = service.getAccessTokenPasswordGrant("user1", "password1"); + assertNotNull(token); + + final JsonNode response = OBJECT_MAPPER.readTree(token.getRawResponse()); + + assertEquals(OAuth20ServiceUnit.TOKEN, response.get(OAuthConstants.ACCESS_TOKEN).asText()); + assertEquals(OAuth20ServiceUnit.EXPIRES, response.get("expires_in").asInt()); + + final String authorize = Base64.encode( + String.format("%s:%s", service.getApiKey(), service.getApiSecret()).getBytes(Charset.forName("UTF-8"))); + + assertEquals(OAuthConstants.BASIC + ' ' + authorize, response.get(OAuthConstants.HEADER).asText()); + + assertEquals("user1", response.get("query-username").asText()); + assertEquals("password1", response.get("query-password").asText()); + assertEquals("password", response.get("query-grant_type").asText()); + } + + @Test + public void shouldProduceCorrectRequestAsync() throws ExecutionException, InterruptedException, IOException { + final OAuth20Service service = new ServiceBuilder("your_api_key") + .apiSecret("your_api_secret") + .build(new OAuth20ApiUnit()); + + final OAuth2AccessToken token = service.getAccessTokenPasswordGrantAsync("user1", "password1").get(); + + assertNotNull(token); + + final JsonNode response = OBJECT_MAPPER.readTree(token.getRawResponse()); + + assertEquals(OAuth20ServiceUnit.TOKEN, response.get(OAuthConstants.ACCESS_TOKEN).asText()); + assertEquals(OAuth20ServiceUnit.EXPIRES, response.get("expires_in").asInt()); + + final String authorize = Base64.encode( + String.format("%s:%s", service.getApiKey(), service.getApiSecret()).getBytes(Charset.forName("UTF-8"))); + + assertEquals(OAuthConstants.BASIC + ' ' + authorize, response.get(OAuthConstants.HEADER).asText()); + + assertEquals("user1", response.get("query-username").asText()); + assertEquals("password1", response.get("query-password").asText()); + assertEquals("password", response.get("query-grant_type").asText()); + } + + @Test + public void testOAuthExtractAuthorization() { + final OAuth20Service service = new ServiceBuilder("your_api_key") + .apiSecret("your_api_secret") + .build(new OAuth20ApiUnit()); + + OAuth2Authorization authorization = service.extractAuthorization("https://cl.ex.com/cb?code=SplxlOB&state=xyz"); + assertEquals("SplxlOB", authorization.getCode()); + assertEquals("xyz", authorization.getState()); + + authorization = service.extractAuthorization("https://cl.ex.com/cb?state=xyz&code=SplxlOB"); + assertEquals("SplxlOB", authorization.getCode()); + assertEquals("xyz", authorization.getState()); + + authorization = service.extractAuthorization("https://cl.ex.com/cb?key=value&state=xyz&code=SplxlOB"); + assertEquals("SplxlOB", authorization.getCode()); + assertEquals("xyz", authorization.getState()); + + authorization = service.extractAuthorization("https://cl.ex.com/cb?state=xyz&code=SplxlOB&key=value&"); + assertEquals("SplxlOB", authorization.getCode()); + assertEquals("xyz", authorization.getState()); + + authorization = service.extractAuthorization("https://cl.ex.com/cb?code=SplxlOB&state="); + assertEquals("SplxlOB", authorization.getCode()); + assertEquals(null, authorization.getState()); + + authorization = service.extractAuthorization("https://cl.ex.com/cb?code=SplxlOB"); + assertEquals("SplxlOB", authorization.getCode()); + assertEquals(null, authorization.getState()); + + authorization = service.extractAuthorization("https://cl.ex.com/cb?code="); + assertEquals(null, authorization.getCode()); + assertEquals(null, authorization.getState()); + + authorization = service.extractAuthorization("https://cl.ex.com/cb?code"); + assertEquals(null, authorization.getCode()); + assertEquals(null, authorization.getState()); + + authorization = service.extractAuthorization("https://cl.ex.com/cb?"); + assertEquals(null, authorization.getCode()); + assertEquals(null, authorization.getState()); + + authorization = service.extractAuthorization("https://cl.ex.com/cb"); + assertEquals(null, authorization.getCode()); + assertEquals(null, authorization.getState()); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/oauth/OAuth20ServiceUnit.java b/scribejava-core/src/test/java/com/github/scribejava/core/oauth/OAuth20ServiceUnit.java new file mode 100644 index 000000000..2766b7f2b --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/oauth/OAuth20ServiceUnit.java @@ -0,0 +1,72 @@ +package com.github.scribejava.core.oauth; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Parameter; + +import java.io.OutputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Future; + +class OAuth20ServiceUnit extends OAuth20Service { + + static final String TOKEN = "ae82980abab675c646a070686d5558ad"; + static final String STATE = "123"; + static final int EXPIRES = 3600; + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + OAuth20ServiceUnit(DefaultApi20 api, String apiKey, String apiSecret, String callback, String defaultScope, + String responseType, OutputStream debugStream, String userAgent, HttpClientConfig httpClientConfig, + HttpClient httpClient) { + super(api, apiKey, apiSecret, callback, defaultScope, responseType, debugStream, userAgent, httpClientConfig, + httpClient); + } + + @Override + protected OAuth2AccessToken sendAccessTokenRequestSync(OAuthRequest request) { + return new OAuth2AccessToken(TOKEN, prepareRawResponse(request)); + } + + private String prepareRawResponse(OAuthRequest request) { + final Map response = new HashMap<>(); + response.put(OAuthConstants.ACCESS_TOKEN, TOKEN); + response.put(OAuthConstants.STATE, STATE); + response.put("expires_in", EXPIRES); + + response.putAll(request.getHeaders()); + response.putAll(request.getOauthParameters()); + + for (Parameter param : request.getBodyParams().getParams()) { + response.put("query-" + param.getKey(), param.getValue()); + } + + try { + return OBJECT_MAPPER.writeValueAsString(response); + } catch (JsonProcessingException ex) { + throw new IllegalStateException("smth wrong with Jackson?"); + } + } + + @Override + protected Future sendAccessTokenRequestAsync(OAuthRequest request, + OAuthAsyncRequestCallback callback) { + + final OAuth2AccessToken accessToken = new OAuth2AccessToken(TOKEN, prepareRawResponse(request)); + + try { + return new CompletedFuture<>(accessToken); + } finally { + if (callback != null) { + callback.onCompleted(accessToken); + } + } + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/pkce/PKCECodeChallengeMethodTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/pkce/PKCECodeChallengeMethodTest.java new file mode 100644 index 000000000..a83a5470d --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/pkce/PKCECodeChallengeMethodTest.java @@ -0,0 +1,26 @@ +package com.github.scribejava.core.pkce; + +import org.junit.Test; +import static org.junit.Assert.assertEquals; + +/** + * test PKCE according to
+ * Appendix B. Example for the S256 code_challenge_method
+ * https://tools.ietf.org/html/rfc7636#appendix-B + */ +public class PKCECodeChallengeMethodTest { + + private static final byte[] RANDOM_BYTES = new byte[]{116, 24, (byte) 223, (byte) 180, (byte) 151, (byte) 153, + (byte) 224, 37, 79, (byte) 250, 96, 125, (byte) 216, (byte) 173, (byte) 187, (byte) 186, 22, (byte) 212, 37, 77, + 105, (byte) 214, (byte) 191, (byte) 240, 91, 88, 5, 88, 83, (byte) 132, (byte) 141, 121}; + + @Test + public void testGeneratingPKCE() { + final PKCE pkce = PKCEService.defaultInstance().generatePKCE(RANDOM_BYTES); + + assertEquals(PKCECodeChallengeMethod.S256, pkce.getCodeChallengeMethod()); + assertEquals("dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk", pkce.getCodeVerifier()); + assertEquals("E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM", pkce.getCodeChallenge()); + } + +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/services/HMACSha1SignatureServiceTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/services/HMACSha1SignatureServiceTest.java new file mode 100644 index 000000000..d824d2112 --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/services/HMACSha1SignatureServiceTest.java @@ -0,0 +1,64 @@ +package com.github.scribejava.core.services; + +import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Test; +import com.github.scribejava.core.exceptions.OAuthException; +import static org.junit.Assert.assertThrows; +import org.junit.function.ThrowingRunnable; + +public class HMACSha1SignatureServiceTest { + + private HMACSha1SignatureService service; + + @Before + public void setUp() { + service = new HMACSha1SignatureService(); + } + + @Test + public void shouldReturnSignatureMethodString() { + final String expected = "HMAC-SHA1"; + assertEquals(expected, service.getSignatureMethod()); + } + + @Test + public void shouldReturnSignature() { + final String apiSecret = "api secret"; + final String tokenSecret = "token secret"; + final String baseString = "base string"; + final String signature = "uGymw2KHOTWI699YEaoi5xyLT50="; + assertEquals(signature, service.getSignature(baseString, apiSecret, tokenSecret)); + } + + public void shouldThrowExceptionIfBaseStringIsNull() { + assertThrows(OAuthException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + service.getSignature(null, "apiSecret", "tokenSecret"); + } + }); + } + + public void shouldThrowExceptionIfBaseStringIsEmpty() { + assertThrows(OAuthException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + service.getSignature(" ", "apiSecret", "tokenSecret"); + } + }); + } + + public void shouldThrowExceptionIfApiSecretIsNull() { + assertThrows(OAuthException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + service.getSignature("base string", null, "tokenSecret"); + } + }); + } + + public void shouldNotThrowExceptionIfApiSecretIsEmpty() { + service.getSignature("base string", " ", "tokenSecret"); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/services/RSASha1SignatureServiceTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/services/RSASha1SignatureServiceTest.java new file mode 100644 index 000000000..652f328e3 --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/services/RSASha1SignatureServiceTest.java @@ -0,0 +1,62 @@ +package com.github.scribejava.core.services; + +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import org.apache.commons.codec.binary.Base64; +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class RSASha1SignatureServiceTest { + + private final RSASha1SignatureService service = new RSASha1SignatureService(getPrivateKey()); + + @Test + public void shouldReturnSignatureMethodString() { + final String expected = "RSA-SHA1"; + assertEquals(expected, service.getSignatureMethod()); + } + + @Test + public void shouldReturnSignature() { + final String apiSecret = "api secret"; + final String tokenSecret = "token secret"; + final String baseString = "base string"; + final String signature = "LUNRzQAlpdNyM9mLXm96Va6g/qVNnEAb7p7K1KM0g8IopOFQJPoOO7cvppgt7w3QyhijWJnCmvqXaaIAGrqvd" + + "yr3fIzBULh8D/iZQUNLMi08GCOA34P81XBvsc7A5uJjPDsGhJg2MzoVJ8nWJhU/lMMk4c92S1WGskeoDofRwpo="; + assertEquals(signature, service.getSignature(baseString, apiSecret, tokenSecret)); + } + + /** + * Created primary key using openssl. + * + * openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj '/C=GB/ST=/L=Manchester/CN=www.example.com' + * -keyout myrsakey.pem -out /tmp/myrsacert.pem openssl pkcs8 -in myrsakey.pem -topk8 -nocrypt -out myrsakey.pk8 + */ + private static PrivateKey getPrivateKey() { + final String str = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMPQ5BCMxlUq2TYy\n" + + "iRIoEUsz6HGTJhHuasS2nx1Se4Co3lxwxyubVdFj8AuhHNJSmJvjlpbTsGOjLZpr\n" + + "HyDEDdJmf1Fensh1MhUnBZ4a7uLrZrKzFHHJdamX9pxapB89vLeHlCot9hVXdrZH\n" + + "nNtg6FdmRKH/8gbs8iDyIayFvzYDAgMBAAECgYA+c9MpTBy9cQsR9BAvkEPjvkx2\n" + + "XL4ZnfbDgpNA4Nuu7yzsQrPjPomiXMNkkiAFHH67yVxwAlgRjyuuQlgNNTpKvyQt\n" + + "XcHxffnU0820VmE23M+L7jg2TlB3+rUnEDmDvCoyjlwGDR6lNb7t7Fgg2iR+iaov\n" + + "0iVzz+l9w0slRlyGsQJBAPWXW2m3NmFgqfDxtw8fsKC2y8o17/cnPjozRGtWb8LQ\n" + + "g3VCb8kbOFHOYNGazq3M7+wD1qILF2h/HecgK9eQrZ0CQQDMHXoJMfKKbrFrTKgE\n" + + "zyggO1gtuT5OXYeFewMEb5AbDI2FfSc2YP7SHij8iQ2HdukBrbTmi6qxh3HmIR58\n" + + "I/AfAkEA0Y9vr0tombsUB8cZv0v5OYoBZvCTbMANtzfb4AOHpiKqqbohDOevLQ7/\n" + + "SpvgVCmVaDz2PptcRAyEBZ5MCssneQJAB2pmvaDH7Ambfod5bztLfOhLCtY5EkXJ\n" + + "n6rZcDbRaHorRhdG7m3VtDKOUKZ2DF7glkQGV33phKukErVPUzlHBwJAScD9TqaG\n" + + "wJ3juUsVtujV23SnH43iMggXT7m82STpPGam1hPfmqu2Z0niePFo927ogQ7H1EMJ\n" + + "UHgqXmuvk2X/Ww=="; + + try { + final KeyFactory fac = KeyFactory.getInstance("RSA"); + final PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(str)); + return fac.generatePrivate(privKeySpec); + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + throw new RuntimeException(e); + } + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/services/TimestampServiceTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/services/TimestampServiceTest.java new file mode 100644 index 000000000..4d8f27bc5 --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/services/TimestampServiceTest.java @@ -0,0 +1,41 @@ +package com.github.scribejava.core.services; + +import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Test; + +public class TimestampServiceTest { + + private TimestampServiceImpl service; + + @Before + public void setUp() { + service = new TimestampServiceImpl(); + service.setTimer(new TimerStub()); + } + + @Test + public void shouldReturnTimestampInSeconds() { + final String expected = "1000"; + assertEquals(expected, service.getTimestampInSeconds()); + } + + @Test + public void shouldReturnNonce() { + final String expected = "1042"; + assertEquals(expected, service.getNonce()); + } + + private static class TimerStub extends TimestampServiceImpl.Timer { + + @Override + public Long getMilis() { + return 1000000L; + } + + @Override + public Integer getRandomInteger() { + return 42; + } + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/utils/OAuthEncoderTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/utils/OAuthEncoderTest.java new file mode 100644 index 000000000..9a27d238d --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/utils/OAuthEncoderTest.java @@ -0,0 +1,69 @@ +package com.github.scribejava.core.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import org.junit.Test; +import org.junit.function.ThrowingRunnable; + +public class OAuthEncoderTest { + + @Test + public void shouldPercentEncodeString() { + final String plain = "this is a test &^"; + final String encoded = "this%20is%20a%20test%20%26%5E"; + assertEquals(encoded, OAuthEncoder.encode(plain)); + } + + @Test + public void shouldFormURLDecodeString() { + final String encoded = "this+is+a+test+%26%5E"; + final String plain = "this is a test &^"; + assertEquals(plain, OAuthEncoder.decode(encoded)); + } + + @Test + public void shouldPercentEncodeAllSpecialCharacters() { + final String plain = "!*'();:@&=+$,/?#[]"; + final String encoded = "%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%23%5B%5D"; + assertEquals(encoded, OAuthEncoder.encode(plain)); + assertEquals(plain, OAuthEncoder.decode(encoded)); + } + + @Test + public void shouldNotPercentEncodeReservedCharacters() { + final String plain = "abcde123456-._~"; + final String encoded = plain; + assertEquals(encoded, OAuthEncoder.encode(plain)); + } + + public void shouldThrowExceptionIfStringToEncodeIsNull() { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + OAuthEncoder.encode(null); + } + }); + } + + public void shouldThrowExceptionIfStringToDecodeIsNull() { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + OAuthEncoder.decode(null); + } + }); + } + + @Test + public void shouldPercentEncodeCorrectlyTwitterCodingExamples() { + // These tests are part of the Twitter dev examples here + // -> https://dev.twitter.com/docs/auth/percent-encoding-parameters + final String[] sources = {"Ladies + Gentlemen", "An encoded string!", "Dogs, Cats & Mice"}; + final String[] encoded = {"Ladies%20%2B%20Gentlemen", "An%20encoded%20string%21", + "Dogs%2C%20Cats%20%26%20Mice"}; + + for (int i = 0; i < sources.length; i++) { + assertEquals(encoded[i], OAuthEncoder.encode(sources[i])); + } + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/utils/PreconditionsTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/utils/PreconditionsTest.java new file mode 100644 index 000000000..1e3bd71e2 --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/utils/PreconditionsTest.java @@ -0,0 +1,45 @@ +package com.github.scribejava.core.utils; + +import static org.junit.Assert.assertThrows; +import org.junit.function.ThrowingRunnable; + +public class PreconditionsTest { + + private static final String ERROR_MSG = ""; + + public void shouldThrowExceptionForNullObjects() { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + Preconditions.checkNotNull(null, ERROR_MSG); + } + }); + } + + public void shouldThrowExceptionForNullStrings() { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + Preconditions.checkEmptyString(null, ERROR_MSG); + } + }); + } + + public void shouldThrowExceptionForEmptyStrings() { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + Preconditions.checkEmptyString("", ERROR_MSG); + } + }); + } + + public void shouldThrowExceptionForSpacesOnlyStrings() { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + Preconditions.checkEmptyString(" ", ERROR_MSG); + } + }); + } +} diff --git a/scribejava-core/src/test/java/com/github/scribejava/core/utils/StreamUtilsTest.java b/scribejava-core/src/test/java/com/github/scribejava/core/utils/StreamUtilsTest.java new file mode 100644 index 000000000..61937bac6 --- /dev/null +++ b/scribejava-core/src/test/java/com/github/scribejava/core/utils/StreamUtilsTest.java @@ -0,0 +1,49 @@ +package com.github.scribejava.core.utils; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import org.junit.Test; +import org.junit.function.ThrowingRunnable; + +public class StreamUtilsTest { + + private static final InputStream ALLWAYS_ERROR_INPUT_STREAM = new AllwaysErrorInputStream(); + + private static class AllwaysErrorInputStream extends InputStream { + + @Override + public int read() throws IOException { + throw new IOException(); + } + } + + @Test + public void shouldCorrectlyDecodeAStream() throws IOException { + final String value = "expected"; + final InputStream is = new ByteArrayInputStream(value.getBytes()); + final String decoded = StreamUtils.getStreamContents(is); + assertEquals("expected", decoded); + } + + public void shouldFailForNullParameter() throws IOException { + assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + StreamUtils.getStreamContents(null); + } + }); + } + + public void shouldFailWithBrokenStream() throws IOException { + assertThrows(IOException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + // This object simulates problems with input stream. + StreamUtils.getStreamContents(ALLWAYS_ERROR_INPUT_STREAM); + } + }); + } +} diff --git a/scribejava-httpclient-ahc/pom.xml b/scribejava-httpclient-ahc/pom.xml new file mode 100644 index 000000000..fabd225c3 --- /dev/null +++ b/scribejava-httpclient-ahc/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + + + com.github.scribejava + scribejava + 8.3.4-SNAPSHOT + ../pom.xml + + + com.github.scribejava + scribejava-httpclient-ahc + ScribeJava Async Http Http Client support + jar + + + + com.github.scribejava + scribejava-core + ${project.version} + + + org.slf4j + slf4j-simple + 2.0.3 + test + + + org.asynchttpclient + async-http-client + 2.12.3 + + + com.github.scribejava + scribejava-core + ${project.version} + test-jar + test + + + + + + + org.apache.felix + maven-bundle-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + diff --git a/scribejava-httpclient-ahc/src/main/java/com/github/scribejava/httpclient/ahc/AhcHttpClient.java b/scribejava-httpclient-ahc/src/main/java/com/github/scribejava/httpclient/ahc/AhcHttpClient.java new file mode 100644 index 000000000..5c9b87249 --- /dev/null +++ b/scribejava-httpclient-ahc/src/main/java/com/github/scribejava/httpclient/ahc/AhcHttpClient.java @@ -0,0 +1,132 @@ +package com.github.scribejava.httpclient.ahc; + +import com.github.scribejava.core.httpclient.AbstractAsyncOnlyHttpClient; +import com.github.scribejava.core.httpclient.multipart.MultipartPayload; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Verb; +import org.asynchttpclient.AsyncHttpClient; +import org.asynchttpclient.DefaultAsyncHttpClient; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.Future; + +import java.io.File; +import org.asynchttpclient.AsyncHttpClientConfig; +import org.asynchttpclient.BoundRequestBuilder; + +public class AhcHttpClient extends AbstractAsyncOnlyHttpClient { + + private final AsyncHttpClient client; + + public AhcHttpClient() { + this(AhcHttpClientConfig.defaultConfig()); + } + + public AhcHttpClient(AhcHttpClientConfig ahcConfig) { + final AsyncHttpClientConfig clientConfig = ahcConfig.getClientConfig(); + client = clientConfig == null ? new DefaultAsyncHttpClient() : new DefaultAsyncHttpClient(clientConfig); + } + + public AhcHttpClient(AsyncHttpClient ahcClient) { + client = ahcClient; + } + + @Override + public void close() throws IOException { + client.close(); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + byte[] bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter) { + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodySetter.BYTE_ARRAY, bodyContents, callback, + converter); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + MultipartPayload bodyContents, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + + throw new UnsupportedOperationException("AhcHttpClient does not support MultipartPayload yet."); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + String bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter) { + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodySetter.STRING, bodyContents, callback, + converter); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + File bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter) { + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodySetter.FILE, bodyContents, callback, + converter); + } + + private Future doExecuteAsync(String userAgent, Map headers, Verb httpVerb, + String completeUrl, BodySetter bodySetter, Object bodyContents, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + final BoundRequestBuilder boundRequestBuilder; + switch (httpVerb) { + case GET: + boundRequestBuilder = client.prepareGet(completeUrl); + break; + case POST: + boundRequestBuilder = client.preparePost(completeUrl); + break; + case PUT: + boundRequestBuilder = client.preparePut(completeUrl); + break; + case DELETE: + boundRequestBuilder = client.prepareDelete(completeUrl); + break; + default: + throw new IllegalArgumentException("message build error: unknown verb type"); + } + + if (httpVerb.isPermitBody()) { + if (!headers.containsKey(CONTENT_TYPE)) { + boundRequestBuilder.addHeader(CONTENT_TYPE, DEFAULT_CONTENT_TYPE); + } + bodySetter.setBody(boundRequestBuilder, bodyContents); + } + + for (Map.Entry header : headers.entrySet()) { + boundRequestBuilder.addHeader(header.getKey(), header.getValue()); + } + + if (userAgent != null) { + boundRequestBuilder.setHeader(OAuthConstants.USER_AGENT_HEADER_NAME, userAgent); + } + + return boundRequestBuilder.execute(new OAuthAsyncCompletionHandler<>(callback, converter)); + } + + private enum BodySetter { + BYTE_ARRAY { + @Override + BoundRequestBuilder setBody(BoundRequestBuilder requestBuilder, Object bodyContents) { + return requestBuilder.setBody((byte[]) bodyContents); + } + }, + STRING { + @Override + BoundRequestBuilder setBody(BoundRequestBuilder requestBuilder, Object bodyContents) { + return requestBuilder.setBody((String) bodyContents); + } + }, + FILE { + @Override + BoundRequestBuilder setBody(BoundRequestBuilder requestBuilder, Object bodyContents) { + return requestBuilder.setBody((File) bodyContents); + } + }; + + abstract BoundRequestBuilder setBody(BoundRequestBuilder requestBuilder, Object bodyContents); + } +} diff --git a/scribejava-httpclient-ahc/src/main/java/com/github/scribejava/httpclient/ahc/AhcHttpClientConfig.java b/scribejava-httpclient-ahc/src/main/java/com/github/scribejava/httpclient/ahc/AhcHttpClientConfig.java new file mode 100644 index 000000000..490eaf2e6 --- /dev/null +++ b/scribejava-httpclient-ahc/src/main/java/com/github/scribejava/httpclient/ahc/AhcHttpClientConfig.java @@ -0,0 +1,26 @@ +package com.github.scribejava.httpclient.ahc; + +import com.github.scribejava.core.httpclient.HttpClientConfig; +import org.asynchttpclient.AsyncHttpClientConfig; + +public class AhcHttpClientConfig implements HttpClientConfig { + + private final AsyncHttpClientConfig clientConfig; + + public AhcHttpClientConfig(AsyncHttpClientConfig clientConfig) { + this.clientConfig = clientConfig; + } + + public AsyncHttpClientConfig getClientConfig() { + return clientConfig; + } + + @Override + public AhcHttpClientConfig createDefaultConfig() { + return defaultConfig(); + } + + public static AhcHttpClientConfig defaultConfig() { + return new AhcHttpClientConfig(null); + } +} diff --git a/scribejava-httpclient-ahc/src/main/java/com/github/scribejava/httpclient/ahc/AhcProvider.java b/scribejava-httpclient-ahc/src/main/java/com/github/scribejava/httpclient/ahc/AhcProvider.java new file mode 100644 index 000000000..97c21dc86 --- /dev/null +++ b/scribejava-httpclient-ahc/src/main/java/com/github/scribejava/httpclient/ahc/AhcProvider.java @@ -0,0 +1,16 @@ +package com.github.scribejava.httpclient.ahc; + +import com.github.scribejava.core.httpclient.HttpClientProvider; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; + +public class AhcProvider implements HttpClientProvider { + + @Override + public HttpClient createClient(HttpClientConfig config) { + if (config instanceof AhcHttpClientConfig) { + return new AhcHttpClient((AhcHttpClientConfig) config); + } + return null; + } +} diff --git a/scribejava-httpclient-ahc/src/main/java/com/github/scribejava/httpclient/ahc/OAuthAsyncCompletionHandler.java b/scribejava-httpclient-ahc/src/main/java/com/github/scribejava/httpclient/ahc/OAuthAsyncCompletionHandler.java new file mode 100644 index 000000000..0cb77af25 --- /dev/null +++ b/scribejava-httpclient-ahc/src/main/java/com/github/scribejava/httpclient/ahc/OAuthAsyncCompletionHandler.java @@ -0,0 +1,51 @@ +package com.github.scribejava.httpclient.ahc; + +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import org.asynchttpclient.AsyncCompletionHandler; + +public class OAuthAsyncCompletionHandler extends AsyncCompletionHandler { + + private final OAuthAsyncRequestCallback callback; + private final OAuthRequest.ResponseConverter converter; + + public OAuthAsyncCompletionHandler(OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + this.callback = callback; + this.converter = converter; + } + + @Override + public T onCompleted(org.asynchttpclient.Response ahcResponse) { + try { + final Map headersMap = new HashMap<>(); + for (Map.Entry header : ahcResponse.getHeaders()) { + headersMap.put(header.getKey(), header.getValue()); + } + + final Response response = new Response(ahcResponse.getStatusCode(), ahcResponse.getStatusText(), headersMap, + ahcResponse.getResponseBodyAsStream()); + + @SuppressWarnings("unchecked") + final T t = converter == null ? (T) response : converter.convert(response); + if (callback != null) { + callback.onCompleted(t); + } + return t; + } catch (IOException | RuntimeException e) { + onThrowable(e); + return null; + } + } + + @Override + public void onThrowable(Throwable t) { + if (callback != null) { + callback.onThrowable(t); + } + } +} diff --git a/scribejava-httpclient-ahc/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider b/scribejava-httpclient-ahc/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider new file mode 100644 index 000000000..bbe752ff6 --- /dev/null +++ b/scribejava-httpclient-ahc/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider @@ -0,0 +1 @@ +com.github.scribejava.httpclient.ahc.AhcProvider diff --git a/scribejava-httpclient-ahc/src/test/java/com/github/scribejava/httpclient/ahc/AhcHttpClientTest.java b/scribejava-httpclient-ahc/src/test/java/com/github/scribejava/httpclient/ahc/AhcHttpClientTest.java new file mode 100644 index 000000000..5de2d153e --- /dev/null +++ b/scribejava-httpclient-ahc/src/test/java/com/github/scribejava/httpclient/ahc/AhcHttpClientTest.java @@ -0,0 +1,12 @@ +package com.github.scribejava.httpclient.ahc; + +import com.github.scribejava.core.AbstractClientTest; +import com.github.scribejava.core.httpclient.HttpClient; + +public class AhcHttpClientTest extends AbstractClientTest { + + @Override + protected HttpClient createNewClient() { + return new AhcHttpClient(); + } +} diff --git a/scribejava-httpclient-apache/pom.xml b/scribejava-httpclient-apache/pom.xml new file mode 100644 index 000000000..1dc9dd53c --- /dev/null +++ b/scribejava-httpclient-apache/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + + + com.github.scribejava + scribejava + 8.3.4-SNAPSHOT + ../pom.xml + + + com.github.scribejava + scribejava-httpclient-apache + ScribeJava Apache HttpComponents HttpClient support + jar + + + + com.github.scribejava + scribejava-core + ${project.version} + + + org.apache.httpcomponents + httpclient + 4.5.13 + + + org.apache.httpcomponents + httpasyncclient + 4.1.5 + + + com.github.scribejava + scribejava-core + ${project.version} + test-jar + test + + + + + + + org.apache.felix + maven-bundle-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + diff --git a/scribejava-httpclient-apache/src/main/java/com/github/scribejava/httpclient/apache/ApacheHttpClient.java b/scribejava-httpclient-apache/src/main/java/com/github/scribejava/httpclient/apache/ApacheHttpClient.java new file mode 100644 index 000000000..8c204e67b --- /dev/null +++ b/scribejava-httpclient-apache/src/main/java/com/github/scribejava/httpclient/apache/ApacheHttpClient.java @@ -0,0 +1,126 @@ +package com.github.scribejava.httpclient.apache; + +import com.github.scribejava.core.httpclient.AbstractAsyncOnlyHttpClient; +import com.github.scribejava.core.httpclient.multipart.MultipartPayload; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Verb; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.FileEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.concurrent.Future; +import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; + +public class ApacheHttpClient extends AbstractAsyncOnlyHttpClient { + + private final CloseableHttpAsyncClient client; + + public ApacheHttpClient() { + this(ApacheHttpClientConfig.defaultConfig()); + } + + public ApacheHttpClient(ApacheHttpClientConfig config) { + this(config.getHttpAsyncClientBuilder()); + } + + public ApacheHttpClient(HttpAsyncClientBuilder builder) { + this(builder.build()); + } + + public ApacheHttpClient(CloseableHttpAsyncClient client) { + this.client = client; + this.client.start(); + } + + @Override + public void close() throws IOException { + client.close(); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + byte[] bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter) { + final HttpEntity entity = bodyContents == null ? null : new ByteArrayEntity(bodyContents); + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, entity, callback, converter); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + MultipartPayload bodyContents, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + + throw new UnsupportedOperationException("ApacheHttpClient does not support MultipartPayload yet."); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + String bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter) { + final HttpEntity entity = bodyContents == null ? null : new StringEntity(bodyContents, StandardCharsets.UTF_8); + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, entity, callback, converter); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + File bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter) { + final HttpEntity entity = bodyContents == null ? null : new FileEntity(bodyContents); + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, entity, callback, converter); + } + + private Future doExecuteAsync(String userAgent, Map headers, Verb httpVerb, + String completeUrl, HttpEntity entity, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + final RequestBuilder builder = getRequestBuilder(httpVerb); + builder.setUri(completeUrl); + + if (httpVerb.isPermitBody()) { + if (!headers.containsKey(CONTENT_TYPE)) { + builder.addHeader(CONTENT_TYPE, DEFAULT_CONTENT_TYPE); + } + builder.setEntity(entity); + } + + for (Map.Entry header : headers.entrySet()) { + builder.addHeader(header.getKey(), header.getValue()); + } + + if (userAgent != null) { + builder.setHeader(OAuthConstants.USER_AGENT_HEADER_NAME, userAgent); + } + final OAuthAsyncCompletionHandler handler = new OAuthAsyncCompletionHandler<>(callback, converter); + final Future future = client.execute(builder.build(), handler); + return new ApacheHttpFuture<>(future, handler); + } + + private static RequestBuilder getRequestBuilder(Verb httpVerb) { + switch (httpVerb) { + case GET: + return RequestBuilder.get(); + case PUT: + return RequestBuilder.put(); + case DELETE: + return RequestBuilder.delete(); + case HEAD: + return RequestBuilder.head(); + case POST: + return RequestBuilder.post(); + case PATCH: + return RequestBuilder.patch(); + case TRACE: + return RequestBuilder.trace(); + case OPTIONS: + return RequestBuilder.options(); + default: + throw new IllegalArgumentException("message build error: unknown verb type"); + } + } +} diff --git a/scribejava-httpclient-apache/src/main/java/com/github/scribejava/httpclient/apache/ApacheHttpClientConfig.java b/scribejava-httpclient-apache/src/main/java/com/github/scribejava/httpclient/apache/ApacheHttpClientConfig.java new file mode 100644 index 000000000..2a4f3a5b0 --- /dev/null +++ b/scribejava-httpclient-apache/src/main/java/com/github/scribejava/httpclient/apache/ApacheHttpClientConfig.java @@ -0,0 +1,26 @@ +package com.github.scribejava.httpclient.apache; + +import com.github.scribejava.core.httpclient.HttpClientConfig; +import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; + +public class ApacheHttpClientConfig implements HttpClientConfig { + + private final HttpAsyncClientBuilder httpAsyncClientBuilder; + + public ApacheHttpClientConfig(HttpAsyncClientBuilder httpAsyncClientBuilder) { + this.httpAsyncClientBuilder = httpAsyncClientBuilder; + } + + public HttpAsyncClientBuilder getHttpAsyncClientBuilder() { + return httpAsyncClientBuilder; + } + + @Override + public HttpClientConfig createDefaultConfig() { + return defaultConfig(); + } + + public static ApacheHttpClientConfig defaultConfig() { + return new ApacheHttpClientConfig(HttpAsyncClientBuilder.create()); + } +} diff --git a/scribejava-httpclient-apache/src/main/java/com/github/scribejava/httpclient/apache/ApacheHttpFuture.java b/scribejava-httpclient-apache/src/main/java/com/github/scribejava/httpclient/apache/ApacheHttpFuture.java new file mode 100644 index 000000000..47c098383 --- /dev/null +++ b/scribejava-httpclient-apache/src/main/java/com/github/scribejava/httpclient/apache/ApacheHttpFuture.java @@ -0,0 +1,44 @@ +package com.github.scribejava.httpclient.apache; + +import org.apache.http.HttpResponse; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class ApacheHttpFuture implements Future { + + private final Future future; + private final OAuthAsyncCompletionHandler handler; + + public ApacheHttpFuture(Future future, OAuthAsyncCompletionHandler handler) { + this.future = future; + this.handler = handler; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return future.cancel(mayInterruptIfRunning); + } + + @Override + public boolean isCancelled() { + return future.isCancelled(); + } + + @Override + public boolean isDone() { + return future.isDone(); + } + + @Override + public T get() throws InterruptedException, ExecutionException { + return handler.getResult(); + } + + @Override + public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + return handler.getResult(timeout, unit); + } +} diff --git a/scribejava-httpclient-apache/src/main/java/com/github/scribejava/httpclient/apache/ApacheProvider.java b/scribejava-httpclient-apache/src/main/java/com/github/scribejava/httpclient/apache/ApacheProvider.java new file mode 100644 index 000000000..553972d1d --- /dev/null +++ b/scribejava-httpclient-apache/src/main/java/com/github/scribejava/httpclient/apache/ApacheProvider.java @@ -0,0 +1,16 @@ +package com.github.scribejava.httpclient.apache; + +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.github.scribejava.core.httpclient.HttpClientProvider; + +public class ApacheProvider implements HttpClientProvider { + + @Override + public HttpClient createClient(HttpClientConfig httpClientConfig) { + if (httpClientConfig instanceof ApacheHttpClientConfig) { + return new ApacheHttpClient((ApacheHttpClientConfig) httpClientConfig); + } + return null; + } +} diff --git a/scribejava-httpclient-apache/src/main/java/com/github/scribejava/httpclient/apache/OAuthAsyncCompletionHandler.java b/scribejava-httpclient-apache/src/main/java/com/github/scribejava/httpclient/apache/OAuthAsyncCompletionHandler.java new file mode 100644 index 000000000..7779b83e7 --- /dev/null +++ b/scribejava-httpclient-apache/src/main/java/com/github/scribejava/httpclient/apache/OAuthAsyncCompletionHandler.java @@ -0,0 +1,110 @@ +package com.github.scribejava.httpclient.apache; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.concurrent.FutureCallback; + +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthRequest.ResponseConverter; +import com.github.scribejava.core.model.Response; +import java.io.IOException; +import java.io.InputStream; +import org.apache.http.HttpEntity; + +public class OAuthAsyncCompletionHandler implements FutureCallback { + + private final OAuthAsyncRequestCallback callback; + private final ResponseConverter converter; + private final CountDownLatch latch; + private T result; + private Exception exception; + + public OAuthAsyncCompletionHandler(OAuthAsyncRequestCallback callback, ResponseConverter converter) { + this.callback = callback; + this.converter = converter; + this.latch = new CountDownLatch(1); + } + + @Override + public void completed(HttpResponse httpResponse) { + try { + final Map headersMap = new HashMap<>(); + for (Header header : httpResponse.getAllHeaders()) { + headersMap.put(header.getName(), header.getValue()); + } + + final StatusLine statusLine = httpResponse.getStatusLine(); + + final HttpEntity httpEntity = httpResponse.getEntity(); + final InputStream contentStream = httpEntity == null ? null : httpEntity.getContent(); + final Response response = new Response(statusLine.getStatusCode(), statusLine.getReasonPhrase(), headersMap, + contentStream, contentStream); + + @SuppressWarnings("unchecked") + final T t = converter == null ? (T) response : converter.convert(response); + result = t; + if (callback != null) { + callback.onCompleted(result); + } + } catch (IOException | RuntimeException e) { + exception = e; + if (callback != null) { + callback.onThrowable(e); + } + } finally { + latch.countDown(); + } + } + + @Override + public void failed(Exception e) { + exception = e; + try { + if (callback != null) { + callback.onThrowable(e); + } + } finally { + latch.countDown(); + } + } + + @Override + public void cancelled() { + exception = new CancellationException(); + try { + if (callback != null) { + callback.onThrowable(exception); + } + } finally { + latch.countDown(); + } + } + + public T getResult() throws InterruptedException, ExecutionException { + latch.await(); + if (exception != null) { + throw new ExecutionException(exception); + } + return result; + } + + public T getResult(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + + if (!latch.await(timeout, unit)) { + throw new TimeoutException(); + } + if (exception != null) { + throw new ExecutionException(exception); + } + return result; + } +} diff --git a/scribejava-httpclient-apache/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider b/scribejava-httpclient-apache/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider new file mode 100644 index 000000000..651910028 --- /dev/null +++ b/scribejava-httpclient-apache/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider @@ -0,0 +1 @@ +com.github.scribejava.httpclient.apache.ApacheProvider diff --git a/scribejava-httpclient-apache/src/test/java/com/github/scribejava/httpclient/apache/ApacheHttpClientTest.java b/scribejava-httpclient-apache/src/test/java/com/github/scribejava/httpclient/apache/ApacheHttpClientTest.java new file mode 100644 index 000000000..03924d81e --- /dev/null +++ b/scribejava-httpclient-apache/src/test/java/com/github/scribejava/httpclient/apache/ApacheHttpClientTest.java @@ -0,0 +1,13 @@ +package com.github.scribejava.httpclient.apache; + +import com.github.scribejava.core.AbstractClientTest; +import com.github.scribejava.core.httpclient.HttpClient; + +public class ApacheHttpClientTest extends AbstractClientTest { + + @Override + protected HttpClient createNewClient() { + return new ApacheHttpClient(); + } + +} diff --git a/scribejava-httpclient-apache/src/test/java/com/github/scribejava/httpclient/apache/OAuthAsyncCompletionHandlerTest.java b/scribejava-httpclient-apache/src/test/java/com/github/scribejava/httpclient/apache/OAuthAsyncCompletionHandlerTest.java new file mode 100644 index 000000000..684ac5c62 --- /dev/null +++ b/scribejava-httpclient-apache/src/test/java/com/github/scribejava/httpclient/apache/OAuthAsyncCompletionHandlerTest.java @@ -0,0 +1,193 @@ +package com.github.scribejava.httpclient.apache; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; + +import org.apache.http.HttpResponse; +import org.apache.http.ProtocolVersion; +import org.apache.http.entity.BasicHttpEntity; +import org.apache.http.message.BasicHttpResponse; +import org.apache.http.message.BasicStatusLine; +import org.junit.Before; +import org.junit.Test; + +import com.github.scribejava.core.exceptions.OAuthException; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import static org.junit.Assert.assertThrows; +import org.junit.function.ThrowingRunnable; + +public class OAuthAsyncCompletionHandlerTest { + + private static final AllGoodResponseConverter ALL_GOOD_RESPONSE_CONVERTER = new AllGoodResponseConverter(); + private static final ExceptionResponseConverter EXCEPTION_RESPONSE_CONVERTER = new ExceptionResponseConverter(); + private static final OAuthExceptionResponseConverter OAUTH_EXCEPTION_RESPONSE_CONVERTER + = new OAuthExceptionResponseConverter(); + + private OAuthAsyncCompletionHandler handler; + private TestCallback callback; + + private static class TestCallback implements OAuthAsyncRequestCallback { + + private Throwable throwable; + private String response; + + @Override + public void onCompleted(String response) { + this.response = response; + } + + @Override + public void onThrowable(Throwable throwable) { + this.throwable = throwable; + } + + public Throwable getThrowable() { + return throwable; + } + + public String getResponse() { + return response; + } + + } + + @Before + public void setUp() { + callback = new TestCallback(); + } + + @Test + public void shouldReleaseLatchOnSuccess() throws Exception { + handler = new OAuthAsyncCompletionHandler<>(callback, ALL_GOOD_RESPONSE_CONVERTER); + final HttpResponse response + = new BasicHttpResponse(new BasicStatusLine(new ProtocolVersion("4", 1, 1), 200, "ok")); + final BasicHttpEntity entity = new BasicHttpEntity(); + entity.setContent(new ByteArrayInputStream(new byte[0])); + response.setEntity(entity); + handler.completed(response); + assertNotNull(callback.getResponse()); + assertNull(callback.getThrowable()); + // verify latch is released + assertEquals("All good", handler.getResult()); + } + + @Test + public void shouldReleaseLatchOnIOException() { + handler = new OAuthAsyncCompletionHandler<>(callback, EXCEPTION_RESPONSE_CONVERTER); + final HttpResponse response + = new BasicHttpResponse(new BasicStatusLine(new ProtocolVersion("4", 1, 1), 200, "ok")); + final BasicHttpEntity entity = new BasicHttpEntity(); + entity.setContent(new ByteArrayInputStream(new byte[0])); + response.setEntity(entity); + handler.completed(response); + assertNull(callback.getResponse()); + assertNotNull(callback.getThrowable()); + assertTrue(callback.getThrowable() instanceof IOException); + // verify latch is released + assertThrows(ExecutionException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + handler.getResult(); + } + }); + } + + @Test + public void shouldReportOAuthException() { + handler = new OAuthAsyncCompletionHandler<>(callback, OAUTH_EXCEPTION_RESPONSE_CONVERTER); + final HttpResponse response + = new BasicHttpResponse(new BasicStatusLine(new ProtocolVersion("4", 1, 1), 200, "ok")); + final BasicHttpEntity entity = new BasicHttpEntity(); + entity.setContent(new ByteArrayInputStream(new byte[0])); + response.setEntity(entity); + handler.completed(response); + assertNull(callback.getResponse()); + assertNotNull(callback.getThrowable()); + assertTrue(callback.getThrowable() instanceof OAuthException); + // verify latch is released + assertThrows(ExecutionException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + handler.getResult(); + } + }); + } + + @Test + public void shouldReleaseLatchOnCancel() { + handler = new OAuthAsyncCompletionHandler<>(callback, ALL_GOOD_RESPONSE_CONVERTER); + final HttpResponse response + = new BasicHttpResponse(new BasicStatusLine(new ProtocolVersion("4", 1, 1), 200, "ok")); + final BasicHttpEntity entity = new BasicHttpEntity(); + entity.setContent(new ByteArrayInputStream(new byte[0])); + response.setEntity(entity); + handler.cancelled(); + assertNull(callback.getResponse()); + assertNotNull(callback.getThrowable()); + assertTrue(callback.getThrowable() instanceof CancellationException); + // verify latch is released + assertThrows(ExecutionException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + handler.getResult(); + } + }); + } + + @Test + public void shouldReleaseLatchOnFailure() { + handler = new OAuthAsyncCompletionHandler<>(callback, ALL_GOOD_RESPONSE_CONVERTER); + final HttpResponse response + = new BasicHttpResponse(new BasicStatusLine(new ProtocolVersion("4", 1, 1), 200, "ok")); + final BasicHttpEntity entity = new BasicHttpEntity(); + entity.setContent(new ByteArrayInputStream(new byte[0])); + response.setEntity(entity); + handler.failed(new RuntimeException()); + assertNull(callback.getResponse()); + assertNotNull(callback.getThrowable()); + assertTrue(callback.getThrowable() instanceof RuntimeException); + // verify latch is released + assertThrows(ExecutionException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + handler.getResult(); + } + }); + } + + private static class AllGoodResponseConverter implements OAuthRequest.ResponseConverter { + + @Override + public String convert(Response response) throws IOException { + response.close(); + return "All good"; + } + } + + private static class ExceptionResponseConverter implements OAuthRequest.ResponseConverter { + + @Override + public String convert(Response response) throws IOException { + response.close(); + throw new IOException("Failed to convert"); + } + } + + private static class OAuthExceptionResponseConverter implements OAuthRequest.ResponseConverter { + + @Override + public String convert(Response response) throws IOException { + response.close(); + throw new OAuthException("bad oauth"); + } + } +} diff --git a/scribejava-httpclient-armeria/pom.xml b/scribejava-httpclient-armeria/pom.xml new file mode 100644 index 000000000..54e58c619 --- /dev/null +++ b/scribejava-httpclient-armeria/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + + com.github.scribejava + scribejava + 8.3.4-SNAPSHOT + ../pom.xml + + + com.github.scribejava + scribejava-httpclient-armeria + ScribeJava Async Armeria Client support + jar + + + + com.github.scribejava + scribejava-core + ${project.version} + + + org.slf4j + slf4j-simple + 2.0.3 + test + + + com.linecorp.armeria + armeria + 1.20.2 + + + com.github.scribejava + scribejava-core + ${project.version} + test-jar + test + + + + + + + org.apache.felix + maven-bundle-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + + + 8 + + diff --git a/scribejava-httpclient-armeria/src/main/java/com/github/scribejava/httpclient/armeria/ArmeriaHttpClient.java b/scribejava-httpclient-armeria/src/main/java/com/github/scribejava/httpclient/armeria/ArmeriaHttpClient.java new file mode 100644 index 000000000..982ddc63a --- /dev/null +++ b/scribejava-httpclient-armeria/src/main/java/com/github/scribejava/httpclient/armeria/ArmeriaHttpClient.java @@ -0,0 +1,375 @@ +package com.github.scribejava.httpclient.armeria; + +import static java.util.Objects.requireNonNull; + +import com.github.scribejava.core.httpclient.AbstractAsyncOnlyHttpClient; +import com.github.scribejava.core.httpclient.multipart.MultipartPayload; +import com.github.scribejava.core.httpclient.multipart.MultipartUtils; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.linecorp.armeria.client.WebClient; +import com.linecorp.armeria.common.AggregatedHttpResponse; +import com.linecorp.armeria.common.HttpData; +import com.linecorp.armeria.common.HttpMethod; +import com.linecorp.armeria.common.HttpResponse; +import com.linecorp.armeria.common.HttpStatus; +import com.linecorp.armeria.common.MediaType; +import com.linecorp.armeria.common.RequestHeaders; +import com.linecorp.armeria.common.RequestHeadersBuilder; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.nio.file.Files; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Supplier; + +/** + * An implementation of {@link AbstractAsyncOnlyHttpClient} based on + * Armeria HTTP client. + */ +public class ArmeriaHttpClient extends AbstractAsyncOnlyHttpClient { + + /** + * A builder of new instances of Armeria's {@link WebClient} + */ + private final ArmeriaWebClientBuilder clientBuilder; + /** + * A list of cached Endpoints. It helps avoiding building a new Endpoint per each request. + */ + private final Map httpClients = new HashMap<>(); + /** + * A read/write lock to access the list of cached Endpoints concurrently. + */ + private final ReentrantReadWriteLock httpClientsLock = new ReentrantReadWriteLock(); + + public ArmeriaHttpClient() { + this(ArmeriaHttpClientConfig.defaultConfig()); + } + + public ArmeriaHttpClient(ArmeriaHttpClientConfig config) { + clientBuilder = config.createClientBuilder(); + } + + /** + * Cleans up the list of cached Endpoints. + */ + @Override + public void close() { + final Lock writeLock = httpClientsLock.writeLock(); + writeLock.lock(); + try { + httpClients.clear(); + } finally { + writeLock.unlock(); + } + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + byte[] bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter) { + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, new BytesBody(bodyContents), callback, + converter); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + MultipartPayload bodyContents, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, new MultipartBody(bodyContents), callback, + converter); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + String bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter) { + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, new StringBody(bodyContents), callback, + converter); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + File bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter) { + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, new FileBody(bodyContents), callback, + converter); + } + + private CompletableFuture doExecuteAsync(String userAgent, Map headers, Verb httpVerb, + String completeUrl, Supplier contentSupplier, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + // Get the URI and Path + final URI uri = URI.create(completeUrl); + final String path = getServicePath(uri); + + // Fetch/Create WebClient instance for a given Endpoint + final WebClient client = getClient(uri); + + // Build HTTP request + final RequestHeadersBuilder headersBuilder = RequestHeaders.of(getHttpMethod(httpVerb), path).toBuilder(); + + headersBuilder.add(headers.entrySet()); + if (userAgent != null) { + headersBuilder.add(OAuthConstants.USER_AGENT_HEADER_NAME, userAgent); + } + + // Build the request body and execute HTTP request + final HttpResponse response; + if (httpVerb.isPermitBody()) { // POST, PUT, PATCH and DELETE methods + final HttpData contents = contentSupplier.get(); + if (httpVerb.isRequiresBody() && contents == null) { // POST or PUT methods + throw new IllegalArgumentException("Contents missing for request method " + httpVerb.name()); + } + + if (headersBuilder.contentType() == null) { + headersBuilder.contentType(MediaType.FORM_DATA); + } + + if (contents != null) { + response = client.execute(headersBuilder.build(), contents); + } else { + response = client.execute(headersBuilder.build()); + } + } else { + response = client.execute(headersBuilder.build()); + } + + // Aggregate HTTP response (asynchronously) and return the result Future + return response.aggregate() + .thenApply(aggregatedResponse -> whenResponseComplete(callback, converter, aggregatedResponse)) + .exceptionally(throwable -> completeExceptionally(callback, throwable)); + } + + /** + * Provides an instance of {@link WebClient} for a given endpoint {@link URI} based on an endpoint as + * {@code scheme://authority}. + * + * @param uri an endpoint {@link URI} + * @return {@link WebClient} instance + */ + private WebClient getClient(URI uri) { + final String endpoint = getEndPoint(uri); + + WebClient client; + final Lock readLock = httpClientsLock.readLock(); + readLock.lock(); + try { + client = httpClients.get(endpoint); + } finally { + readLock.unlock(); + } + + if (client != null) { + return client; + } + + client = clientBuilder.newWebClient( + requireNonNull(uri.getScheme(), "scheme"), + requireNonNull(uri.getAuthority(), "authority")); + + final Lock writeLock = httpClientsLock.writeLock(); + writeLock.lock(); + try { + if (!httpClients.containsKey(endpoint)) { + httpClients.put(endpoint, client); + return client; + } else { + return httpClients.get(endpoint); + } + } finally { + writeLock.unlock(); + } + } + + /** + * Extracts {@code scheme} and {@code authority} portion of the {@link URI}. + * + * Assuming the {@link URI} as the following: {@code URI = scheme:[//authority]path[?query][#fragment]} + */ + private static String getEndPoint(URI uri) { + return requireNonNull(uri.getScheme(), "scheme") + "://" + requireNonNull(uri.getAuthority(), "authority"); + } + + /** + * Extracts {@code path}, {@code query} and {@code fragment} portion of the {@link URI}. + * + * Assuming the {@link URI} as the following: {@code URI = scheme:[//authority]path[?query][#fragment]} + */ + private static String getServicePath(URI uri) { + final StringBuilder builder = new StringBuilder() + .append(requireNonNull(uri.getPath(), "path")); + final String query = uri.getQuery(); + if (query != null) { + builder.append('?').append(query); + } + final String fragment = uri.getFragment(); + if (fragment != null) { + builder.append('#').append(fragment); + } + return builder.toString(); + } + + /** + * Maps {@link Verb} to {@link HttpMethod} + * + * @param httpVerb a {@link Verb} to match with {@link HttpMethod} + * @return {@link HttpMethod} corresponding to the parameter + */ + private static HttpMethod getHttpMethod(Verb httpVerb) { + switch (httpVerb) { + case GET: + return HttpMethod.GET; + case POST: + return HttpMethod.POST; + case PUT: + return HttpMethod.PUT; + case DELETE: + return HttpMethod.DELETE; + case HEAD: + return HttpMethod.HEAD; + case OPTIONS: + return HttpMethod.OPTIONS; + case TRACE: + return HttpMethod.TRACE; + case PATCH: + return HttpMethod.PATCH; + default: + throw new IllegalArgumentException( + "message build error: unsupported HTTP method: " + httpVerb.name()); + } + } + + // Response asynchronous handlers + /** + * Converts {@link AggregatedHttpResponse} to {@link Response} + * + * @param aggregatedResponse an instance of {@link AggregatedHttpResponse} to convert to {@link Response} + * @return a {@link Response} converted from {@link AggregatedHttpResponse} + */ + private Response convertResponse(AggregatedHttpResponse aggregatedResponse) { + final Map headersMap = new HashMap<>(); + aggregatedResponse.headers().forEach((header, value) -> headersMap.put(header.toString(), value)); + + final HttpStatus status = aggregatedResponse.status(); + final InputStream inputStream = aggregatedResponse.content().toInputStream(); + + return new Response(status.code(), status.reasonPhrase(), headersMap, inputStream, inputStream); + } + + /** + * Converts {@link AggregatedHttpResponse} to {@link Response} upon its aggregation completion and invokes + * {@link OAuthAsyncRequestCallback} for it. + * + * @param callback a {@link OAuthAsyncRequestCallback} callback to invoke upon response completion + * @param converter an optional {@link OAuthRequest.ResponseConverter} result converter for {@link Response} + * @param aggregatedResponse a source {@link AggregatedHttpResponse} to handle + * @param converter {@link OAuthRequest.ResponseConverter} specific type or {@link Response} + * @return either instance of {@link Response} or converted result based on {@link OAuthRequest.ResponseConverter} + */ + private T whenResponseComplete(OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter, AggregatedHttpResponse aggregatedResponse) { + final Response response = convertResponse(aggregatedResponse); + try { + @SuppressWarnings("unchecked") + final T t = converter == null ? (T) response : converter.convert(response); + if (callback != null) { + callback.onCompleted(t); + } + return t; + } catch (IOException | RuntimeException e) { + return completeExceptionally(callback, e); + } + } + + /** + * Invokes {@link OAuthAsyncRequestCallback} upon {@link Throwable} error result + * + * @param callback a {@link OAuthAsyncRequestCallback} callback to invoke upon response completion + * @param throwable a {@link Throwable} error result + * @param converter {@link OAuthRequest.ResponseConverter} specific type or {@link Response} + * @return null + */ + private T completeExceptionally(OAuthAsyncRequestCallback callback, Throwable throwable) { + if (callback != null) { + callback.onThrowable(throwable); + } + return null; + } + + // Body type suppliers + private static class BytesBody implements Supplier { + + private final byte[] bodyContents; + + BytesBody(byte[] bodyContents) { + this.bodyContents = bodyContents; + } + + @Override + public HttpData get() { + return (bodyContents != null) ? HttpData.wrap(bodyContents) : null; + } + } + + private static class StringBody implements Supplier { + + private final String bodyContents; + + StringBody(String bodyContents) { + this.bodyContents = bodyContents; + } + + @Override + public HttpData get() { + return (bodyContents != null) ? HttpData.ofUtf8(bodyContents) : null; + } + } + + private static class FileBody implements Supplier { + + private final File bodyContents; + + FileBody(File bodyContents) { + this.bodyContents = bodyContents; + } + + @Override + public HttpData get() { + try { + return (bodyContents != null) + ? HttpData.wrap(Files.readAllBytes(bodyContents.toPath())) + : null; + } catch (IOException ioE) { + throw new RuntimeException(ioE); + } + } + } + + private static class MultipartBody implements Supplier { + + private final MultipartPayload bodyContents; + + MultipartBody(MultipartPayload bodyContents) { + this.bodyContents = bodyContents; + } + + @Override + public HttpData get() { + try { + return (bodyContents != null) + ? HttpData.wrap(MultipartUtils.getPayload(bodyContents).toByteArray()) + : null; + } catch (IOException ioE) { + throw new RuntimeException(ioE); + } + } + } +} diff --git a/scribejava-httpclient-armeria/src/main/java/com/github/scribejava/httpclient/armeria/ArmeriaHttpClientConfig.java b/scribejava-httpclient-armeria/src/main/java/com/github/scribejava/httpclient/armeria/ArmeriaHttpClientConfig.java new file mode 100644 index 000000000..f9d494f52 --- /dev/null +++ b/scribejava-httpclient-armeria/src/main/java/com/github/scribejava/httpclient/armeria/ArmeriaHttpClientConfig.java @@ -0,0 +1,93 @@ +package com.github.scribejava.httpclient.armeria; + +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.linecorp.armeria.client.ClientFactory; +import com.linecorp.armeria.client.ClientOptions; +import com.linecorp.armeria.client.HttpClient; +import com.linecorp.armeria.client.logging.LoggingClient; +import com.linecorp.armeria.client.retry.RetryingClient; +import com.linecorp.armeria.common.SessionProtocol; +import java.util.function.Function; + +public class ArmeriaHttpClientConfig implements HttpClientConfig { + + private static final SessionProtocol DEFAULT_PROTOCOL_PREFERENCE = SessionProtocol.H1; // H1 or H2 + + private final ClientOptions clientOptions; + private final ClientFactory clientFactory; + private SessionProtocol protocolPreference; + private Function retry; + private Function logging; + + /** + * Creates new {@link ArmeriaHttpClientConfig} using provided {@link ClientOptions} and {@link ClientFactory}. + * + * @param clientOptions clientOptions + * @param clientFactory clientFactory + */ + public ArmeriaHttpClientConfig(ClientOptions clientOptions, ClientFactory clientFactory) { + this.clientOptions = clientOptions; + this.clientFactory = clientFactory; + protocolPreference = DEFAULT_PROTOCOL_PREFERENCE; + } + + /** + * Creates new {@link HttpClientConfig} using default settings. + * + * @return new {@link HttpClientConfig} using default settings. + */ + @Override + public HttpClientConfig createDefaultConfig() { + return defaultConfig(); + } + + /** + * Creates new {@link ArmeriaHttpClientConfig} using default settings. + * + * @return ArmeriaHttpClientConfig + */ + public static ArmeriaHttpClientConfig defaultConfig() { + return new ArmeriaHttpClientConfig(null, null); + } + + /** + * Selects which protocol shall take preference when generic protocol scheme used by the URL, like {@code http} or + * {@code https}. + * + * @param protocolPreference specifies which protocol shall take preference. Acceptable values: + * {@link SessionProtocol#H1} and {@link SessionProtocol#H2} + */ + public void setProtocolPreference(SessionProtocol protocolPreference) { + if (protocolPreference != SessionProtocol.H1 && protocolPreference != SessionProtocol.H2) { + throw new IllegalArgumentException("Invalid protocolPreference: " + protocolPreference); + } + this.protocolPreference = protocolPreference; + } + + public ArmeriaHttpClientConfig withProtocolPreference(SessionProtocol protocolPreference) { + setProtocolPreference(protocolPreference); + return this; + } + + public void setRetry(Function retry) { + this.retry = retry; + } + + public ArmeriaHttpClientConfig withRetry(Function retry) { + this.retry = retry; + return this; + } + + public void setLogging(Function logging) { + this.logging = logging; + } + + public ArmeriaHttpClientConfig withLogging(Function logging) { + this.logging = logging; + return this; + } + + ArmeriaWebClientBuilder createClientBuilder() { + return new ArmeriaWebClientBuilder(clientOptions, clientFactory, protocolPreference, retry, logging); + } +} diff --git a/scribejava-httpclient-armeria/src/main/java/com/github/scribejava/httpclient/armeria/ArmeriaProvider.java b/scribejava-httpclient-armeria/src/main/java/com/github/scribejava/httpclient/armeria/ArmeriaProvider.java new file mode 100644 index 000000000..323eb7599 --- /dev/null +++ b/scribejava-httpclient-armeria/src/main/java/com/github/scribejava/httpclient/armeria/ArmeriaProvider.java @@ -0,0 +1,16 @@ +package com.github.scribejava.httpclient.armeria; + +import com.github.scribejava.core.httpclient.HttpClientProvider; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; + +public class ArmeriaProvider implements HttpClientProvider { + + @Override + public HttpClient createClient(HttpClientConfig config) { + if (config instanceof ArmeriaHttpClientConfig) { + return new ArmeriaHttpClient((ArmeriaHttpClientConfig) config); + } + return null; + } +} diff --git a/scribejava-httpclient-armeria/src/main/java/com/github/scribejava/httpclient/armeria/ArmeriaWebClientBuilder.java b/scribejava-httpclient-armeria/src/main/java/com/github/scribejava/httpclient/armeria/ArmeriaWebClientBuilder.java new file mode 100644 index 000000000..6972fadd0 --- /dev/null +++ b/scribejava-httpclient-armeria/src/main/java/com/github/scribejava/httpclient/armeria/ArmeriaWebClientBuilder.java @@ -0,0 +1,74 @@ +package com.github.scribejava.httpclient.armeria; + +import com.linecorp.armeria.client.ClientFactory; +import com.linecorp.armeria.client.ClientOptions; +import com.linecorp.armeria.client.Endpoint; +import com.linecorp.armeria.client.HttpClient; +import com.linecorp.armeria.client.WebClient; +import com.linecorp.armeria.client.WebClientBuilder; +import com.linecorp.armeria.client.logging.LoggingClient; +import com.linecorp.armeria.client.retry.RetryingClient; +import com.linecorp.armeria.common.SessionProtocol; +import java.util.function.Function; + +/** + * A builder of {@link WebClient} using supplied configuration parameters. + */ +public class ArmeriaWebClientBuilder { + + private final ClientFactory clientFactory; + private final ClientOptions clientOptions; + private final SessionProtocol protocolPreference; + private final Function retry; + private final Function logging; + + ArmeriaWebClientBuilder(ClientOptions clientOptions, ClientFactory clientFactory, + SessionProtocol protocolPreference, Function retry, + Function logging) { + this.clientOptions = clientOptions; + this.clientFactory = clientFactory; + this.protocolPreference = protocolPreference; + this.retry = retry; + this.logging = logging; + } + + WebClient newWebClient(String scheme, String authority) { + final SessionProtocol protocol = protocol(scheme); + final Endpoint endpoint = Endpoint.parse(authority); + final WebClientBuilder clientBuilder = WebClient.builder(protocol, endpoint); + if (clientOptions != null) { + clientBuilder.options(clientOptions); + } + if (clientFactory != null) { + clientBuilder.factory(clientFactory); + } + if (retry != null) { + clientBuilder.decorator(retry); + } + if (logging != null) { + clientBuilder.decorator(logging); + } + return clientBuilder.build(); + } + + private SessionProtocol protocol(String scheme) { + final SessionProtocol protocol = SessionProtocol.of(scheme); + switch (protocol) { + case HTTP: + if (protocolPreference == SessionProtocol.H1) { + // enforce HTTP/1 protocol + return SessionProtocol.H1C; + } + break; + case HTTPS: + if (protocolPreference == SessionProtocol.H1) { + // enforce HTTP/1 protocol + return SessionProtocol.H1; + } + break; + default: + break; + } + return protocol; + } +} diff --git a/scribejava-httpclient-armeria/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider b/scribejava-httpclient-armeria/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider new file mode 100644 index 000000000..bba338db5 --- /dev/null +++ b/scribejava-httpclient-armeria/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider @@ -0,0 +1 @@ +com.github.scribejava.httpclient.armeria.ArmeriaProvider diff --git a/scribejava-httpclient-armeria/src/test/java/com/github/scribejava/httpclient/armeria/ArmeriaHttpClientTest.java b/scribejava-httpclient-armeria/src/test/java/com/github/scribejava/httpclient/armeria/ArmeriaHttpClientTest.java new file mode 100644 index 000000000..c94d6b369 --- /dev/null +++ b/scribejava-httpclient-armeria/src/test/java/com/github/scribejava/httpclient/armeria/ArmeriaHttpClientTest.java @@ -0,0 +1,88 @@ +package com.github.scribejava.httpclient.armeria; + +import com.github.scribejava.core.AbstractClientTest; +import com.github.scribejava.core.httpclient.HttpClient; +import com.linecorp.armeria.client.ClientFactory; +import com.linecorp.armeria.client.logging.LoggingClient; +import com.linecorp.armeria.client.retry.Backoff; +import com.linecorp.armeria.client.retry.RetryRule; +import com.linecorp.armeria.client.retry.RetryingClient; +import com.linecorp.armeria.common.HttpStatus; +import com.linecorp.armeria.common.logging.LogLevel; +import io.netty.channel.EventLoopGroup; +import io.netty.resolver.AbstractAddressResolver; +import io.netty.resolver.AddressResolver; +import io.netty.resolver.AddressResolverGroup; +import io.netty.util.concurrent.EventExecutor; +import io.netty.util.concurrent.Promise; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; +import org.slf4j.LoggerFactory; + +public class ArmeriaHttpClientTest extends AbstractClientTest { + + @Override + protected HttpClient createNewClient() { + // simulate DNS resolution for a mock address ("kubernetes.docker.internal") + final Function> addressRGF + = eventLoopGroup -> new MockAddressResolverGroup(); + // No-Op DNS resolver to avoid resolution issues in the unit test + final ClientFactory clientFactory = ClientFactory.builder().addressResolverGroupFactory(addressRGF).build(); + final ArmeriaHttpClientConfig config = new ArmeriaHttpClientConfig(null, clientFactory); + + // enable client-side HTTP tracing + config.setLogging(LoggingClient.builder() + .logger(LoggerFactory.getLogger("HTTP_TRACE")) + .requestLogLevel(LogLevel.valueOf("INFO")) + .successfulResponseLogLevel(LogLevel.valueOf("INFO")) + .failureResponseLogLevel(LogLevel.valueOf("WARN")) + .newDecorator()); + + // enable request retry + final Backoff retryBackoff = Backoff.of("exponential=200:10000,jitter=0.2,maxAttempts=5"); + final RetryRule retryRule = RetryRule.builder() + .onStatus(HttpStatus.SERVICE_UNAVAILABLE) + .onUnprocessed() + .thenBackoff(retryBackoff); + + return new ArmeriaHttpClient(config.withRetry(RetryingClient.newDecorator(retryRule))); + } + + // No-Op DNS resolver to avoid resolution issues in the unit test + private static class MockAddressResolverGroup extends AddressResolverGroup { + + @Override + protected AddressResolver newResolver(EventExecutor executor) { + return new MockAddressResolver(executor); + } + } + + private static class MockAddressResolver extends AbstractAddressResolver { + + private MockAddressResolver(EventExecutor executor) { + super(executor); + } + + @Override + protected boolean doIsResolved(InetSocketAddress address) { + return !address.isUnresolved(); + } + + private InetSocketAddress resolveToLoopback(InetSocketAddress unresolvedAddress) { + return new InetSocketAddress(InetAddress.getLoopbackAddress(), unresolvedAddress.getPort()); + } + + @Override + protected void doResolve(InetSocketAddress unresolvedAddress, Promise promise) { + promise.setSuccess(resolveToLoopback(unresolvedAddress)); + } + + @Override + protected void doResolveAll(InetSocketAddress unresolvedAddress, Promise> promise) { + promise.setSuccess(Collections.singletonList(resolveToLoopback(unresolvedAddress))); + } + } +} diff --git a/scribejava-httpclient-ning/pom.xml b/scribejava-httpclient-ning/pom.xml new file mode 100644 index 000000000..39696d698 --- /dev/null +++ b/scribejava-httpclient-ning/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + + + com.github.scribejava + scribejava + 8.3.4-SNAPSHOT + ../pom.xml + + + com.github.scribejava + scribejava-httpclient-ning + ScribeJava Ning Async Http Client support + jar + + + + com.github.scribejava + scribejava-core + ${project.version} + + + org.slf4j + slf4j-simple + 2.0.3 + test + + + com.ning + async-http-client + 1.9.40 + + + com.github.scribejava + scribejava-core + ${project.version} + test-jar + test + + + + + + + org.apache.felix + maven-bundle-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + diff --git a/scribejava-httpclient-ning/src/main/java/com/github/scribejava/httpclient/ning/NingHttpClient.java b/scribejava-httpclient-ning/src/main/java/com/github/scribejava/httpclient/ning/NingHttpClient.java new file mode 100644 index 000000000..52250f698 --- /dev/null +++ b/scribejava-httpclient-ning/src/main/java/com/github/scribejava/httpclient/ning/NingHttpClient.java @@ -0,0 +1,147 @@ +package com.github.scribejava.httpclient.ning; + +import com.github.scribejava.core.httpclient.AbstractAsyncOnlyHttpClient; +import com.github.scribejava.core.httpclient.multipart.MultipartPayload; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Verb; +import com.ning.http.client.AsyncHttpClient; + +import java.util.Map; +import java.util.concurrent.Future; + +import com.ning.http.client.AsyncHttpClientConfig; +import java.io.File; + +public class NingHttpClient extends AbstractAsyncOnlyHttpClient { + + private final AsyncHttpClient client; + + public NingHttpClient() { + this(NingHttpClientConfig.defaultConfig()); + } + + public NingHttpClient(NingHttpClientConfig ningConfig) { + final String ningAsyncHttpProviderClassName = ningConfig.getNingAsyncHttpProviderClassName(); + AsyncHttpClientConfig config = ningConfig.getConfig(); + if (ningAsyncHttpProviderClassName == null) { + client = config == null ? new AsyncHttpClient() : new AsyncHttpClient(config); + } else { + if (config == null) { + config = new AsyncHttpClientConfig.Builder().build(); + } + client = new AsyncHttpClient(ningAsyncHttpProviderClassName, config); + } + } + + public NingHttpClient(AsyncHttpClient client) { + this.client = client; + } + + @Override + public void close() { + client.close(); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + final byte[] bodyContents, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodySetter.BYTE_ARRAY, bodyContents, callback, + converter); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + MultipartPayload bodyContents, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + + throw new UnsupportedOperationException("NingHttpClient does not support MultipartPayload yet."); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + final String bodyContents, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodySetter.STRING, bodyContents, callback, + converter); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + final File bodyContents, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodySetter.FILE, bodyContents, callback, + converter); + } + + private Future doExecuteAsync(String userAgent, Map headers, Verb httpVerb, + String completeUrl, BodySetter bodySetter, Object bodyContents, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + final AsyncHttpClient.BoundRequestBuilder boundRequestBuilder; + switch (httpVerb) { + case GET: + boundRequestBuilder = client.prepareGet(completeUrl); + break; + case POST: + boundRequestBuilder = client.preparePost(completeUrl); + break; + case PUT: + boundRequestBuilder = client.preparePut(completeUrl); + break; + case DELETE: + boundRequestBuilder = client.prepareDelete(completeUrl); + break; + default: + throw new IllegalArgumentException("message build error: unknown verb type"); + } + + if (httpVerb.isPermitBody()) { + if (!headers.containsKey(CONTENT_TYPE)) { + boundRequestBuilder.addHeader(CONTENT_TYPE, DEFAULT_CONTENT_TYPE); + } + bodySetter.setBody(boundRequestBuilder, bodyContents); + } + + for (Map.Entry header : headers.entrySet()) { + boundRequestBuilder.addHeader(header.getKey(), header.getValue()); + } + + if (userAgent != null) { + boundRequestBuilder.setHeader(OAuthConstants.USER_AGENT_HEADER_NAME, userAgent); + } + + return boundRequestBuilder.execute(new OAuthAsyncCompletionHandler<>(callback, converter)); + } + + private enum BodySetter { + BYTE_ARRAY { + @Override + AsyncHttpClient.BoundRequestBuilder setBody(AsyncHttpClient.BoundRequestBuilder requestBuilder, + Object bodyContents) { + return requestBuilder.setBody((byte[]) bodyContents); + } + }, + STRING { + @Override + AsyncHttpClient.BoundRequestBuilder setBody(AsyncHttpClient.BoundRequestBuilder requestBuilder, + Object bodyContents) { + return requestBuilder.setBody((String) bodyContents); + } + }, + FILE { + @Override + AsyncHttpClient.BoundRequestBuilder setBody(AsyncHttpClient.BoundRequestBuilder requestBuilder, + Object bodyContents) { + return requestBuilder.setBody((File) bodyContents); + } + }; + + abstract AsyncHttpClient.BoundRequestBuilder setBody(AsyncHttpClient.BoundRequestBuilder requestBuilder, + Object bodyContents); + } +} diff --git a/scribejava-httpclient-ning/src/main/java/com/github/scribejava/httpclient/ning/NingHttpClientConfig.java b/scribejava-httpclient-ning/src/main/java/com/github/scribejava/httpclient/ning/NingHttpClientConfig.java new file mode 100644 index 000000000..6e8842cc7 --- /dev/null +++ b/scribejava-httpclient-ning/src/main/java/com/github/scribejava/httpclient/ning/NingHttpClientConfig.java @@ -0,0 +1,40 @@ +package com.github.scribejava.httpclient.ning; + +import com.github.scribejava.core.httpclient.HttpClientConfig; +import com.ning.http.client.AsyncHttpClientConfig; + +public class NingHttpClientConfig implements HttpClientConfig { + + private final AsyncHttpClientConfig config; + private String ningAsyncHttpProviderClassName; + + public NingHttpClientConfig(AsyncHttpClientConfig config) { + this.config = config; + } + + public String getNingAsyncHttpProviderClassName() { + return ningAsyncHttpProviderClassName; + } + + public void setNingAsyncHttpProviderClassName(String ningAsyncHttpProviderClassName) { + this.ningAsyncHttpProviderClassName = ningAsyncHttpProviderClassName; + } + + public NingHttpClientConfig withNingAsyncHttpProviderClassName(String ningAsyncHttpProviderClassName) { + this.ningAsyncHttpProviderClassName = ningAsyncHttpProviderClassName; + return this; + } + + public AsyncHttpClientConfig getConfig() { + return config; + } + + @Override + public NingHttpClientConfig createDefaultConfig() { + return defaultConfig(); + } + + public static NingHttpClientConfig defaultConfig() { + return new NingHttpClientConfig(null); + } +} diff --git a/scribejava-httpclient-ning/src/main/java/com/github/scribejava/httpclient/ning/NingProvider.java b/scribejava-httpclient-ning/src/main/java/com/github/scribejava/httpclient/ning/NingProvider.java new file mode 100644 index 000000000..2db967249 --- /dev/null +++ b/scribejava-httpclient-ning/src/main/java/com/github/scribejava/httpclient/ning/NingProvider.java @@ -0,0 +1,16 @@ +package com.github.scribejava.httpclient.ning; + +import com.github.scribejava.core.httpclient.HttpClientProvider; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; + +public class NingProvider implements HttpClientProvider { + + @Override + public HttpClient createClient(HttpClientConfig httpClientConfig) { + if (httpClientConfig instanceof NingHttpClientConfig) { + return new NingHttpClient((NingHttpClientConfig) httpClientConfig); + } + return null; + } +} diff --git a/scribejava-httpclient-ning/src/main/java/com/github/scribejava/httpclient/ning/OAuthAsyncCompletionHandler.java b/scribejava-httpclient-ning/src/main/java/com/github/scribejava/httpclient/ning/OAuthAsyncCompletionHandler.java new file mode 100644 index 000000000..cd8a25ce1 --- /dev/null +++ b/scribejava-httpclient-ning/src/main/java/com/github/scribejava/httpclient/ning/OAuthAsyncCompletionHandler.java @@ -0,0 +1,57 @@ +package com.github.scribejava.httpclient.ning; + +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.ning.http.client.AsyncCompletionHandler; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class OAuthAsyncCompletionHandler extends AsyncCompletionHandler { + + private final OAuthAsyncRequestCallback callback; + private final OAuthRequest.ResponseConverter converter; + + public OAuthAsyncCompletionHandler(OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + this.callback = callback; + this.converter = converter; + } + + @Override + public T onCompleted(com.ning.http.client.Response ningResponse) { + try { + final Map headersMap = new HashMap<>(); + + for (Map.Entry> header : ningResponse.getHeaders().entrySet()) { + final StringBuilder value = new StringBuilder(); + for (String str : header.getValue()) { + value.append(str); + } + headersMap.put(header.getKey(), value.toString()); + } + + final Response response = new Response(ningResponse.getStatusCode(), ningResponse.getStatusText(), + headersMap, ningResponse.getResponseBodyAsStream()); + + @SuppressWarnings("unchecked") + final T t = converter == null ? (T) response : converter.convert(response); + if (callback != null) { + callback.onCompleted(t); + } + return t; + } catch (IOException | RuntimeException e) { + onThrowable(e); + return null; + } + } + + @Override + public void onThrowable(Throwable t) { + if (callback != null) { + callback.onThrowable(t); + } + } +} diff --git a/scribejava-httpclient-ning/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider b/scribejava-httpclient-ning/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider new file mode 100644 index 000000000..9f6843994 --- /dev/null +++ b/scribejava-httpclient-ning/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider @@ -0,0 +1 @@ +com.github.scribejava.httpclient.ning.NingProvider diff --git a/scribejava-httpclient-ning/src/test/java/com/github/scribejava/httpclient/ning/MockResponse.java b/scribejava-httpclient-ning/src/test/java/com/github/scribejava/httpclient/ning/MockResponse.java new file mode 100644 index 000000000..af75bf871 --- /dev/null +++ b/scribejava-httpclient-ning/src/test/java/com/github/scribejava/httpclient/ning/MockResponse.java @@ -0,0 +1,122 @@ +package com.github.scribejava.httpclient.ning; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.util.List; + +import com.ning.http.client.FluentCaseInsensitiveStringsMap; +import com.ning.http.client.Response; +import com.ning.http.client.cookie.Cookie; +import com.ning.http.client.uri.Uri; + +public class MockResponse implements Response { + + private final int statusCode; + private final String statusText; + private final FluentCaseInsensitiveStringsMap headers; + private final byte[] body; + + public MockResponse(int statusCode, String statusText, FluentCaseInsensitiveStringsMap headers, byte[] body) { + this.statusCode = statusCode; + this.statusText = statusText; + this.headers = headers; + this.body = body; + } + + @Override + public int getStatusCode() { + return statusCode; + } + + @Override + public String getStatusText() { + return statusText; + } + + @Override + public byte[] getResponseBodyAsBytes() throws IOException { + return body; + } + + @Override + public ByteBuffer getResponseBodyAsByteBuffer() throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public InputStream getResponseBodyAsStream() throws IOException { + return new ByteArrayInputStream(getResponseBodyAsBytes()); + } + + @Override + public String getResponseBodyExcerpt(final int maxLength, final String charset) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public String getResponseBodyExcerpt(final int maxLength) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public String getResponseBody(final String charset) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public String getResponseBody() throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public Uri getUri() { + throw new UnsupportedOperationException(); + } + + @Override + public String getContentType() { + throw new UnsupportedOperationException(); + } + + @Override + public String getHeader(final String name) { + return headers.getFirstValue(name); + } + + @Override + public List getHeaders(final String name) { + return headers.get(name); + } + + @Override + public FluentCaseInsensitiveStringsMap getHeaders() { + return headers; + } + + @Override + public boolean isRedirected() { + throw new UnsupportedOperationException(); + } + + @Override + public List getCookies() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasResponseStatus() { + return true; + } + + @Override + public boolean hasResponseHeaders() { + return !this.headers.isEmpty(); + } + + @Override + public boolean hasResponseBody() { + return body != null && body.length > 0; + } +} diff --git a/scribejava-httpclient-ning/src/test/java/com/github/scribejava/httpclient/ning/NingHttpClientTest.java b/scribejava-httpclient-ning/src/test/java/com/github/scribejava/httpclient/ning/NingHttpClientTest.java new file mode 100644 index 000000000..6ebf6456f --- /dev/null +++ b/scribejava-httpclient-ning/src/test/java/com/github/scribejava/httpclient/ning/NingHttpClientTest.java @@ -0,0 +1,12 @@ +package com.github.scribejava.httpclient.ning; + +import com.github.scribejava.core.AbstractClientTest; +import com.github.scribejava.core.httpclient.HttpClient; + +public class NingHttpClientTest extends AbstractClientTest { + + @Override + protected HttpClient createNewClient() { + return new NingHttpClient(); + } +} diff --git a/scribejava-httpclient-ning/src/test/java/com/github/scribejava/httpclient/ning/OAuthAsyncCompletionHandlerTest.java b/scribejava-httpclient-ning/src/test/java/com/github/scribejava/httpclient/ning/OAuthAsyncCompletionHandlerTest.java new file mode 100644 index 000000000..7bc56e1e1 --- /dev/null +++ b/scribejava-httpclient-ning/src/test/java/com/github/scribejava/httpclient/ning/OAuthAsyncCompletionHandlerTest.java @@ -0,0 +1,100 @@ +package com.github.scribejava.httpclient.ning; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import org.junit.Before; +import org.junit.Test; + +import com.github.scribejava.core.exceptions.OAuthException; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.ning.http.client.FluentCaseInsensitiveStringsMap; + +public class OAuthAsyncCompletionHandlerTest { + + private static final AllGoodResponseConverter ALL_GOOD_RESPONSE_CONVERTER = new AllGoodResponseConverter(); + private static final OAuthExceptionResponseConverter OAUTH_EXCEPTION_RESPONSE_CONVERTER + = new OAuthExceptionResponseConverter(); + + private OAuthAsyncCompletionHandler handler; + private TestCallback callback; + + private static class TestCallback implements OAuthAsyncRequestCallback { + + private Throwable throwable; + private String response; + + @Override + public void onCompleted(String response) { + this.response = response; + } + + @Override + public void onThrowable(Throwable throwable) { + this.throwable = throwable; + } + + public Throwable getThrowable() { + return throwable; + } + + public String getResponse() { + return response; + } + + } + + @Before + public void setUp() { + callback = new TestCallback(); + } + + @Test + public void shouldReleaseLatchOnSuccess() throws Exception { + handler = new OAuthAsyncCompletionHandler<>(callback, ALL_GOOD_RESPONSE_CONVERTER); + + final com.ning.http.client.Response response + = new MockResponse(200, "ok", new FluentCaseInsensitiveStringsMap(), new byte[0]); + handler.onCompleted(response); + assertNotNull(callback.getResponse()); + assertNull(callback.getThrowable()); + // verify latch is released + assertEquals("All good", callback.getResponse()); + } + + @Test + public void shouldReportOAuthException() throws Exception { + handler = new OAuthAsyncCompletionHandler<>(callback, OAUTH_EXCEPTION_RESPONSE_CONVERTER); + + final com.ning.http.client.Response response + = new MockResponse(200, "ok", new FluentCaseInsensitiveStringsMap(), new byte[0]); + handler.onCompleted(response); + assertNull(callback.getResponse()); + assertNotNull(callback.getThrowable()); + assertTrue(callback.getThrowable() instanceof OAuthException); + } + + private static class AllGoodResponseConverter implements OAuthRequest.ResponseConverter { + + @Override + public String convert(Response response) throws IOException { + response.close(); + return "All good"; + } + } + + private static class OAuthExceptionResponseConverter implements OAuthRequest.ResponseConverter { + + @Override + public String convert(Response response) throws IOException { + response.close(); + throw new OAuthException("bad oauth"); + } + } +} diff --git a/scribejava-httpclient-okhttp/pom.xml b/scribejava-httpclient-okhttp/pom.xml new file mode 100644 index 000000000..59bc2bffc --- /dev/null +++ b/scribejava-httpclient-okhttp/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + + com.github.scribejava + scribejava + 8.3.4-SNAPSHOT + ../pom.xml + + + com.github.scribejava + scribejava-httpclient-okhttp + ScribeJava Async OkHttp Client support + jar + + + + com.github.scribejava + scribejava-core + ${project.version} + + + com.squareup.okhttp3 + okhttp + 4.10.0 + + + com.github.scribejava + scribejava-core + ${project.version} + test-jar + test + + + + + + + org.apache.felix + maven-bundle-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + diff --git a/scribejava-httpclient-okhttp/src/main/java/com/github/scribejava/httpclient/okhttp/OAuthAsyncCompletionHandler.java b/scribejava-httpclient-okhttp/src/main/java/com/github/scribejava/httpclient/okhttp/OAuthAsyncCompletionHandler.java new file mode 100644 index 000000000..787b70395 --- /dev/null +++ b/scribejava-httpclient-okhttp/src/main/java/com/github/scribejava/httpclient/okhttp/OAuthAsyncCompletionHandler.java @@ -0,0 +1,58 @@ +package com.github.scribejava.httpclient.okhttp; + +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import okhttp3.Call; +import okhttp3.Callback; + +import java.io.IOException; + +class OAuthAsyncCompletionHandler implements Callback { + + private final OAuthAsyncRequestCallback callback; + private final OAuthRequest.ResponseConverter converter; + private final OkHttpFuture okHttpFuture; + + OAuthAsyncCompletionHandler(OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter, + OkHttpFuture okHttpFuture) { + this.callback = callback; + this.converter = converter; + this.okHttpFuture = okHttpFuture; + } + + @Override + public void onFailure(Call call, IOException exception) { + try { + okHttpFuture.setException(exception); + if (callback != null) { + callback.onThrowable(exception); + } + } finally { + okHttpFuture.finish(); + } + } + + @Override + public void onResponse(Call call, okhttp3.Response okHttpResponse) { + try { + + final Response response = OkHttpHttpClient.convertResponse(okHttpResponse); + try { + @SuppressWarnings("unchecked") + final T t = converter == null ? (T) response : converter.convert(response); + okHttpFuture.setResult(t); + if (callback != null) { + callback.onCompleted(t); + } + } catch (IOException | RuntimeException e) { + okHttpFuture.setException(e); + if (callback != null) { + callback.onThrowable(e); + } + } + } finally { + okHttpFuture.finish(); + } + } +} diff --git a/scribejava-httpclient-okhttp/src/main/java/com/github/scribejava/httpclient/okhttp/OkHttpFuture.java b/scribejava-httpclient-okhttp/src/main/java/com/github/scribejava/httpclient/okhttp/OkHttpFuture.java new file mode 100644 index 000000000..417b03e0a --- /dev/null +++ b/scribejava-httpclient-okhttp/src/main/java/com/github/scribejava/httpclient/okhttp/OkHttpFuture.java @@ -0,0 +1,70 @@ +package com.github.scribejava.httpclient.okhttp; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import okhttp3.Call; + +public class OkHttpFuture implements Future { + + private final CountDownLatch latch = new CountDownLatch(1); + private final Call call; + private T result; + private Exception exception; + + public OkHttpFuture(Call call) { + this.call = call; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + call.cancel(); + return call.isCanceled(); + } + + @Override + public boolean isCancelled() { + return call.isCanceled(); + } + + @Override + public boolean isDone() { + return call.isExecuted(); + } + + public void setException(Exception exception) { + this.exception = exception; + } + + @Override + public T get() throws InterruptedException, ExecutionException { + latch.await(); + if (exception != null) { + throw new ExecutionException(exception); + } + return result; + } + + @Override + public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + if (latch.await(timeout, unit)) { + if (exception != null) { + throw new ExecutionException(exception); + } + return result; + } + throw new TimeoutException(); + } + + void finish() { + latch.countDown(); + } + + void setResult(T result) { + this.result = result; + } + +} diff --git a/scribejava-httpclient-okhttp/src/main/java/com/github/scribejava/httpclient/okhttp/OkHttpHttpClient.java b/scribejava-httpclient-okhttp/src/main/java/com/github/scribejava/httpclient/okhttp/OkHttpHttpClient.java new file mode 100644 index 000000000..f82697db0 --- /dev/null +++ b/scribejava-httpclient-okhttp/src/main/java/com/github/scribejava/httpclient/okhttp/OkHttpHttpClient.java @@ -0,0 +1,201 @@ +package com.github.scribejava.httpclient.okhttp; + +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.multipart.MultipartPayload; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Verb; +import okhttp3.Call; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.internal.http.HttpMethod; +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.Future; +import com.github.scribejava.core.model.Response; +import java.io.File; +import java.io.InputStream; +import java.util.HashMap; +import java.util.concurrent.ExecutionException; +import okhttp3.Cache; +import okhttp3.Headers; +import okhttp3.ResponseBody; + +public class OkHttpHttpClient implements HttpClient { + + private static final MediaType DEFAULT_CONTENT_TYPE_MEDIA_TYPE = MediaType.parse(DEFAULT_CONTENT_TYPE); + + private final OkHttpClient client; + + public OkHttpHttpClient() { + this(OkHttpHttpClientConfig.defaultConfig()); + } + + public OkHttpHttpClient(OkHttpHttpClientConfig config) { + final OkHttpClient.Builder clientBuilder = config.getClientBuilder(); + client = clientBuilder == null ? new OkHttpClient() : clientBuilder.build(); + } + + public OkHttpHttpClient(OkHttpClient client) { + this.client = client; + } + + @Override + public void close() throws IOException { + client.dispatcher().executorService().shutdown(); + client.connectionPool().evictAll(); + final Cache cache = client.cache(); + if (cache != null) { + cache.close(); + } + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + byte[] bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter) { + + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodyType.BYTE_ARRAY, bodyContents, callback, + converter); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + MultipartPayload bodyContents, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + + throw new UnsupportedOperationException("OKHttpClient does not support Multipart payload for the moment"); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + String bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter) { + + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodyType.STRING, bodyContents, callback, + converter); + } + + @Override + public Future executeAsync(String userAgent, Map headers, Verb httpVerb, String completeUrl, + File bodyContents, OAuthAsyncRequestCallback callback, OAuthRequest.ResponseConverter converter) { + + return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, BodyType.FILE, bodyContents, callback, + converter); + } + + private Future doExecuteAsync(String userAgent, Map headers, Verb httpVerb, + String completeUrl, BodyType bodyType, Object bodyContents, OAuthAsyncRequestCallback callback, + OAuthRequest.ResponseConverter converter) { + final Call call = createCall(userAgent, headers, httpVerb, completeUrl, bodyType, bodyContents); + final OkHttpFuture okHttpFuture = new OkHttpFuture<>(call); + call.enqueue(new OAuthAsyncCompletionHandler<>(callback, converter, okHttpFuture)); + return okHttpFuture; + } + + @Override + public Response execute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + byte[] bodyContents) throws InterruptedException, ExecutionException, IOException { + + return doExecute(userAgent, headers, httpVerb, completeUrl, BodyType.BYTE_ARRAY, bodyContents); + } + + @Override + public Response execute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + MultipartPayload bodyContents) throws InterruptedException, ExecutionException, IOException { + + throw new UnsupportedOperationException("OKHttpClient does not support Multipart payload for the moment"); + } + + @Override + public Response execute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + String bodyContents) throws InterruptedException, ExecutionException, IOException { + + return doExecute(userAgent, headers, httpVerb, completeUrl, BodyType.STRING, bodyContents); + } + + @Override + public Response execute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + File bodyContents) throws InterruptedException, ExecutionException, IOException { + + return doExecute(userAgent, headers, httpVerb, completeUrl, BodyType.FILE, bodyContents); + } + + private Response doExecute(String userAgent, Map headers, Verb httpVerb, String completeUrl, + BodyType bodyType, Object bodyContents) throws IOException { + final Call call = createCall(userAgent, headers, httpVerb, completeUrl, bodyType, bodyContents); + return convertResponse(call.execute()); + } + + private Call createCall(String userAgent, Map headers, Verb httpVerb, String completeUrl, + BodyType bodyType, Object bodyContents) { + final Request.Builder requestBuilder = new Request.Builder(); + requestBuilder.url(completeUrl); + + final String method = httpVerb.name(); + + // prepare body + final RequestBody body; + if (bodyContents != null && HttpMethod.permitsRequestBody(method)) { + final MediaType mediaType = headers.containsKey(CONTENT_TYPE) ? MediaType.parse(headers.get(CONTENT_TYPE)) + : DEFAULT_CONTENT_TYPE_MEDIA_TYPE; + + body = bodyType.createBody(mediaType, bodyContents); + } else { + body = null; + } + + // fill HTTP method and body + requestBuilder.method(method, body); + + // fill headers + for (Map.Entry header : headers.entrySet()) { + requestBuilder.addHeader(header.getKey(), header.getValue()); + } + + if (userAgent != null) { + requestBuilder.header(OAuthConstants.USER_AGENT_HEADER_NAME, userAgent); + } + + // create a new call + return client.newCall(requestBuilder.build()); + } + + private enum BodyType { + BYTE_ARRAY { + @Override + RequestBody createBody(MediaType mediaType, Object bodyContents) { + return RequestBody.create((byte[]) bodyContents, mediaType); + } + }, + STRING { + @Override + RequestBody createBody(MediaType mediaType, Object bodyContents) { + return RequestBody.create((String) bodyContents, mediaType); + } + }, + FILE { + @Override + RequestBody createBody(MediaType mediaType, Object bodyContents) { + return RequestBody.create((File) bodyContents, mediaType); + } + }; + + abstract RequestBody createBody(MediaType mediaType, Object bodyContents); + } + + static Response convertResponse(okhttp3.Response okHttpResponse) { + final Headers headers = okHttpResponse.headers(); + final Map headersMap = new HashMap<>(); + for (String headerName : headers.names()) { + headersMap.put(headerName, headers.get(headerName)); + } + + final ResponseBody body = okHttpResponse.body(); + final InputStream bodyStream = body == null ? null : body.byteStream(); + return new Response(okHttpResponse.code(), okHttpResponse.message(), headersMap, bodyStream, bodyStream, body, + okHttpResponse); + } + +} diff --git a/scribejava-httpclient-okhttp/src/main/java/com/github/scribejava/httpclient/okhttp/OkHttpHttpClientConfig.java b/scribejava-httpclient-okhttp/src/main/java/com/github/scribejava/httpclient/okhttp/OkHttpHttpClientConfig.java new file mode 100644 index 000000000..7759a0936 --- /dev/null +++ b/scribejava-httpclient-okhttp/src/main/java/com/github/scribejava/httpclient/okhttp/OkHttpHttpClientConfig.java @@ -0,0 +1,26 @@ +package com.github.scribejava.httpclient.okhttp; + +import com.github.scribejava.core.httpclient.HttpClientConfig; +import okhttp3.OkHttpClient; + +public class OkHttpHttpClientConfig implements HttpClientConfig { + + private final OkHttpClient.Builder clientBuilder; + + public OkHttpHttpClientConfig(OkHttpClient.Builder clientBuilder) { + this.clientBuilder = clientBuilder; + } + + public OkHttpClient.Builder getClientBuilder() { + return clientBuilder; + } + + @Override + public OkHttpHttpClientConfig createDefaultConfig() { + return defaultConfig(); + } + + public static OkHttpHttpClientConfig defaultConfig() { + return new OkHttpHttpClientConfig(null); + } +} diff --git a/scribejava-httpclient-okhttp/src/main/java/com/github/scribejava/httpclient/okhttp/OkHttpProvider.java b/scribejava-httpclient-okhttp/src/main/java/com/github/scribejava/httpclient/okhttp/OkHttpProvider.java new file mode 100644 index 000000000..4d27f5f0c --- /dev/null +++ b/scribejava-httpclient-okhttp/src/main/java/com/github/scribejava/httpclient/okhttp/OkHttpProvider.java @@ -0,0 +1,16 @@ +package com.github.scribejava.httpclient.okhttp; + +import com.github.scribejava.core.httpclient.HttpClientProvider; +import com.github.scribejava.core.httpclient.HttpClient; +import com.github.scribejava.core.httpclient.HttpClientConfig; + +public class OkHttpProvider implements HttpClientProvider { + + @Override + public HttpClient createClient(HttpClientConfig config) { + if (config instanceof OkHttpHttpClientConfig) { + return new OkHttpHttpClient((OkHttpHttpClientConfig) config); + } + return null; + } +} diff --git a/scribejava-httpclient-okhttp/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider b/scribejava-httpclient-okhttp/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider new file mode 100644 index 000000000..46afa18ed --- /dev/null +++ b/scribejava-httpclient-okhttp/src/main/resources/META-INF/services/com.github.scribejava.core.httpclient.HttpClientProvider @@ -0,0 +1 @@ +com.github.scribejava.httpclient.okhttp.OkHttpProvider diff --git a/scribejava-httpclient-okhttp/src/test/java/com/github/scribejava/httpclient/okhttp/MockCall.java b/scribejava-httpclient-okhttp/src/test/java/com/github/scribejava/httpclient/okhttp/MockCall.java new file mode 100644 index 000000000..7fa14a630 --- /dev/null +++ b/scribejava-httpclient-okhttp/src/test/java/com/github/scribejava/httpclient/okhttp/MockCall.java @@ -0,0 +1,60 @@ +package com.github.scribejava.httpclient.okhttp; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.Request; +import okhttp3.Response; +import okio.Timeout; + +public class MockCall implements Call { + + private final Collection callbacks = new ArrayList<>(); + private boolean canceled; + + @Override + public void enqueue(Callback responseCallback) { + callbacks.add(responseCallback); + } + + @Override + public void cancel() { + canceled = true; + for (Callback callback : callbacks) { + callback.onFailure(this, new IOException("Canceled")); + } + } + + @Override + public boolean isCanceled() { + return canceled; + } + + @Override + public Request request() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Response execute() throws IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean isExecuted() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public MockCall clone() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Timeout timeout() { + throw new UnsupportedOperationException("Not supported yet."); + } +} diff --git a/scribejava-httpclient-okhttp/src/test/java/com/github/scribejava/httpclient/okhttp/OAuthAsyncCompletionHandlerTest.java b/scribejava-httpclient-okhttp/src/test/java/com/github/scribejava/httpclient/okhttp/OAuthAsyncCompletionHandlerTest.java new file mode 100644 index 000000000..b58e8df93 --- /dev/null +++ b/scribejava-httpclient-okhttp/src/test/java/com/github/scribejava/httpclient/okhttp/OAuthAsyncCompletionHandlerTest.java @@ -0,0 +1,205 @@ +package com.github.scribejava.httpclient.okhttp; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertThrows; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import org.junit.Before; +import org.junit.Test; + +import com.github.scribejava.core.exceptions.OAuthException; +import com.github.scribejava.core.model.OAuthAsyncRequestCallback; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; + +import okhttp3.Call; +import okhttp3.MediaType; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.ResponseBody; +import org.junit.function.ThrowingRunnable; + +public class OAuthAsyncCompletionHandlerTest { + + private static final AllGoodResponseConverter ALL_GOOD_RESPONSE_CONVERTER = new AllGoodResponseConverter(); + private static final ExceptionResponseConverter EXCEPTION_RESPONSE_CONVERTER = new ExceptionResponseConverter(); + private static final OAuthExceptionResponseConverter OAUTH_EXCEPTION_RESPONSE_CONVERTER + = new OAuthExceptionResponseConverter(); + + private OAuthAsyncCompletionHandler handler; + private Call call; + private OkHttpFuture future; + private TestCallback callback; + + private static class TestCallback implements OAuthAsyncRequestCallback { + + private Throwable throwable; + private String response; + + @Override + public void onCompleted(String response) { + this.response = response; + } + + @Override + public void onThrowable(Throwable throwable) { + this.throwable = throwable; + } + + public Throwable getThrowable() { + return throwable; + } + + public String getResponse() { + return response; + } + + } + + @Before + public void setUp() { + callback = new TestCallback(); + call = new MockCall(); + future = new OkHttpFuture<>(call); + } + + @Test + public void shouldReleaseLatchOnSuccess() throws Exception { + handler = new OAuthAsyncCompletionHandler<>(callback, ALL_GOOD_RESPONSE_CONVERTER, future); + call.enqueue(handler); + + final Request request = new Request.Builder().url("http://localhost/").build(); + final okhttp3.Response response = new okhttp3.Response.Builder() + .request(request) + .protocol(Protocol.HTTP_1_1) + .code(200) + .message("ok") + .body(ResponseBody.create(new byte[0], MediaType.get("text/plain"))) + .build(); + handler.onResponse(call, response); + assertNotNull(callback.getResponse()); + assertNull(callback.getThrowable()); + // verify latch is released + assertEquals("All good", future.get()); + } + + @Test + public void shouldReleaseLatchOnIOException() { + handler = new OAuthAsyncCompletionHandler<>(callback, EXCEPTION_RESPONSE_CONVERTER, future); + call.enqueue(handler); + + final Request request = new Request.Builder().url("http://localhost/").build(); + final okhttp3.Response response = new okhttp3.Response.Builder() + .request(request) + .protocol(Protocol.HTTP_1_1) + .code(200) + .message("ok") + .body(ResponseBody.create(new byte[0], MediaType.get("text/plain"))) + .build(); + handler.onResponse(call, response); + assertNull(callback.getResponse()); + assertNotNull(callback.getThrowable()); + assertTrue(callback.getThrowable() instanceof IOException); + // verify latch is released + assertThrows(ExecutionException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + future.get(); + } + }); + } + + @Test + public void shouldReportOAuthException() { + handler = new OAuthAsyncCompletionHandler<>(callback, OAUTH_EXCEPTION_RESPONSE_CONVERTER, future); + call.enqueue(handler); + + final Request request = new Request.Builder().url("http://localhost/").build(); + final okhttp3.Response response = new okhttp3.Response.Builder() + .request(request) + .protocol(Protocol.HTTP_1_1) + .code(200) + .message("ok") + .body(ResponseBody.create(new byte[0], MediaType.get("text/plain"))) + .build(); + handler.onResponse(call, response); + assertNull(callback.getResponse()); + assertNotNull(callback.getThrowable()); + assertTrue(callback.getThrowable() instanceof OAuthException); + // verify latch is released + assertThrows(ExecutionException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + future.get(); + } + }); + } + + @Test + public void shouldReleaseLatchOnCancel() { + handler = new OAuthAsyncCompletionHandler<>(callback, ALL_GOOD_RESPONSE_CONVERTER, future); + call.enqueue(handler); + + future.cancel(true); + assertNull(callback.getResponse()); + assertNotNull(callback.getThrowable()); + assertTrue(callback.getThrowable() instanceof IOException); + // verify latch is released + assertThrows(ExecutionException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + future.get(); + } + }); + } + + @Test + public void shouldReleaseLatchOnFailure() { + handler = new OAuthAsyncCompletionHandler<>(callback, ALL_GOOD_RESPONSE_CONVERTER, future); + call.enqueue(handler); + + handler.onFailure(call, new IOException()); + assertNull(callback.getResponse()); + assertNotNull(callback.getThrowable()); + assertTrue(callback.getThrowable() instanceof IOException); + // verify latch is released + assertThrows(ExecutionException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + future.get(); + } + }); + } + + private static class AllGoodResponseConverter implements OAuthRequest.ResponseConverter { + + @Override + public String convert(Response response) throws IOException { + response.close(); + return "All good"; + } + } + + private static class ExceptionResponseConverter implements OAuthRequest.ResponseConverter { + + @Override + public String convert(Response response) throws IOException { + response.close(); + throw new IOException("Failed to convert"); + } + } + + private static class OAuthExceptionResponseConverter implements OAuthRequest.ResponseConverter { + + @Override + public String convert(Response response) throws IOException { + response.close(); + throw new OAuthException("bad oauth"); + } + } +} diff --git a/scribejava-httpclient-okhttp/src/test/java/com/github/scribejava/httpclient/okhttp/OkHttpHttpClientTest.java b/scribejava-httpclient-okhttp/src/test/java/com/github/scribejava/httpclient/okhttp/OkHttpHttpClientTest.java new file mode 100644 index 000000000..80fdf2834 --- /dev/null +++ b/scribejava-httpclient-okhttp/src/test/java/com/github/scribejava/httpclient/okhttp/OkHttpHttpClientTest.java @@ -0,0 +1,12 @@ +package com.github.scribejava.httpclient.okhttp; + +import com.github.scribejava.core.AbstractClientTest; +import com.github.scribejava.core.httpclient.HttpClient; + +public class OkHttpHttpClientTest extends AbstractClientTest { + + @Override + protected HttpClient createNewClient() { + return new OkHttpHttpClient(); + } +} diff --git a/scribejava-java8/pom.xml b/scribejava-java8/pom.xml new file mode 100644 index 000000000..b75f6d2de --- /dev/null +++ b/scribejava-java8/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + + com.github.scribejava + scribejava + 8.3.4-SNAPSHOT + ../pom.xml + + + com.github.scribejava + scribejava-java8 + ScribeJava Java 8+ compatibility stuff + jar + + + + + org.apache.felix + maven-bundle-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + + + 8 + + diff --git a/scribejava-java8/src/main/java/com/github/scribejava/java8/base64/Java8Base64.java b/scribejava-java8/src/main/java/com/github/scribejava/java8/base64/Java8Base64.java new file mode 100644 index 000000000..eb391dcad --- /dev/null +++ b/scribejava-java8/src/main/java/com/github/scribejava/java8/base64/Java8Base64.java @@ -0,0 +1,17 @@ +package com.github.scribejava.java8.base64; + +public class Java8Base64 { + + private static final java.util.Base64.Encoder BASE64_ENCODER = java.util.Base64.getEncoder(); + private static final java.util.Base64.Encoder BASE64_URL_ENCODER_WITHOUT_PADDING + = java.util.Base64.getUrlEncoder().withoutPadding(); + + public String internalEncode(byte[] bytes) { + return BASE64_ENCODER.encodeToString(bytes); + } + + public String internalEncodeUrlWithoutPadding(byte[] bytes) { + return BASE64_URL_ENCODER_WITHOUT_PADDING.encodeToString(bytes); + } + +} diff --git a/src/main/config/scribe-eclipse-formatter.xml b/src/main/config/scribe-eclipse-formatter.xml deleted file mode 100644 index 8ea5bc9d5..000000000 --- a/src/main/config/scribe-eclipse-formatter.xml +++ /dev/null @@ -1,290 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/main/config/scribe-eclipse.importorder b/src/main/config/scribe-eclipse.importorder deleted file mode 100644 index 1fcaf0f22..000000000 --- a/src/main/config/scribe-eclipse.importorder +++ /dev/null @@ -1,7 +0,0 @@ -#Organize Import Order -#Tue Feb 21 20:29:55 GMT 2012 -4=java -3=javax -2=org -1=org.boncey -0=com diff --git a/src/main/java/org/scribe/builder/ServiceBuilder.java b/src/main/java/org/scribe/builder/ServiceBuilder.java deleted file mode 100644 index 27f3c8f63..000000000 --- a/src/main/java/org/scribe/builder/ServiceBuilder.java +++ /dev/null @@ -1,169 +0,0 @@ -package org.scribe.builder; - -import java.io.*; -import org.scribe.builder.api.*; -import org.scribe.exceptions.*; -import org.scribe.model.*; -import org.scribe.oauth.*; -import org.scribe.utils.*; - -/** - * Implementation of the Builder pattern, with a fluent interface that creates a - * {@link OAuthService} - * - * @author Pablo Fernandez - * - */ -public class ServiceBuilder -{ - private String apiKey; - private String apiSecret; - private String callback; - private Api api; - private String scope; - private SignatureType signatureType; - private OutputStream debugStream; - - /** - * Default constructor - */ - public ServiceBuilder() - { - this.callback = OAuthConstants.OUT_OF_BAND; - this.signatureType = SignatureType.Header; - this.debugStream = null; - } - - /** - * Configures the {@link Api} - * - * @param apiClass the class of one of the existent {@link Api}s on org.scribe.api package - * @return the {@link ServiceBuilder} instance for method chaining - */ - public ServiceBuilder provider(Class apiClass) - { - this.api = createApi(apiClass); - return this; - } - - private Api createApi(Class apiClass) - { - Preconditions.checkNotNull(apiClass, "Api class cannot be null"); - Api api; - try - { - api = apiClass.newInstance(); - } - catch(Exception e) - { - throw new OAuthException("Error while creating the Api object", e); - } - return api; - } - - /** - * Configures the {@link Api} - * - * Overloaded version. Let's you use an instance instead of a class. - * - * @param api instance of {@link Api}s - * @return the {@link ServiceBuilder} instance for method chaining - */ - public ServiceBuilder provider(Api api) - { - Preconditions.checkNotNull(api, "Api cannot be null"); - this.api = api; - return this; - } - - /** - * Adds an OAuth callback url - * - * @param callback callback url. Must be a valid url or 'oob' for out of band OAuth - * @return the {@link ServiceBuilder} instance for method chaining - */ - public ServiceBuilder callback(String callback) - { - Preconditions.checkNotNull(callback, "Callback can't be null"); - this.callback = callback; - return this; - } - - /** - * Configures the api key - * - * @param apiKey The api key for your application - * @return the {@link ServiceBuilder} instance for method chaining - */ - public ServiceBuilder apiKey(String apiKey) - { - Preconditions.checkEmptyString(apiKey, "Invalid Api key"); - this.apiKey = apiKey; - return this; - } - - /** - * Configures the api secret - * - * @param apiSecret The api secret for your application - * @return the {@link ServiceBuilder} instance for method chaining - */ - public ServiceBuilder apiSecret(String apiSecret) - { - Preconditions.checkEmptyString(apiSecret, "Invalid Api secret"); - this.apiSecret = apiSecret; - return this; - } - - /** - * Configures the OAuth scope. This is only necessary in some APIs (like Google's). - * - * @param scope The OAuth scope - * @return the {@link ServiceBuilder} instance for method chaining - */ - public ServiceBuilder scope(String scope) - { - Preconditions.checkEmptyString(scope, "Invalid OAuth scope"); - this.scope = scope; - return this; - } - - /** - * Configures the signature type, choose between header, querystring, etc. Defaults to Header - * - * @param scope The OAuth scope - * @return the {@link ServiceBuilder} instance for method chaining - */ - public ServiceBuilder signatureType(SignatureType type) - { - Preconditions.checkNotNull(type, "Signature type can't be null"); - this.signatureType = type; - return this; - } - - public ServiceBuilder debugStream(OutputStream stream) - { - Preconditions.checkNotNull(stream, "debug stream can't be null"); - this.debugStream = stream; - return this; - } - - public ServiceBuilder debug() - { - this.debugStream(System.out); - return this; - } - - /** - * Returns the fully configured {@link OAuthService} - * - * @return fully configured {@link OAuthService} - */ - public OAuthService build() - { - Preconditions.checkNotNull(api, "You must specify a valid api through the provider() method"); - Preconditions.checkEmptyString(apiKey, "You must provide an api key"); - Preconditions.checkEmptyString(apiSecret, "You must provide an api secret"); - return api.createService(new OAuthConfig(apiKey, apiSecret, callback, signatureType, scope, debugStream)); - } -} diff --git a/src/main/java/org/scribe/builder/api/Api.java b/src/main/java/org/scribe/builder/api/Api.java deleted file mode 100644 index 6664296bd..000000000 --- a/src/main/java/org/scribe/builder/api/Api.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; -import org.scribe.oauth.*; - -/** - * Contains all the configuration needed to instantiate a valid {@link OAuthService} - * - * @author Pablo Fernandez - * - */ -public interface Api -{ - /** - * Creates an {@link OAuthService} - * - * @param apiKey your application api key - * @param apiSecret your application api secret - * @param callback the callback url (or 'oob' for out of band OAuth) - * @param scope the OAuth scope - * - * @return fully configured {@link OAuthService} - */ - OAuthService createService(OAuthConfig config); -} diff --git a/src/main/java/org/scribe/builder/api/ConstantContactApi.java b/src/main/java/org/scribe/builder/api/ConstantContactApi.java deleted file mode 100644 index 0588bc40c..000000000 --- a/src/main/java/org/scribe/builder/api/ConstantContactApi.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -public class ConstantContactApi extends DefaultApi10a -{ - private static final String AUTHORIZE_URL = "https://oauth.constantcontact.com/ws/oauth/confirm_access?oauth_token=%s"; - - @Override - public String getAccessTokenEndpoint() - { - return "https://oauth.constantcontact.com/ws/oauth/access_token"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } - - @Override - public String getRequestTokenEndpoint() - { - return "https://oauth.constantcontact.com/ws/oauth/request_token"; - } -} diff --git a/src/main/java/org/scribe/builder/api/ConstantContactApi2.java b/src/main/java/org/scribe/builder/api/ConstantContactApi2.java deleted file mode 100644 index b5e4cac27..000000000 --- a/src/main/java/org/scribe/builder/api/ConstantContactApi2.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.scribe.builder.api; - -import java.util.regex.*; -import org.scribe.exceptions.*; -import org.scribe.extractors.*; -import org.scribe.model.*; -import org.scribe.utils.*; - -public class ConstantContactApi2 extends DefaultApi20 -{ - private static final String AUTHORIZE_URL = "https://oauth2.constantcontact.com/oauth2/oauth/siteowner/authorize?client_id=%s&response_type=code&redirect_uri=%s"; - - @Override - public String getAccessTokenEndpoint() - { - return "https://oauth2.constantcontact.com/oauth2/oauth/token?grant_type=authorization_code"; - } - - @Override - public String getAuthorizationUrl(OAuthConfig config) - { - return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback())); - } - - @Override - public Verb getAccessTokenVerb() - { - return Verb.POST; - } - - @Override - public AccessTokenExtractor getAccessTokenExtractor() - { - return new AccessTokenExtractor() - { - - public Token extract(String response) - { - Preconditions.checkEmptyString(response, "Response body is incorrect. Can't extract a token from an empty string"); - - String regex = "\"access_token\"\\s*:\\s*\"([^&\"]+)\""; - Matcher matcher = Pattern.compile(regex).matcher(response); - if (matcher.find()) - { - String token = OAuthEncoder.decode(matcher.group(1)); - return new Token(token, "", response); - } - else - { - throw new OAuthException("Response body is incorrect. Can't extract a token from this: '" + response + "'", null); - } - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/org/scribe/builder/api/DefaultApi10a.java b/src/main/java/org/scribe/builder/api/DefaultApi10a.java deleted file mode 100644 index 7506986b1..000000000 --- a/src/main/java/org/scribe/builder/api/DefaultApi10a.java +++ /dev/null @@ -1,141 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.extractors.*; -import org.scribe.model.*; -import org.scribe.oauth.*; -import org.scribe.services.*; - -/** - * Default implementation of the OAuth protocol, version 1.0a - * - * This class is meant to be extended by concrete implementations of the API, - * providing the endpoints and endpoint-http-verbs. - * - * If your Api adheres to the 1.0a protocol correctly, you just need to extend - * this class and define the getters for your endpoints. - * - * If your Api does something a bit different, you can override the different - * extractors or services, in order to fine-tune the process. Please read the - * javadocs of the interfaces to get an idea of what to do. - * - * @author Pablo Fernandez - * - */ -public abstract class DefaultApi10a implements Api -{ - /** - * Returns the access token extractor. - * - * @return access token extractor - */ - public AccessTokenExtractor getAccessTokenExtractor() - { - return new TokenExtractorImpl(); - } - - /** - * Returns the base string extractor. - * - * @return base string extractor - */ - public BaseStringExtractor getBaseStringExtractor() - { - return new BaseStringExtractorImpl(); - } - - /** - * Returns the header extractor. - * - * @return header extractor - */ - public HeaderExtractor getHeaderExtractor() - { - return new HeaderExtractorImpl(); - } - - /** - * Returns the request token extractor. - * - * @return request token extractor - */ - public RequestTokenExtractor getRequestTokenExtractor() - { - return new TokenExtractorImpl(); - } - - /** - * Returns the signature service. - * - * @return signature service - */ - public SignatureService getSignatureService() - { - return new HMACSha1SignatureService(); - } - - /** - * Returns the timestamp service. - * - * @return timestamp service - */ - public TimestampService getTimestampService() - { - return new TimestampServiceImpl(); - } - - /** - * Returns the verb for the access token endpoint (defaults to POST) - * - * @return access token endpoint verb - */ - public Verb getAccessTokenVerb() - { - return Verb.POST; - } - - /** - * Returns the verb for the request token endpoint (defaults to POST) - * - * @return request token endpoint verb - */ - public Verb getRequestTokenVerb() - { - return Verb.POST; - } - - /** - * Returns the URL that receives the request token requests. - * - * @return request token URL - */ - public abstract String getRequestTokenEndpoint(); - - /** - * Returns the URL that receives the access token requests. - * - * @return access token URL - */ - public abstract String getAccessTokenEndpoint(); - - /** - * Returns the URL where you should redirect your users to authenticate - * your application. - * - * @param requestToken the request token you need to authorize - * @return the URL where you should redirect your users - */ - public abstract String getAuthorizationUrl(Token requestToken); - - /** - * Returns the {@link OAuthService} for this Api - * - * @param apiKey Key - * @param apiSecret Api Secret - * @param callback OAuth callback (either URL or 'oob') - * @param scope OAuth scope (optional) - */ - public OAuthService createService(OAuthConfig config) - { - return new OAuth10aServiceImpl(this, config); - } -} diff --git a/src/main/java/org/scribe/builder/api/DefaultApi20.java b/src/main/java/org/scribe/builder/api/DefaultApi20.java deleted file mode 100644 index ffb620702..000000000 --- a/src/main/java/org/scribe/builder/api/DefaultApi20.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.extractors.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -/** - * Default implementation of the OAuth protocol, version 2.0 (draft 11) - * - * This class is meant to be extended by concrete implementations of the API, - * providing the endpoints and endpoint-http-verbs. - * - * If your Api adheres to the 2.0 (draft 11) protocol correctly, you just need to extend - * this class and define the getters for your endpoints. - * - * If your Api does something a bit different, you can override the different - * extractors or services, in order to fine-tune the process. Please read the - * javadocs of the interfaces to get an idea of what to do. - * - * @author Diego Silveira - * - */ -public abstract class DefaultApi20 implements Api -{ - - /** - * Returns the access token extractor. - * - * @return access token extractor - */ - public AccessTokenExtractor getAccessTokenExtractor() - { - return new TokenExtractor20Impl(); - } - - /** - * Returns the verb for the access token endpoint (defaults to GET) - * - * @return access token endpoint verb - */ - public Verb getAccessTokenVerb() - { - return Verb.GET; - } - - /** - * Returns the URL that receives the access token requests. - * - * @return access token URL - */ - public abstract String getAccessTokenEndpoint(); - - /** - * Returns the URL where you should redirect your users to authenticate - * your application. - * - * @param config OAuth 2.0 configuration param object - * @return the URL where you should redirect your users - */ - public abstract String getAuthorizationUrl(OAuthConfig config); - - /** - * {@inheritDoc} - */ - public OAuthService createService(OAuthConfig config) - { - return new OAuth20ServiceImpl(this, config); - } - -} diff --git a/src/main/java/org/scribe/builder/api/DiggApi.java b/src/main/java/org/scribe/builder/api/DiggApi.java deleted file mode 100644 index b69253eb9..000000000 --- a/src/main/java/org/scribe/builder/api/DiggApi.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -public class DiggApi extends DefaultApi10a -{ - - private static final String AUTHORIZATION_URL = "http://digg.com/oauth/authorize?oauth_token=%s"; - private static final String BASE_URL = "http://services.digg.com/oauth/"; - - @Override - public String getRequestTokenEndpoint() - { - return BASE_URL + "request_token"; - } - - @Override - public String getAccessTokenEndpoint() - { - return BASE_URL + "access_token"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZATION_URL, requestToken.getToken()); - } - -} diff --git a/src/main/java/org/scribe/builder/api/DropBoxApi.java b/src/main/java/org/scribe/builder/api/DropBoxApi.java deleted file mode 100644 index 86f4a71a1..000000000 --- a/src/main/java/org/scribe/builder/api/DropBoxApi.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -public class DropBoxApi extends DefaultApi10a -{ - @Override - public String getAccessTokenEndpoint() - { - return "https://api.dropbox.com/1/oauth/access_token"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return "https://www.dropbox.com/1/oauth/authorize?oauth_token="+requestToken.getToken(); - } - - @Override - public String getRequestTokenEndpoint() - { - return "https://api.dropbox.com/1/oauth/request_token"; - } - -} \ No newline at end of file diff --git a/src/main/java/org/scribe/builder/api/EvernoteApi.java b/src/main/java/org/scribe/builder/api/EvernoteApi.java deleted file mode 100644 index 007f48b1e..000000000 --- a/src/main/java/org/scribe/builder/api/EvernoteApi.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.Token; - -public class EvernoteApi extends DefaultApi10a -{ - private static final String AUTHORIZATION_URL = "https://www.evernote.com/OAuth.action?oauth_token=%s"; - - @Override - public String getRequestTokenEndpoint() - { - return "https://www.evernote.com/oauth"; - } - - @Override - public String getAccessTokenEndpoint() - { - return "https://www.evernote.com/oauth"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZATION_URL, requestToken.getToken()); - } - - public static class Sandbox extends EvernoteApi - { - private static final String SANDBOX_URL = "https://sandbox.evernote.com"; - - @Override - public String getRequestTokenEndpoint() - { - return SANDBOX_URL + "/oauth"; - } - - @Override - public String getAccessTokenEndpoint() - { - return SANDBOX_URL + "/oauth"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(SANDBOX_URL + "/OAuth.action?oauth_token=%s", requestToken.getToken()); - } - } -} diff --git a/src/main/java/org/scribe/builder/api/FacebookApi.java b/src/main/java/org/scribe/builder/api/FacebookApi.java deleted file mode 100644 index 996a651e1..000000000 --- a/src/main/java/org/scribe/builder/api/FacebookApi.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -import org.scribe.utils.*; - -public class FacebookApi extends DefaultApi20 -{ - private static final String AUTHORIZE_URL = "https://www.facebook.com/dialog/oauth?client_id=%s&redirect_uri=%s"; - private static final String SCOPED_AUTHORIZE_URL = AUTHORIZE_URL + "&scope=%s"; - - @Override - public String getAccessTokenEndpoint() - { - return "https://graph.facebook.com/oauth/access_token"; - } - - @Override - public String getAuthorizationUrl(OAuthConfig config) - { - Preconditions.checkValidUrl(config.getCallback(), "Must provide a valid url as callback. Facebook does not support OOB"); - - // Append scope if present - if(config.hasScope()) - { - return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope())); - } - else - { - return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback())); - } - } -} diff --git a/src/main/java/org/scribe/builder/api/FlickrApi.java b/src/main/java/org/scribe/builder/api/FlickrApi.java deleted file mode 100644 index a63043610..000000000 --- a/src/main/java/org/scribe/builder/api/FlickrApi.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -/** - * OAuth API for Flickr. - * - * @author Darren Greaves - * @see Flickr API - */ -public class FlickrApi extends DefaultApi10a -{ - - /** - * {@inheritDoc} - */ - @Override - public String getAccessTokenEndpoint() - { - return "http://www.flickr.com/services/oauth/access_token"; - } - - /** - * {@inheritDoc} - */ - @Override - public String getAuthorizationUrl(Token requestToken) - { - return "http://www.flickr.com/services/oauth/authorize?oauth_token=" + requestToken.getToken(); - } - - /** - * {@inheritDoc} - */ - @Override - public String getRequestTokenEndpoint() - { - return "http://www.flickr.com/services/oauth/request_token"; - } -} diff --git a/src/main/java/org/scribe/builder/api/Foursquare2Api.java b/src/main/java/org/scribe/builder/api/Foursquare2Api.java deleted file mode 100644 index d11def9d7..000000000 --- a/src/main/java/org/scribe/builder/api/Foursquare2Api.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.extractors.*; -import org.scribe.model.*; -import org.scribe.utils.*; - -public class Foursquare2Api extends DefaultApi20 -{ - private static final String AUTHORIZATION_URL = "https://foursquare.com/oauth2/authenticate?client_id=%s&response_type=code&redirect_uri=%s"; - - @Override - public String getAccessTokenEndpoint() - { - return "https://foursquare.com/oauth2/access_token?grant_type=authorization_code"; - } - - @Override - public String getAuthorizationUrl(OAuthConfig config) - { - Preconditions.checkValidUrl(config.getCallback(), "Must provide a valid url as callback. Foursquare2 does not support OOB"); - return String.format(AUTHORIZATION_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback())); - } - - @Override - public AccessTokenExtractor getAccessTokenExtractor() - { - return new JsonTokenExtractor(); - } -} diff --git a/src/main/java/org/scribe/builder/api/FoursquareApi.java b/src/main/java/org/scribe/builder/api/FoursquareApi.java deleted file mode 100644 index 060a76b76..000000000 --- a/src/main/java/org/scribe/builder/api/FoursquareApi.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.Token; - -public class FoursquareApi extends DefaultApi10a -{ - private static final String AUTHORIZATION_URL = "http://foursquare.com/oauth/authorize?oauth_token=%s"; - - @Override - public String getAccessTokenEndpoint() - { - return "http://foursquare.com/oauth/access_token"; - } - - @Override - public String getRequestTokenEndpoint() - { - return "http://foursquare.com/oauth/request_token"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZATION_URL, requestToken.getToken()); - } -} diff --git a/src/main/java/org/scribe/builder/api/FreelancerApi.java b/src/main/java/org/scribe/builder/api/FreelancerApi.java deleted file mode 100644 index 482e66fd1..000000000 --- a/src/main/java/org/scribe/builder/api/FreelancerApi.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -public class FreelancerApi extends DefaultApi10a -{ - private static final String AUTHORIZATION_URL = "http://www.freelancer.com/users/api-token/auth.php?oauth_token=%s"; - - @Override - public String getAccessTokenEndpoint() - { - return "http://api.freelancer.com/RequestAccessToken/requestAccessToken.xml?"; - } - - @Override - public String getRequestTokenEndpoint() - { - return "http://api.freelancer.com/RequestRequestToken/requestRequestToken.xml"; - } - - @Override - public Verb getAccessTokenVerb() - { - return Verb.GET; - } - - @Override - public Verb getRequestTokenVerb() - { - return Verb.GET; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZATION_URL, requestToken.getToken()); - } - - public static class Sandbox extends FreelancerApi - { - private static final String SANDBOX_AUTHORIZATION_URL = "http://www.sandbox.freelancer.com/users/api-token/auth.php"; - - @Override - public String getRequestTokenEndpoint() - { - return "http://api.sandbox.freelancer.com/RequestRequestToken/requestRequestToken.xml"; - } - - @Override - public String getAccessTokenEndpoint() - { - return "http://api.sandbox.freelancer.com/RequestAccessToken/requestAccessToken.xml?"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(SANDBOX_AUTHORIZATION_URL + "?oauth_token=%s", requestToken.getToken()); - } - } -} diff --git a/src/main/java/org/scribe/builder/api/GetGlueApi.java b/src/main/java/org/scribe/builder/api/GetGlueApi.java deleted file mode 100644 index 3a7560f0f..000000000 --- a/src/main/java/org/scribe/builder/api/GetGlueApi.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.Token; - -public class GetGlueApi extends DefaultApi10a -{ - private static final String AUTHORIZE_URL = "http://getglue.com/oauth/authorize?oauth_token=%s"; - private static final String REQUEST_TOKEN_RESOURCE = "https://api.getglue.com/oauth/request_token"; - private static final String ACCESS_TOKEN_RESOURCE = "https://api.getglue.com/oauth/access_token"; - - @Override - public String getAccessTokenEndpoint() - { - return ACCESS_TOKEN_RESOURCE; - } - - @Override - public String getRequestTokenEndpoint() - { - return REQUEST_TOKEN_RESOURCE; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } - -} diff --git a/src/main/java/org/scribe/builder/api/GoogleApi.java b/src/main/java/org/scribe/builder/api/GoogleApi.java deleted file mode 100644 index 9c86e5e1a..000000000 --- a/src/main/java/org/scribe/builder/api/GoogleApi.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -public class GoogleApi extends DefaultApi10a -{ - private static final String AUTHORIZATION_URL = "https://www.google.com/accounts/OAuthAuthorizeToken?oauth_token=%s"; - - @Override - public String getAccessTokenEndpoint() - { - return "https://www.google.com/accounts/OAuthGetAccessToken"; - } - - @Override - public String getRequestTokenEndpoint() - { - return "https://www.google.com/accounts/OAuthGetRequestToken"; - } - - @Override - public Verb getAccessTokenVerb() - { - return Verb.GET; - } - - @Override - public Verb getRequestTokenVerb() - { - return Verb.GET; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZATION_URL, requestToken.getToken()); - } -} diff --git a/src/main/java/org/scribe/builder/api/ImgUrApi.java b/src/main/java/org/scribe/builder/api/ImgUrApi.java deleted file mode 100644 index 06dd6910d..000000000 --- a/src/main/java/org/scribe/builder/api/ImgUrApi.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -/** - * OAuth API for ImgUr - * - * @author David Wursteisen - * @see ImgUr API - */ -public class ImgUrApi extends DefaultApi10a -{ - - @Override - public String getRequestTokenEndpoint() - { - return "https://api.imgur.com/oauth/request_token"; - } - - @Override - public String getAccessTokenEndpoint() - { - return "https://api.imgur.com/oauth/access_token"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format("https://api.imgur.com/oauth/authorize?oauth_token=%s", requestToken.getToken()); - } -} - diff --git a/src/main/java/org/scribe/builder/api/KaixinApi.java b/src/main/java/org/scribe/builder/api/KaixinApi.java deleted file mode 100644 index 5b0e0d5dc..000000000 --- a/src/main/java/org/scribe/builder/api/KaixinApi.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -public class KaixinApi extends DefaultApi10a -{ - private static final String REQUEST_TOKEN_URL = "http://api.kaixin001.com/oauth/request_token"; - private static final String ACCESS_TOKEN_URL = "http://api.kaixin001.com/oauth/access_token"; - private static final String AUTHORIZE_URL = "http://api.kaixin001.com/oauth/authorize?oauth_token=%s"; - - @Override - public String getRequestTokenEndpoint() - { - return REQUEST_TOKEN_URL; - } - - @Override - public String getAccessTokenEndpoint() - { - return ACCESS_TOKEN_URL; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } - - @Override - public Verb getRequestTokenVerb() - { - return Verb.GET; - } - - @Override - public Verb getAccessTokenVerb() - { - return Verb.GET; - } -} diff --git a/src/main/java/org/scribe/builder/api/KaixinApi20.java b/src/main/java/org/scribe/builder/api/KaixinApi20.java deleted file mode 100644 index 9e27bcb33..000000000 --- a/src/main/java/org/scribe/builder/api/KaixinApi20.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.extractors.*; -import org.scribe.model.*; -import org.scribe.utils.*; - -/** - * Kaixin(http://www.kaixin001.com/) open platform api based on OAuth 2.0. - */ -public class KaixinApi20 extends DefaultApi20 -{ - - private static final String AUTHORIZE_URL = "http://api.kaixin001.com/oauth2/authorize?client_id=%s&redirect_uri=%s&response_type=code"; - private static final String SCOPED_AUTHORIZE_URL = AUTHORIZE_URL + "&scope=%s"; - - @Override - public AccessTokenExtractor getAccessTokenExtractor() - { - return new JsonTokenExtractor(); - } - - @Override - public String getAccessTokenEndpoint() - { - return "https://api.kaixin001.com/oauth2/access_token?grant_type=authorization_code"; - } - - @Override - public String getAuthorizationUrl(OAuthConfig config) - { - // Append scope if present - if (config.hasScope()) - { - return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope())); - } - else - { - return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback())); - } - } -} diff --git a/src/main/java/org/scribe/builder/api/LinkedInApi.java b/src/main/java/org/scribe/builder/api/LinkedInApi.java deleted file mode 100644 index dc3e58327..000000000 --- a/src/main/java/org/scribe/builder/api/LinkedInApi.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -public class LinkedInApi extends DefaultApi10a -{ - private static final String AUTHORIZE_URL = "https://api.linkedin.com/uas/oauth/authenticate?oauth_token=%s"; - - @Override - public String getAccessTokenEndpoint() - { - return "https://api.linkedin.com/uas/oauth/accessToken"; - } - - @Override - public String getRequestTokenEndpoint() - { - return "https://api.linkedin.com/uas/oauth/requestToken"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } - -} diff --git a/src/main/java/org/scribe/builder/api/LiveApi.java b/src/main/java/org/scribe/builder/api/LiveApi.java deleted file mode 100644 index 18140f603..000000000 --- a/src/main/java/org/scribe/builder/api/LiveApi.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.extractors.*; -import org.scribe.model.*; -import org.scribe.utils.*; - -public class LiveApi extends DefaultApi20 -{ - - private static final String AUTHORIZE_URL = "https://oauth.live.com/authorize?client_id=%s&redirect_uri=%s&response_type=code"; - private static final String SCOPED_AUTHORIZE_URL = AUTHORIZE_URL + "&scope=%s"; - - @Override - public String getAccessTokenEndpoint() - { - return "https://oauth.live.com/token?grant_type=authorization_code"; - } - - @Override - public String getAuthorizationUrl(OAuthConfig config) - { - Preconditions.checkValidUrl(config.getCallback(), "Must provide a valid url as callback. Live does not support OOB"); - - // Append scope if present - if (config.hasScope()) - { - return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope())); - } - else - { - return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback())); - } - } - - @Override - public AccessTokenExtractor getAccessTokenExtractor() - { - return new JsonTokenExtractor(); - } -} \ No newline at end of file diff --git a/src/main/java/org/scribe/builder/api/LoveFilmApi.java b/src/main/java/org/scribe/builder/api/LoveFilmApi.java deleted file mode 100644 index 81a5bb874..000000000 --- a/src/main/java/org/scribe/builder/api/LoveFilmApi.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.Token; - -public class LoveFilmApi extends DefaultApi10a -{ - private static final String REQUEST_TOKEN_URL = "http://openapi.lovefilm.com/oauth/request_token"; - private static final String ACCESS_TOKEN_URL = "http://openapi.lovefilm.com/oauth/access_token"; - private static final String AUTHORIZE_URL = "https://www.lovefilm.com/activate?oauth_token=%s"; - - @Override - public String getRequestTokenEndpoint() - { - return REQUEST_TOKEN_URL; - } - - @Override - public String getAccessTokenEndpoint() - { - return ACCESS_TOKEN_URL; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } -} diff --git a/src/main/java/org/scribe/builder/api/MeetupApi.java b/src/main/java/org/scribe/builder/api/MeetupApi.java deleted file mode 100644 index 8f63e39e1..000000000 --- a/src/main/java/org/scribe/builder/api/MeetupApi.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.Token; - -/** - * OAuth access to the Meetup.com API. - * For more information visit http://www.meetup.com/api - */ -public class MeetupApi extends DefaultApi10a -{ - private static final String AUTHORIZE_URL = "http://www.meetup.com/authenticate?oauth_token=%s"; - - @Override - public String getRequestTokenEndpoint() - { - return "http://api.meetup.com/oauth/request/"; - } - - @Override - public String getAccessTokenEndpoint() - { - return "http://api.meetup.com/oauth/access/"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } -} diff --git a/src/main/java/org/scribe/builder/api/MendeleyApi.java b/src/main/java/org/scribe/builder/api/MendeleyApi.java deleted file mode 100644 index c6e0eced7..000000000 --- a/src/main/java/org/scribe/builder/api/MendeleyApi.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -/** - * @author Arieh "Vainolo" Bibliowicz - * @see http://apidocs.mendeley.com/home/authentication - */ -public class MendeleyApi extends DefaultApi10a -{ - - private static final String AUTHORIZATION_URL = "http://api.mendeley.com/oauth/authorize?oauth_token=%s"; - - @Override - public String getRequestTokenEndpoint() - { - return "http://api.mendeley.com/oauth/request_token/"; - } - - @Override - public String getAccessTokenEndpoint() - { - return "http://api.mendeley.com/oauth/access_token/"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZATION_URL, requestToken.getToken()); - } - - @Override - public Verb getAccessTokenVerb() - { - return Verb.GET; - } - - @Override - public Verb getRequestTokenVerb() - { - return Verb.GET; - } -} diff --git a/src/main/java/org/scribe/builder/api/MisoApi.java b/src/main/java/org/scribe/builder/api/MisoApi.java deleted file mode 100644 index a6d88d3df..000000000 --- a/src/main/java/org/scribe/builder/api/MisoApi.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.Token; - -public class MisoApi extends DefaultApi10a -{ - private static final String AUTHORIZE_URL = "http://gomiso.com/oauth/authorize?oauth_token=%s"; - private static final String REQUEST_TOKEN_RESOURCE = "http://gomiso.com/oauth/request_token"; - private static final String ACCESS_TOKEN_RESOURCE = "http://gomiso.com/oauth/access_token"; - - @Override - public String getAccessTokenEndpoint() - { - return ACCESS_TOKEN_RESOURCE; - } - - @Override - public String getRequestTokenEndpoint() - { - return REQUEST_TOKEN_RESOURCE; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } - -} diff --git a/src/main/java/org/scribe/builder/api/NetProspexApi.java b/src/main/java/org/scribe/builder/api/NetProspexApi.java deleted file mode 100644 index 8257de751..000000000 --- a/src/main/java/org/scribe/builder/api/NetProspexApi.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.Token; - -public class NetProspexApi extends DefaultApi10a -{ - private static final String REQUEST_TOKEN_URL = "https://api.netprospex.com/1.0/oauth/request-token"; - private static final String ACCESS_TOKEN_URL = "https://api.netprospex.com/1.0/oauth/access-token"; - private static final String AUTHORIZE_URL = "https://api.netprospex.com/1.0/oauth/authorize?oauth_token=%s"; - - @Override - public String getRequestTokenEndpoint() - { - return REQUEST_TOKEN_URL; - } - - @Override - public String getAccessTokenEndpoint() - { - return ACCESS_TOKEN_URL; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } -} diff --git a/src/main/java/org/scribe/builder/api/NeteaseWeibooApi.java b/src/main/java/org/scribe/builder/api/NeteaseWeibooApi.java deleted file mode 100644 index fae38ac30..000000000 --- a/src/main/java/org/scribe/builder/api/NeteaseWeibooApi.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -public class NeteaseWeibooApi extends DefaultApi10a -{ - private static final String REQUEST_TOKEN_URL = "http://api.t.163.com/oauth/request_token"; - private static final String ACCESS_TOKEN_URL = "http://api.t.163.com/oauth/access_token"; - private static final String AUTHORIZE_URL = "http://api.t.163.com/oauth/authorize?oauth_token=%s"; - private static final String AUTHENTICATE_URL = "http://api.t.163.com/oauth/authenticate?oauth_token=%s"; - - @Override - public String getRequestTokenEndpoint() - { - return REQUEST_TOKEN_URL; - } - - @Override - public String getAccessTokenEndpoint() - { - return ACCESS_TOKEN_URL; - } - - @Override - /** - * this method will ignore your callback - * if you're creating a desktop client please choose this url - * else your can call getAuthenticateUrl - * - * via http://open.t.163.com/wiki/index.php?title=%E8%AF%B7%E6%B1%82%E7%94%A8%E6%88%B7%E6%8E%88%E6%9D%83Token(oauth/authorize) - */ - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } - - /** - * this method is for web client with callback url - * if you're creating a desktop client please call getAuthorizationUrl - * - * via http://open.t.163.com/wiki/index.php?title=%E8%AF%B7%E6%B1%82%E7%94%A8%E6%88%B7%E6%8E%88%E6%9D%83Token(oauth/authenticate) - */ - public String getAuthenticateUrl(Token requestToken) - { - return String.format(AUTHENTICATE_URL, requestToken.getToken()); - } -} diff --git a/src/main/java/org/scribe/builder/api/PlurkApi.java b/src/main/java/org/scribe/builder/api/PlurkApi.java deleted file mode 100644 index 323ad2cf4..000000000 --- a/src/main/java/org/scribe/builder/api/PlurkApi.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.Token; - -public class PlurkApi extends DefaultApi10a -{ - private static final String REQUEST_TOKEN_URL = "http://www.plurk.com/OAuth/request_token"; - private static final String AUTHORIZATION_URL = "http://www.plurk.com/OAuth/authorize?oauth_token=%s"; - private static final String ACCESS_TOKEN_URL = "http://www.plurk.com/OAuth/access_token"; - - @Override - public String getRequestTokenEndpoint() - { - return REQUEST_TOKEN_URL; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZATION_URL, requestToken.getToken()); - } - - @Override - public String getAccessTokenEndpoint() - { - return ACCESS_TOKEN_URL; - } - - public class Mobile extends PlurkApi - { - private static final String AUTHORIZATION_URL = "http://www.plurk.com/m/authorize?oauth_token=%s"; - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZATION_URL, requestToken.getToken()); - } - } -} diff --git a/src/main/java/org/scribe/builder/api/Px500Api.java b/src/main/java/org/scribe/builder/api/Px500Api.java deleted file mode 100644 index f7f3b0e0a..000000000 --- a/src/main/java/org/scribe/builder/api/Px500Api.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -public class Px500Api extends DefaultApi10a -{ - private static final String AUTHORIZATION_URL = "https://api.500px.com/v1/oauth/authorize?oauth_token=%s"; - - @Override - public String getAccessTokenEndpoint() - { - return "https://api.500px.com/v1/oauth/access_token"; - } - - @Override - public String getRequestTokenEndpoint() - { - return "https://api.500px.com/v1/oauth/request_token"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZATION_URL, requestToken.getToken()); - } -} \ No newline at end of file diff --git a/src/main/java/org/scribe/builder/api/QWeiboApi.java b/src/main/java/org/scribe/builder/api/QWeiboApi.java deleted file mode 100644 index e16f28836..000000000 --- a/src/main/java/org/scribe/builder/api/QWeiboApi.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -public class QWeiboApi extends DefaultApi10a -{ - private static final String REQUEST_TOKEN_URL = "https://open.t.qq.com/cgi-bin/request_token"; - private static final String ACCESS_TOKEN_URL = "https://open.t.qq.com/cgi-bin/access_token"; - private static final String AUTHORIZE_URL = "https://open.t.qq.com/cgi-bin/authorize?oauth_token=%s"; - - @Override - public String getRequestTokenEndpoint() - { - return REQUEST_TOKEN_URL; - } - - @Override - public String getAccessTokenEndpoint() - { - return ACCESS_TOKEN_URL; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } -} diff --git a/src/main/java/org/scribe/builder/api/RenrenApi.java b/src/main/java/org/scribe/builder/api/RenrenApi.java deleted file mode 100644 index b31337ba4..000000000 --- a/src/main/java/org/scribe/builder/api/RenrenApi.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.extractors.*; -import org.scribe.model.*; -import org.scribe.utils.*; - -/** - * Renren(http://www.renren.com/) OAuth 2.0 based api. - */ -public class RenrenApi extends DefaultApi20 -{ - private static final String AUTHORIZE_URL = "https://graph.renren.com/oauth/authorize?client_id=%s&redirect_uri=%s&response_type=code"; - private static final String SCOPED_AUTHORIZE_URL = AUTHORIZE_URL + "&scope=%s"; - - @Override - public AccessTokenExtractor getAccessTokenExtractor() - { - return new JsonTokenExtractor(); - } - - @Override - public String getAccessTokenEndpoint() - { - return "https://graph.renren.com/oauth/token?grant_type=authorization_code"; - } - - @Override - public String getAuthorizationUrl(OAuthConfig config) - { - // Append scope if present - if (config.hasScope()) - { - return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope())); - } - else - { - return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback())); - } - } -} diff --git a/src/main/java/org/scribe/builder/api/SapoApi.java b/src/main/java/org/scribe/builder/api/SapoApi.java deleted file mode 100644 index 9771daf4c..000000000 --- a/src/main/java/org/scribe/builder/api/SapoApi.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -public class SapoApi extends DefaultApi10a -{ - private static final String AUTHORIZE_URL = "https://id.sapo.pt/oauth/authorize?oauth_token=%s"; - private static final String ACCESS_URL = "https://id.sapo.pt/oauth/access_token"; - private static final String REQUEST_URL = "https://id.sapo.pt/oauth/request_token"; - - @Override - public String getAccessTokenEndpoint() - { - return ACCESS_URL; - } - - @Override - public String getRequestTokenEndpoint() - { - return REQUEST_URL; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } - - @Override - public Verb getRequestTokenVerb() - { - return Verb.GET; - } - - @Override - public Verb getAccessTokenVerb() - { - return Verb.GET; - } -} \ No newline at end of file diff --git a/src/main/java/org/scribe/builder/api/SimpleGeoApi.java b/src/main/java/org/scribe/builder/api/SimpleGeoApi.java deleted file mode 100644 index 3e19df70a..000000000 --- a/src/main/java/org/scribe/builder/api/SimpleGeoApi.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.Token; - -/** - * @author: Pablo Fernandez - */ -public class SimpleGeoApi extends DefaultApi10a -{ - private static final String ENDPOINT = "these are not used since SimpleGeo uses 2 legged OAuth"; - - @Override - public String getRequestTokenEndpoint() - { - return ENDPOINT; - } - - @Override - public String getAccessTokenEndpoint() - { - return ENDPOINT; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return ENDPOINT; - } -} diff --git a/src/main/java/org/scribe/builder/api/SinaWeiboApi.java b/src/main/java/org/scribe/builder/api/SinaWeiboApi.java deleted file mode 100644 index 14951d31b..000000000 --- a/src/main/java/org/scribe/builder/api/SinaWeiboApi.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -public class SinaWeiboApi extends DefaultApi10a -{ - private static final String REQUEST_TOKEN_URL = "http://api.t.sina.com.cn/oauth/request_token"; - private static final String ACCESS_TOKEN_URL = "http://api.t.sina.com.cn/oauth/access_token"; - private static final String AUTHORIZE_URL = "http://api.t.sina.com.cn/oauth/authorize?oauth_token=%s"; - - @Override - public String getRequestTokenEndpoint() - { - return REQUEST_TOKEN_URL; - } - - @Override - public String getAccessTokenEndpoint() - { - return ACCESS_TOKEN_URL; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } -} diff --git a/src/main/java/org/scribe/builder/api/SinaWeiboApi20.java b/src/main/java/org/scribe/builder/api/SinaWeiboApi20.java deleted file mode 100644 index e0744c432..000000000 --- a/src/main/java/org/scribe/builder/api/SinaWeiboApi20.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.extractors.*; -import org.scribe.model.*; -import org.scribe.utils.*; - -/** - * SinaWeibo OAuth 2.0 api. - */ -public class SinaWeiboApi20 extends DefaultApi20 -{ - private static final String AUTHORIZE_URL = "https://api.weibo.com/oauth2/authorize?client_id=%s&redirect_uri=%s&response_type=code"; - private static final String SCOPED_AUTHORIZE_URL = AUTHORIZE_URL + "&scope=%s"; - - @Override - public Verb getAccessTokenVerb() - { - return Verb.POST; - } - - @Override - public AccessTokenExtractor getAccessTokenExtractor() - { - return new JsonTokenExtractor(); - } - - @Override - public String getAccessTokenEndpoint() - { - return "https://api.weibo.com/oauth2/access_token?grant_type=authorization_code"; - } - - @Override - public String getAuthorizationUrl(OAuthConfig config) - { - // Append scope if present - if (config.hasScope()) - { - return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope())); - } - else - { - return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback())); - } - } -} diff --git a/src/main/java/org/scribe/builder/api/SkyrockApi.java b/src/main/java/org/scribe/builder/api/SkyrockApi.java deleted file mode 100644 index b0e76a303..000000000 --- a/src/main/java/org/scribe/builder/api/SkyrockApi.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -/** - * OAuth API for Skyrock. - * - * @author Nicolas Quiénot - * @see Skyrock.com API - */ -public class SkyrockApi extends DefaultApi10a -{ - private static final String API_ENDPOINT = "https://api.skyrock.com/v2"; - private static final String REQUEST_TOKEN_RESOURCE = "/oauth/initiate"; - private static final String AUTHORIZE_URL = "/oauth/authorize?oauth_token=%s"; - private static final String ACCESS_TOKEN_RESOURCE = "/oauth/token"; - - @Override - public String getAccessTokenEndpoint() - { - return API_ENDPOINT + ACCESS_TOKEN_RESOURCE; - } - - @Override - public String getRequestTokenEndpoint() - { - return API_ENDPOINT + REQUEST_TOKEN_RESOURCE; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(API_ENDPOINT + AUTHORIZE_URL, requestToken.getToken()); - } -} diff --git a/src/main/java/org/scribe/builder/api/SohuWeiboApi.java b/src/main/java/org/scribe/builder/api/SohuWeiboApi.java deleted file mode 100644 index 1f927b7a5..000000000 --- a/src/main/java/org/scribe/builder/api/SohuWeiboApi.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -public class SohuWeiboApi extends DefaultApi10a -{ - private static final String REQUEST_TOKEN_URL = "http://api.t.sohu.com/oauth/request_token"; - private static final String ACCESS_TOKEN_URL = "http://api.t.sohu.com/oauth/access_token"; - private static final String AUTHORIZE_URL = "http://api.t.sohu.com/oauth/authorize?oauth_token=%s"; - - @Override - public String getRequestTokenEndpoint() - { - return REQUEST_TOKEN_URL; - } - - @Override - public String getAccessTokenEndpoint() - { - return ACCESS_TOKEN_URL; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } -} diff --git a/src/main/java/org/scribe/builder/api/TrelloApi.java b/src/main/java/org/scribe/builder/api/TrelloApi.java deleted file mode 100644 index 9e46730d4..000000000 --- a/src/main/java/org/scribe/builder/api/TrelloApi.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; - -public class TrelloApi extends DefaultApi10a -{ - private static final String AUTHORIZE_URL = "https://trello.com/1/OAuthAuthorizeToken?oauth_token=%s"; - - @Override - public String getAccessTokenEndpoint() - { - return "https://trello.com/1/OAuthGetAccessToken"; - } - - @Override - public String getRequestTokenEndpoint() - { - return "https://trello.com/1/OAuthGetRequestToken"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } - -} diff --git a/src/main/java/org/scribe/builder/api/TumblrApi.java b/src/main/java/org/scribe/builder/api/TumblrApi.java deleted file mode 100644 index ee680ee8a..000000000 --- a/src/main/java/org/scribe/builder/api/TumblrApi.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.Token; - -public class TumblrApi extends DefaultApi10a -{ - private static final String AUTHORIZE_URL = "https://www.tumblr.com/oauth/authorize?oauth_token=%s"; - private static final String REQUEST_TOKEN_RESOURCE = "http://www.tumblr.com/oauth/request_token"; - private static final String ACCESS_TOKEN_RESOURCE = "http://www.tumblr.com/oauth/access_token"; - - @Override - public String getAccessTokenEndpoint() - { - return ACCESS_TOKEN_RESOURCE; - } - - @Override - public String getRequestTokenEndpoint() - { - return REQUEST_TOKEN_RESOURCE; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } -} diff --git a/src/main/java/org/scribe/builder/api/TwitterApi.java b/src/main/java/org/scribe/builder/api/TwitterApi.java deleted file mode 100644 index a83c28e71..000000000 --- a/src/main/java/org/scribe/builder/api/TwitterApi.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.Token; - -public class TwitterApi extends DefaultApi10a -{ - private static final String AUTHORIZE_URL = "https://api.twitter.com/oauth/authorize?oauth_token=%s"; - private static final String REQUEST_TOKEN_RESOURCE = "api.twitter.com/oauth/request_token"; - private static final String ACCESS_TOKEN_RESOURCE = "api.twitter.com/oauth/access_token"; - - @Override - public String getAccessTokenEndpoint() - { - return "http://" + ACCESS_TOKEN_RESOURCE; - } - - @Override - public String getRequestTokenEndpoint() - { - return "http://" + REQUEST_TOKEN_RESOURCE; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } - - public static class SSL extends TwitterApi - { - @Override - public String getAccessTokenEndpoint() - { - return "https://" + ACCESS_TOKEN_RESOURCE; - } - - @Override - public String getRequestTokenEndpoint() - { - return "https://" + REQUEST_TOKEN_RESOURCE; - } - } - - /** - * Twitter 'friendlier' authorization endpoint for OAuth. - * - * Uses SSL. - */ - public static class Authenticate extends SSL - { - private static final String AUTHENTICATE_URL = "https://api.twitter.com/oauth/authenticate?oauth_token=%s"; - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHENTICATE_URL, requestToken.getToken()); - } - } - - /** - * Just an alias to the default (SSL) authorization endpoint. - * - * Need to include this for symmetry with 'Authenticate' only. - */ - public static class Authorize extends SSL{} -} diff --git a/src/main/java/org/scribe/builder/api/UbuntuOneApi.java b/src/main/java/org/scribe/builder/api/UbuntuOneApi.java deleted file mode 100644 index 2a72c3afe..000000000 --- a/src/main/java/org/scribe/builder/api/UbuntuOneApi.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.Token; -import org.scribe.services.*; - -/** - * @author Julio Gutierrez - * - * Sep 6, 2012 - */ -public class UbuntuOneApi extends DefaultApi10a -{ - - private static final String AUTHORIZATION_URL = "https://one.ubuntu.com/oauth/authorize/?oauth_token=%s"; - - @Override - public String getAccessTokenEndpoint() - { - return "https://one.ubuntu.com/oauth/access/"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZATION_URL, requestToken.getToken()); - } - - @Override - public String getRequestTokenEndpoint() - { - return "https://one.ubuntu.com/oauth/request/"; - } - - @Override - public SignatureService getSignatureService() - { - return new PlaintextSignatureService(); - } - -} diff --git a/src/main/java/org/scribe/builder/api/VimeoApi.java b/src/main/java/org/scribe/builder/api/VimeoApi.java deleted file mode 100644 index 231895dab..000000000 --- a/src/main/java/org/scribe/builder/api/VimeoApi.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.Token; - -public class VimeoApi extends DefaultApi10a -{ - private static final String AUTHORIZATION_URL = "http://vimeo.com/oauth/authorize?oauth_token=%s"; - - @Override - public String getAccessTokenEndpoint() - { - return "http://vimeo.com/oauth/access_token"; - } - - @Override - public String getRequestTokenEndpoint() - { - return "http://vimeo.com/oauth/request_token"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZATION_URL, requestToken.getToken()); - } -} diff --git a/src/main/java/org/scribe/builder/api/VkontakteApi.java b/src/main/java/org/scribe/builder/api/VkontakteApi.java deleted file mode 100644 index e12f39559..000000000 --- a/src/main/java/org/scribe/builder/api/VkontakteApi.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.extractors.*; -import org.scribe.utils.*; -import org.scribe.model.*; - -/** - * @author Boris G. Tsirkin - * @since 20.4.2011 - */ -public class VkontakteApi extends DefaultApi20 -{ - private static final String AUTHORIZE_URL = "https://oauth.vk.com/authorize?client_id=%s&redirect_uri=%s&response_type=code"; - private static final String SCOPED_AUTHORIZE_URL = String.format("%s&scope=%%s", AUTHORIZE_URL); - - @Override - public String getAccessTokenEndpoint() - { - return "https://api.vkontakte.ru/oauth/access_token"; - } - - @Override - public String getAuthorizationUrl(OAuthConfig config) - { - Preconditions.checkValidUrl(config.getCallback(), "Valid url is required for a callback. Vkontakte does not support OOB"); - if(config.hasScope())// Appending scope if present - { - return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope())); - } - else - { - return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback())); - } - } - - @Override - public AccessTokenExtractor getAccessTokenExtractor() - { - return new JsonTokenExtractor(); - } -} diff --git a/src/main/java/org/scribe/builder/api/YahooApi.java b/src/main/java/org/scribe/builder/api/YahooApi.java deleted file mode 100644 index e8a29a738..000000000 --- a/src/main/java/org/scribe/builder/api/YahooApi.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.Token; - -public class YahooApi extends DefaultApi10a -{ - private static final String AUTHORIZE_URL = "https://api.login.yahoo.com/oauth/v2/request_auth?oauth_token=%s"; - - @Override - public String getAccessTokenEndpoint() - { - return "https://api.login.yahoo.com/oauth/v2/get_token"; - } - - @Override - public String getRequestTokenEndpoint() - { - return "https://api.login.yahoo.com/oauth/v2/get_request_token"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZE_URL, requestToken.getToken()); - } -} diff --git a/src/main/java/org/scribe/builder/api/YammerApi.java b/src/main/java/org/scribe/builder/api/YammerApi.java deleted file mode 100644 index e06543d97..000000000 --- a/src/main/java/org/scribe/builder/api/YammerApi.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.scribe.builder.api; - -import org.scribe.model.*; -import org.scribe.services.*; - -public class YammerApi extends DefaultApi10a -{ - private static final String AUTHORIZATION_URL = "https://www.yammer.com/oauth/authorize?oauth_token=%s"; - - @Override - public String getRequestTokenEndpoint() - { - return "https://www.yammer.com/oauth/request_token"; - } - - @Override - public String getAccessTokenEndpoint() - { - return "https://www.yammer.com/oauth/access_token"; - } - - @Override - public String getAuthorizationUrl(Token requestToken) - { - return String.format(AUTHORIZATION_URL, requestToken.getToken()); - } - - @Override - public SignatureService getSignatureService() - { - return new PlaintextSignatureService(); - } -} diff --git a/src/main/java/org/scribe/exceptions/OAuthConnectionException.java b/src/main/java/org/scribe/exceptions/OAuthConnectionException.java deleted file mode 100644 index 918de810c..000000000 --- a/src/main/java/org/scribe/exceptions/OAuthConnectionException.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.scribe.exceptions; - -/** - * @author: Pablo Fernandez - */ -public class OAuthConnectionException extends OAuthException -{ - private static final String MSG = "There was a problem while creating a connection to the remote service."; - - public OAuthConnectionException(Exception e) - { - super(MSG, e); - } -} diff --git a/src/main/java/org/scribe/exceptions/OAuthException.java b/src/main/java/org/scribe/exceptions/OAuthException.java deleted file mode 100644 index 85f49d9b4..000000000 --- a/src/main/java/org/scribe/exceptions/OAuthException.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.scribe.exceptions; - -/** - * Default scribe exception. - * Represents a problem in the OAuth signing process - * - * @author Pablo Fernandez - */ -public class OAuthException extends RuntimeException -{ - - /** - * Default constructor - * @param message message explaining what went wrong - * @param e original exception - */ - public OAuthException(String message, Exception e) - { - super(message, e); - } - - /** - * No-exception constructor. Used when there is no original exception - * - * @param message message explaining what went wrong - */ - public OAuthException(String message) - { - super(message, null); - } - - private static final long serialVersionUID = 1L; -} diff --git a/src/main/java/org/scribe/exceptions/OAuthParametersMissingException.java b/src/main/java/org/scribe/exceptions/OAuthParametersMissingException.java deleted file mode 100644 index 8407ce493..000000000 --- a/src/main/java/org/scribe/exceptions/OAuthParametersMissingException.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.scribe.exceptions; - -import org.scribe.model.*; - -/** - * Specialized exception that represents a missing OAuth parameter. - * - * @author Pablo Fernandez - */ -public class OAuthParametersMissingException extends OAuthException -{ - - private static final long serialVersionUID = 1745308760111976671L; - private static final String MSG = "Could not find oauth parameters in request: %s. " - + "OAuth parameters must be specified with the addOAuthParameter() method"; - - /** - * Default constructor. - * - * @param request OAuthRequest that caused the error - */ - public OAuthParametersMissingException(OAuthRequest request) - { - super(String.format(MSG, request)); - } -} diff --git a/src/main/java/org/scribe/exceptions/OAuthSignatureException.java b/src/main/java/org/scribe/exceptions/OAuthSignatureException.java deleted file mode 100644 index 94692be5d..000000000 --- a/src/main/java/org/scribe/exceptions/OAuthSignatureException.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.scribe.exceptions; - -/** - * Specialized exception that represents a problem in the signature - * - * @author Pablo Fernandez - */ -public class OAuthSignatureException extends OAuthException -{ - private static final long serialVersionUID = 1L; - private static final String MSG = "Error while signing string: %s"; - - /** - * Default constructor - * - * @param stringToSign plain string that gets signed (HMAC-SHA, etc) - * @param e original exception - */ - public OAuthSignatureException(String stringToSign, Exception e) - { - super(String.format(MSG, stringToSign), e); - } - -} diff --git a/src/main/java/org/scribe/extractors/AccessTokenExtractor.java b/src/main/java/org/scribe/extractors/AccessTokenExtractor.java deleted file mode 100644 index 3c0dd34d6..000000000 --- a/src/main/java/org/scribe/extractors/AccessTokenExtractor.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.scribe.extractors; - -import org.scribe.model.*; - -/** - * Simple command object that extracts a {@link Token} from a String - * - * @author Pablo Fernandez - */ -public interface AccessTokenExtractor -{ - /** - * Extracts the access token from the contents of an Http Response - * - * @param response the contents of the response - * @return OAuth access token - */ - public Token extract(String response); -} diff --git a/src/main/java/org/scribe/extractors/BaseStringExtractor.java b/src/main/java/org/scribe/extractors/BaseStringExtractor.java deleted file mode 100644 index 83ddd10fc..000000000 --- a/src/main/java/org/scribe/extractors/BaseStringExtractor.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.scribe.extractors; - -import org.scribe.model.*; - -/** - * Simple command object that extracts a base string from a {@link OAuthRequest} - * - * @author Pablo Fernandez - */ -public interface BaseStringExtractor -{ - /** - * Extracts an url-encoded base string from the {@link OAuthRequest}. - * - * See the oauth spec for more info on this. - * - * @param request the OAuthRequest - * @return the url-encoded base string - */ - String extract(OAuthRequest request); -} diff --git a/src/main/java/org/scribe/extractors/BaseStringExtractorImpl.java b/src/main/java/org/scribe/extractors/BaseStringExtractorImpl.java deleted file mode 100644 index ca21a0d1f..000000000 --- a/src/main/java/org/scribe/extractors/BaseStringExtractorImpl.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.scribe.extractors; - -import org.scribe.exceptions.*; -import org.scribe.model.*; -import org.scribe.utils.*; - -/** - * Default implementation of {@link BaseStringExtractor}. Conforms to OAuth 1.0a - * - * @author Pablo Fernandez - * - */ -public class BaseStringExtractorImpl implements BaseStringExtractor -{ - - private static final String AMPERSAND_SEPARATED_STRING = "%s&%s&%s"; - - /** - * {@inheritDoc} - */ - public String extract(OAuthRequest request) - { - checkPreconditions(request); - String verb = OAuthEncoder.encode(request.getVerb().name()); - String url = OAuthEncoder.encode(request.getSanitizedUrl()); - String params = getSortedAndEncodedParams(request); - return String.format(AMPERSAND_SEPARATED_STRING, verb, url, params); - } - - private String getSortedAndEncodedParams(OAuthRequest request) - { - ParameterList params = new ParameterList(); - params.addAll(request.getQueryStringParams()); - params.addAll(request.getBodyParams()); - params.addAll(new ParameterList(request.getOauthParameters())); - return params.sort().asOauthBaseString(); - } - - private void checkPreconditions(OAuthRequest request) - { - Preconditions.checkNotNull(request, "Cannot extract base string from null object"); - - if (request.getOauthParameters() == null || request.getOauthParameters().size() <= 0) - { - throw new OAuthParametersMissingException(request); - } - } -} diff --git a/src/main/java/org/scribe/extractors/HeaderExtractor.java b/src/main/java/org/scribe/extractors/HeaderExtractor.java deleted file mode 100644 index 2bc1f8bd4..000000000 --- a/src/main/java/org/scribe/extractors/HeaderExtractor.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.scribe.extractors; - -import org.scribe.model.*; - -/** - * Simple command object that generates an OAuth Authorization header to include in the request. - * - * @author Pablo Fernandez - */ -public interface HeaderExtractor -{ - /** - * Generates an OAuth 'Authorization' Http header to include in requests as the signature. - * - * @param request the OAuthRequest to inspect and generate the header - * @return the Http header value - */ - String extract(OAuthRequest request); -} diff --git a/src/main/java/org/scribe/extractors/HeaderExtractorImpl.java b/src/main/java/org/scribe/extractors/HeaderExtractorImpl.java deleted file mode 100644 index 73c4ada35..000000000 --- a/src/main/java/org/scribe/extractors/HeaderExtractorImpl.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.scribe.extractors; - -import java.util.*; - -import org.scribe.exceptions.*; -import org.scribe.model.*; -import org.scribe.utils.*; - -/** - * Default implementation of {@link HeaderExtractor}. Conforms to OAuth 1.0a - * - * @author Pablo Fernandez - * - */ -public class HeaderExtractorImpl implements HeaderExtractor -{ - private static final String PARAM_SEPARATOR = ", "; - private static final String PREAMBLE = "OAuth "; - - /** - * {@inheritDoc} - */ - public String extract(OAuthRequest request) - { - checkPreconditions(request); - Map parameters = request.getOauthParameters(); - StringBuffer header = new StringBuffer(parameters.size() * 20); - header.append(PREAMBLE); - for (String key : parameters.keySet()) - { - if(header.length() > PREAMBLE.length()) - { - header.append(PARAM_SEPARATOR); - } - header.append(String.format("%s=\"%s\"", key, OAuthEncoder.encode(parameters.get(key)))); - } - return header.toString(); - } - - private void checkPreconditions(OAuthRequest request) - { - Preconditions.checkNotNull(request, "Cannot extract a header from a null object"); - - if (request.getOauthParameters() == null || request.getOauthParameters().size() <= 0) - { - throw new OAuthParametersMissingException(request); - } - } - -} diff --git a/src/main/java/org/scribe/extractors/JsonTokenExtractor.java b/src/main/java/org/scribe/extractors/JsonTokenExtractor.java deleted file mode 100644 index 801cd6296..000000000 --- a/src/main/java/org/scribe/extractors/JsonTokenExtractor.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.scribe.extractors; - -import java.util.regex.*; - -import org.scribe.exceptions.*; -import org.scribe.model.*; -import org.scribe.utils.*; - -public class JsonTokenExtractor implements AccessTokenExtractor -{ - private Pattern accessTokenPattern = Pattern.compile("\"access_token\":\\s*\"(\\S*?)\""); - - public Token extract(String response) - { - Preconditions.checkEmptyString(response, "Cannot extract a token from a null or empty String"); - Matcher matcher = accessTokenPattern.matcher(response); - if(matcher.find()) - { - return new Token(matcher.group(1), "", response); - } - else - { - throw new OAuthException("Cannot extract an acces token. Response was: " + response); - } - } - -} \ No newline at end of file diff --git a/src/main/java/org/scribe/extractors/RequestTokenExtractor.java b/src/main/java/org/scribe/extractors/RequestTokenExtractor.java deleted file mode 100644 index 1830212b6..000000000 --- a/src/main/java/org/scribe/extractors/RequestTokenExtractor.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.scribe.extractors; - -import org.scribe.model.*; - -/** - * Simple command object that extracts a {@link Token} from a String - * - * @author Pablo Fernandez - */ -public interface RequestTokenExtractor -{ - /** - * Extracts the request token from the contents of an Http Response - * - * @param response the contents of the response - * @return OAuth access token - */ - public Token extract(String response); -} diff --git a/src/main/java/org/scribe/extractors/TokenExtractor20Impl.java b/src/main/java/org/scribe/extractors/TokenExtractor20Impl.java deleted file mode 100644 index 1eb22ad63..000000000 --- a/src/main/java/org/scribe/extractors/TokenExtractor20Impl.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.scribe.extractors; - -import java.util.regex.*; - -import org.scribe.exceptions.*; -import org.scribe.model.*; -import org.scribe.utils.*; - -/** - * Default implementation of {@AccessTokenExtractor}. Conforms to OAuth 2.0 - * - */ -public class TokenExtractor20Impl implements AccessTokenExtractor -{ - private static final String TOKEN_REGEX = "access_token=([^&]+)"; - private static final String EMPTY_SECRET = ""; - - /** - * {@inheritDoc} - */ - public Token extract(String response) - { - Preconditions.checkEmptyString(response, "Response body is incorrect. Can't extract a token from an empty string"); - - Matcher matcher = Pattern.compile(TOKEN_REGEX).matcher(response); - if (matcher.find()) - { - String token = OAuthEncoder.decode(matcher.group(1)); - return new Token(token, EMPTY_SECRET, response); - } - else - { - throw new OAuthException("Response body is incorrect. Can't extract a token from this: '" + response + "'", null); - } - } -} diff --git a/src/main/java/org/scribe/extractors/TokenExtractorImpl.java b/src/main/java/org/scribe/extractors/TokenExtractorImpl.java deleted file mode 100644 index ba1784b9b..000000000 --- a/src/main/java/org/scribe/extractors/TokenExtractorImpl.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.scribe.extractors; - -import java.util.regex.*; - -import org.scribe.exceptions.*; -import org.scribe.model.*; -import org.scribe.utils.*; - -/** - * Default implementation of {@RequestTokenExtractor} and {@AccessTokenExtractor}. Conforms to OAuth 1.0a - * - * The process for extracting access and request tokens is similar so this class can do both things. - * - * @author Pablo Fernandez - */ -public class TokenExtractorImpl implements RequestTokenExtractor, AccessTokenExtractor -{ - private static final Pattern TOKEN_REGEX = Pattern.compile("oauth_token=([^&]+)"); - private static final Pattern SECRET_REGEX = Pattern.compile("oauth_token_secret=([^&]*)"); - - /** - * {@inheritDoc} - */ - public Token extract(String response) - { - Preconditions.checkEmptyString(response, "Response body is incorrect. Can't extract a token from an empty string"); - String token = extract(response, TOKEN_REGEX); - String secret = extract(response, SECRET_REGEX); - return new Token(token, secret, response); - } - - private String extract(String response, Pattern p) - { - Matcher matcher = p.matcher(response); - if (matcher.find() && matcher.groupCount() >= 1) - { - return OAuthEncoder.decode(matcher.group(1)); - } - else - { - throw new OAuthException("Response body is incorrect. Can't extract token and secret from this: '" + response + "'", null); - } - } -} diff --git a/src/main/java/org/scribe/model/OAuthConfig.java b/src/main/java/org/scribe/model/OAuthConfig.java deleted file mode 100644 index 374c95894..000000000 --- a/src/main/java/org/scribe/model/OAuthConfig.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.scribe.model; - -import java.io.*; - -/** - * Parameter object that groups OAuth config values - * - * @author Pablo Fernandez - */ -public class OAuthConfig -{ - private final String apiKey; - private final String apiSecret; - private final String callback; - private final SignatureType signatureType; - private final String scope; - private final OutputStream debugStream; - - public OAuthConfig(String key, String secret) - { - this(key, secret, null, null, null, null); - } - - public OAuthConfig(String key, String secret, String callback, SignatureType type, String scope, OutputStream stream) - { - this.apiKey = key; - this.apiSecret = secret; - this.callback = callback; - this.signatureType = type; - this.scope = scope; - this.debugStream = stream; - } - - public String getApiKey() - { - return apiKey; - } - - public String getApiSecret() - { - return apiSecret; - } - - public String getCallback() - { - return callback; - } - - public SignatureType getSignatureType() - { - return signatureType; - } - - public String getScope() - { - return scope; - } - - public boolean hasScope() - { - return scope != null; - } - - public void log(String message) - { - if (debugStream != null) - { - message = message + "\n"; - try - { - debugStream.write(message.getBytes("UTF8")); - } - catch (Exception e) - { - throw new RuntimeException("there were problems while writting to the debug stream", e); - } - } - } -} diff --git a/src/main/java/org/scribe/model/OAuthConstants.java b/src/main/java/org/scribe/model/OAuthConstants.java deleted file mode 100644 index c93c31c71..000000000 --- a/src/main/java/org/scribe/model/OAuthConstants.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -Copyright 2010 Pablo Fernandez - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - */ -package org.scribe.model; - -/** - * This class contains OAuth constants, used project-wide - * - * @author Pablo Fernandez - */ -public class OAuthConstants -{ - public static final String TIMESTAMP = "oauth_timestamp"; - public static final String SIGN_METHOD = "oauth_signature_method"; - public static final String SIGNATURE = "oauth_signature"; - public static final String CONSUMER_SECRET = "oauth_consumer_secret"; - public static final String CONSUMER_KEY = "oauth_consumer_key"; - public static final String CALLBACK = "oauth_callback"; - public static final String VERSION = "oauth_version"; - public static final String NONCE = "oauth_nonce"; - public static final String PARAM_PREFIX = "oauth_"; - public static final String TOKEN = "oauth_token"; - public static final String TOKEN_SECRET = "oauth_token_secret"; - public static final String OUT_OF_BAND = "oob"; - public static final String VERIFIER = "oauth_verifier"; - public static final String HEADER = "Authorization"; - public static final Token EMPTY_TOKEN = new Token("", ""); - public static final String SCOPE = "scope"; - - //OAuth 2.0 - public static final String ACCESS_TOKEN = "access_token"; - public static final String CLIENT_ID = "client_id"; - public static final String CLIENT_SECRET = "client_secret"; - public static final String REDIRECT_URI = "redirect_uri"; - public static final String CODE = "code"; - -} diff --git a/src/main/java/org/scribe/model/OAuthRequest.java b/src/main/java/org/scribe/model/OAuthRequest.java deleted file mode 100644 index 43892278f..000000000 --- a/src/main/java/org/scribe/model/OAuthRequest.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.scribe.model; - -import java.util.*; - -/** - * The representation of an OAuth HttpRequest. - * - * Adds OAuth-related functionality to the {@link Request} - * - * @author Pablo Fernandez - */ -public class OAuthRequest extends Request -{ - private static final String OAUTH_PREFIX = "oauth_"; - private Map oauthParameters; - - /** - * Default constructor. - * - * @param verb Http verb/method - * @param url resource URL - */ - public OAuthRequest(Verb verb, String url) - { - super(verb, url); - this.oauthParameters = new HashMap(); - } - - /** - * Adds an OAuth parameter. - * - * @param key name of the parameter - * @param value value of the parameter - * - * @throws IllegalArgumentException if the parameter is not an OAuth parameter - */ - public void addOAuthParameter(String key, String value) - { - oauthParameters.put(checkKey(key), value); - } - - private String checkKey(String key) - { - if (key.startsWith(OAUTH_PREFIX) || key.equals(OAuthConstants.SCOPE)) - { - return key; - } - else - { - throw new IllegalArgumentException(String.format("OAuth parameters must either be '%s' or start with '%s'", OAuthConstants.SCOPE, OAUTH_PREFIX)); - } - } - - /** - * Returns the {@link Map} containing the key-value pair of parameters. - * - * @return parameters as map - */ - public Map getOauthParameters() - { - return oauthParameters; - } - - @Override - public String toString() - { - return String.format("@OAuthRequest(%s, %s)", getVerb(), getUrl()); - } -} diff --git a/src/main/java/org/scribe/model/Parameter.java b/src/main/java/org/scribe/model/Parameter.java deleted file mode 100644 index 9fe610b43..000000000 --- a/src/main/java/org/scribe/model/Parameter.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.scribe.model; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import org.scribe.exceptions.OAuthException; -import org.scribe.utils.OAuthEncoder; - -/** - * @author: Pablo Fernandez - */ -public class Parameter implements Comparable -{ - private static final String UTF = "UTF8"; - - private final String key; - private final String value; - - public Parameter(String key, String value) - { - this.key = key; - this.value = value; - } - - public String asUrlEncodedPair() - { - return OAuthEncoder.encode(key).concat("=").concat(OAuthEncoder.encode(value)); - } - - public boolean equals(Object other) - { - if(other == null) return false; - if(other == this) return true; - if(!(other instanceof Parameter)) return false; - - Parameter otherParam = (Parameter) other; - return otherParam.key.equals(key) && otherParam.value.equals(value); - } - - public int hashCode() - { - return key.hashCode() + value.hashCode(); - } - - public int compareTo(Parameter parameter) - { - int keyDiff = key.compareTo(parameter.key); - - return keyDiff != 0 ? keyDiff : value.compareTo(parameter.value); - } -} diff --git a/src/main/java/org/scribe/model/ParameterList.java b/src/main/java/org/scribe/model/ParameterList.java deleted file mode 100644 index b365cbaf6..000000000 --- a/src/main/java/org/scribe/model/ParameterList.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.scribe.model; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import org.scribe.utils.OAuthEncoder; -import org.scribe.utils.Preconditions; - -/** - * @author: Pablo Fernandez - */ -public class ParameterList -{ - private static final char QUERY_STRING_SEPARATOR = '?'; - private static final String PARAM_SEPARATOR = "&"; - private static final String PAIR_SEPARATOR = "="; - private static final String EMPTY_STRING = ""; - - private final List params; - - public ParameterList() - { - params = new ArrayList(); - } - - ParameterList(List params) - { - this.params = new ArrayList(params); - } - - public ParameterList(Map map) - { - this(); - for(Map.Entry entry : map.entrySet()) - { - params.add(new Parameter(entry.getKey(), entry.getValue())); - } - } - - public void add(String key, String value) - { - params.add(new Parameter(key, value)); - } - - public String appendTo(String url) - { - Preconditions.checkNotNull(url, "Cannot append to null URL"); - String queryString = asFormUrlEncodedString(); - if (queryString.equals(EMPTY_STRING)) - { - return url; - } - else - { - url += url.indexOf(QUERY_STRING_SEPARATOR) != -1 ? PARAM_SEPARATOR : QUERY_STRING_SEPARATOR; - url += queryString; - return url; - } - } - - public String asOauthBaseString() - { - return OAuthEncoder.encode(asFormUrlEncodedString()); - } - - public String asFormUrlEncodedString() - { - if (params.size() == 0) return EMPTY_STRING; - - StringBuilder builder = new StringBuilder(); - for(Parameter p : params) - { - builder.append('&').append(p.asUrlEncodedPair()); - } - return builder.toString().substring(1); - } - - public void addAll(ParameterList other) - { - params.addAll(other.params); - } - - public void addQuerystring(String queryString) - { - if (queryString != null && queryString.length() > 0) - { - for (String param : queryString.split(PARAM_SEPARATOR)) - { - String pair[] = param.split(PAIR_SEPARATOR); - String key = OAuthEncoder.decode(pair[0]); - String value = pair.length > 1 ? OAuthEncoder.decode(pair[1]) : EMPTY_STRING; - params.add(new Parameter(key, value)); - } - } - } - - public boolean contains(Parameter param) - { - return params.contains(param); - } - - public int size() - { - return params.size(); - } - - public ParameterList sort() - { - ParameterList sorted = new ParameterList(params); - Collections.sort(sorted.params); - return sorted; - } -} diff --git a/src/main/java/org/scribe/model/Request.java b/src/main/java/org/scribe/model/Request.java deleted file mode 100644 index b19e4a80d..000000000 --- a/src/main/java/org/scribe/model/Request.java +++ /dev/null @@ -1,367 +0,0 @@ -package org.scribe.model; - -import java.io.*; -import java.net.*; -import java.nio.charset.*; -import java.util.*; -import java.util.concurrent.TimeUnit; - -import org.scribe.exceptions.*; - -/** - * Represents an HTTP Request object - * - * @author Pablo Fernandez - */ -public class Request -{ - private static final String CONTENT_LENGTH = "Content-Length"; - private static final String CONTENT_TYPE = "Content-Type"; - private static RequestTuner NOOP = new RequestTuner() { - @Override public void tune(Request _){} - }; - public static final String DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded"; - - private String url; - private Verb verb; - private ParameterList querystringParams; - private ParameterList bodyParams; - private Map headers; - private String payload = null; - private HttpURLConnection connection; - private String charset; - private byte[] bytePayload = null; - private boolean connectionKeepAlive = false; - private Long connectTimeout = null; - private Long readTimeout = null; - - /** - * Creates a new Http Request - * - * @param verb Http Verb (GET, POST, etc) - * @param url url with optional querystring parameters. - */ - public Request(Verb verb, String url) - { - this.verb = verb; - this.url = url; - this.querystringParams = new ParameterList(); - this.bodyParams = new ParameterList(); - this.headers = new HashMap(); - } - - /** - * Execute the request and return a {@link Response} - * - * @return Http Response - * @throws RuntimeException - * if the connection cannot be created. - */ - public Response send(RequestTuner tuner) - { - try - { - createConnection(); - return doSend(tuner); - } - catch (Exception e) - { - throw new OAuthConnectionException(e); - } - } - - public Response send() - { - return send(NOOP); - } - - private void createConnection() throws IOException - { - String completeUrl = getCompleteUrl(); - if (connection == null) - { - System.setProperty("http.keepAlive", connectionKeepAlive ? "true" : "false"); - connection = (HttpURLConnection) new URL(completeUrl).openConnection(); - } - } - - /** - * Returns the complete url (host + resource + encoded querystring parameters). - * - * @return the complete url. - */ - public String getCompleteUrl() - { - return querystringParams.appendTo(url); - } - - Response doSend(RequestTuner tuner) throws IOException - { - connection.setRequestMethod(this.verb.name()); - if (connectTimeout != null) - { - connection.setConnectTimeout(connectTimeout.intValue()); - } - if (readTimeout != null) - { - connection.setReadTimeout(readTimeout.intValue()); - } - addHeaders(connection); - if (verb.equals(Verb.PUT) || verb.equals(Verb.POST)) - { - addBody(connection, getByteBodyContents()); - } - tuner.tune(this); - return new Response(connection); - } - - void addHeaders(HttpURLConnection conn) - { - for (String key : headers.keySet()) - conn.setRequestProperty(key, headers.get(key)); - } - - void addBody(HttpURLConnection conn, byte[] content) throws IOException - { - conn.setRequestProperty(CONTENT_LENGTH, String.valueOf(content.length)); - - // Set default content type if none is set. - if (conn.getRequestProperty(CONTENT_TYPE) == null) - { - conn.setRequestProperty(CONTENT_TYPE, DEFAULT_CONTENT_TYPE); - } - conn.setDoOutput(true); - conn.getOutputStream().write(content); - } - - /** - * Add an HTTP Header to the Request - * - * @param key the header name - * @param value the header value - */ - public void addHeader(String key, String value) - { - this.headers.put(key, value); - } - - /** - * Add a body Parameter (for POST/ PUT Requests) - * - * @param key the parameter name - * @param value the parameter value - */ - public void addBodyParameter(String key, String value) - { - this.bodyParams.add(key, value); - } - - /** - * Add a QueryString parameter - * - * @param key the parameter name - * @param value the parameter value - */ - public void addQuerystringParameter(String key, String value) - { - this.querystringParams.add(key, value); - } - - /** - * Add body payload. - * - * This method is used when the HTTP body is not a form-url-encoded string, - * but another thing. Like for example XML. - * - * Note: The contents are not part of the OAuth signature - * - * @param payload the body of the request - */ - public void addPayload(String payload) - { - this.payload = payload; - } - - /** - * Overloaded version for byte arrays - * - * @param payload - */ - public void addPayload(byte[] payload) - { - this.bytePayload = payload; - } - - /** - * Get a {@link ParameterList} with the query string parameters. - * - * @return a {@link ParameterList} containing the query string parameters. - * @throws OAuthException if the request URL is not valid. - */ - public ParameterList getQueryStringParams() - { - try - { - ParameterList result = new ParameterList(); - String queryString = new URL(url).getQuery(); - result.addQuerystring(queryString); - result.addAll(querystringParams); - return result; - } - catch (MalformedURLException mue) - { - throw new OAuthException("Malformed URL", mue); - } - } - - /** - * Obtains a {@link ParameterList} of the body parameters. - * - * @return a {@link ParameterList}containing the body parameters. - */ - public ParameterList getBodyParams() - { - return bodyParams; - } - - /** - * Obtains the URL of the HTTP Request. - * - * @return the original URL of the HTTP Request - */ - public String getUrl() - { - return url; - } - - /** - * Returns the URL without the port and the query string part. - * - * @return the OAuth-sanitized URL - */ - public String getSanitizedUrl() - { - return url.replaceAll("\\?.*", "").replace("\\:\\d{4}", ""); - } - - /** - * Returns the body of the request - * - * @return form encoded string - * @throws OAuthException if the charset chosen is not supported - */ - public String getBodyContents() - { - try - { - return new String(getByteBodyContents(),getCharset()); - } - catch(UnsupportedEncodingException uee) - { - throw new OAuthException("Unsupported Charset: "+charset, uee); - } - } - - byte[] getByteBodyContents() - { - if (bytePayload != null) return bytePayload; - String body = (payload != null) ? payload : bodyParams.asFormUrlEncodedString(); - try - { - return body.getBytes(getCharset()); - } - catch(UnsupportedEncodingException uee) - { - throw new OAuthException("Unsupported Charset: "+getCharset(), uee); - } - } - - /** - * Returns the HTTP Verb - * - * @return the verb - */ - public Verb getVerb() - { - return verb; - } - - /** - * Returns the connection headers as a {@link Map} - * - * @return map of headers - */ - public Map getHeaders() - { - return headers; - } - - /** - * Returns the connection charset. Defaults to {@link Charset} defaultCharset if not set - * - * @return charset - */ - public String getCharset() - { - return charset == null ? Charset.defaultCharset().name() : charset; - } - - /** - * Sets the connect timeout for the underlying {@link HttpURLConnection} - * - * @param duration duration of the timeout - * - * @param unit unit of time (milliseconds, seconds, etc) - */ - public void setConnectTimeout(int duration, TimeUnit unit) - { - this.connectTimeout = unit.toMillis(duration); - } - - /** - * Sets the read timeout for the underlying {@link HttpURLConnection} - * - * @param duration duration of the timeout - * - * @param unit unit of time (milliseconds, seconds, etc) - */ - public void setReadTimeout(int duration, TimeUnit unit) - { - this.readTimeout = unit.toMillis(duration); - } - - /** - * Set the charset of the body of the request - * - * @param charsetName name of the charset of the request - */ - public void setCharset(String charsetName) - { - this.charset = charsetName; - } - - /** - * Sets whether the underlying Http Connection is persistent or not. - * - * @see http://download.oracle.com/javase/1.5.0/docs/guide/net/http-keepalive.html - * @param connectionKeepAlive - */ - public void setConnectionKeepAlive(boolean connectionKeepAlive) - { - this.connectionKeepAlive = connectionKeepAlive; - } - - /* - * We need this in order to stub the connection object for test cases - */ - void setConnection(HttpURLConnection connection) - { - this.connection = connection; - } - - @Override - public String toString() - { - return String.format("@Request(%s %s)", getVerb(), getUrl()); - } -} diff --git a/src/main/java/org/scribe/model/RequestTuner.java b/src/main/java/org/scribe/model/RequestTuner.java deleted file mode 100644 index 34ea1eb45..000000000 --- a/src/main/java/org/scribe/model/RequestTuner.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.scribe.model; - -public abstract class RequestTuner -{ - public abstract void tune(Request request); -} \ No newline at end of file diff --git a/src/main/java/org/scribe/model/Response.java b/src/main/java/org/scribe/model/Response.java deleted file mode 100644 index 9835a05a6..000000000 --- a/src/main/java/org/scribe/model/Response.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.scribe.model; - -import java.io.*; -import java.net.*; -import java.util.*; - -import org.scribe.exceptions.*; -import org.scribe.utils.*; - -/** - * Represents an HTTP Response. - * - * @author Pablo Fernandez - */ -public class Response -{ - private static final String EMPTY = ""; - - private int code; - private String body; - private InputStream stream; - private Map headers; - - Response(HttpURLConnection connection) throws IOException - { - try - { - connection.connect(); - code = connection.getResponseCode(); - headers = parseHeaders(connection); - stream = isSuccessful() ? connection.getInputStream() : connection.getErrorStream(); - } - catch (UnknownHostException e) - { - throw new OAuthException("The IP address of a host could not be determined.", e); - } - } - - private String parseBodyContents() - { - body = StreamUtils.getStreamContents(getStream()); - return body; - } - - private Map parseHeaders(HttpURLConnection conn) - { - Map headers = new HashMap(); - for (String key : conn.getHeaderFields().keySet()) - { - headers.put(key, conn.getHeaderFields().get(key).get(0)); - } - return headers; - } - - public boolean isSuccessful() - { - return getCode() >= 200 && getCode() < 400; - } - - /** - * Obtains the HTTP Response body - * - * @return response body - */ - public String getBody() - { - return body != null ? body : parseBodyContents(); - } - - /** - * Obtains the meaningful stream of the HttpUrlConnection, either inputStream - * or errorInputStream, depending on the status code - * - * @return input stream / error stream - */ - public InputStream getStream() - { - return stream; - } - - /** - * Obtains the HTTP status code - * - * @return the status code - */ - public int getCode() - { - return code; - } - - /** - * Obtains a {@link Map} containing the HTTP Response Headers - * - * @return headers - */ - public Map getHeaders() - { - return headers; - } - - /** - * Obtains a single HTTP Header value, or null if undefined - * - * @param name the header name. - * - * @return header value or null. - */ - public String getHeader(String name) - { - return headers.get(name); - } - -} \ No newline at end of file diff --git a/src/main/java/org/scribe/model/SignatureType.java b/src/main/java/org/scribe/model/SignatureType.java deleted file mode 100644 index 3440a361f..000000000 --- a/src/main/java/org/scribe/model/SignatureType.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.scribe.model; - -public enum SignatureType -{ - Header, - QueryString -} diff --git a/src/main/java/org/scribe/model/Token.java b/src/main/java/org/scribe/model/Token.java deleted file mode 100644 index 4d8c0eeb5..000000000 --- a/src/main/java/org/scribe/model/Token.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.scribe.model; - -import java.io.*; -import org.scribe.utils.*; - -/** - * Represents an OAuth token (either request or access token) and its secret - * - * @author Pablo Fernandez - */ -public class Token implements Serializable -{ - private static final long serialVersionUID = 715000866082812683L; - - private final String token; - private final String secret; - private final String rawResponse; - - /** - * Default constructor - * - * @param token token value. Can't be null. - * @param secret token secret. Can't be null. - */ - public Token(String token, String secret) - { - this(token, secret, null); - } - - public Token(String token, String secret, String rawResponse) - { - Preconditions.checkNotNull(token, "Token can't be null"); - Preconditions.checkNotNull(secret, "Secret can't be null"); - - this.token = token; - this.secret = secret; - this.rawResponse = rawResponse; - } - - public String getToken() - { - return token; - } - - public String getSecret() - { - return secret; - } - - public String getRawResponse() - { - if (rawResponse == null) - { - throw new IllegalStateException("This token object was not constructed by scribe and does not have a rawResponse"); - } - return rawResponse; - } - - @Override - public String toString() - { - return String.format("Token[%s , %s]", token, secret); - } - - /** - * Returns true if the token is empty (token = "", secret = "") - */ - public boolean isEmpty() - { - return "".equals(this.token) && "".equals(this.secret); - } - - /** - * Factory method that returns an empty token (token = "", secret = ""). - * - * Useful for two legged OAuth. - */ - public static Token empty() - { - return new Token("", ""); - } - - @Override - public boolean equals(Object o) - { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Token that = (Token) o; - return token.equals(that.token) && secret.equals(that.secret); - } - - @Override - public int hashCode() - { - return 31 * token.hashCode() + secret.hashCode(); - } -} diff --git a/src/main/java/org/scribe/model/Verb.java b/src/main/java/org/scribe/model/Verb.java deleted file mode 100644 index 0c22f6690..000000000 --- a/src/main/java/org/scribe/model/Verb.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.scribe.model; - -/** - * An enumeration containing the most common HTTP Verbs. - * - * @author Pablo Fernandez - */ -public enum Verb -{ - GET, POST, PUT, DELETE, HEAD, OPTIONS, TRACE, PATCH -} diff --git a/src/main/java/org/scribe/model/Verifier.java b/src/main/java/org/scribe/model/Verifier.java deleted file mode 100644 index 45f0e4ea3..000000000 --- a/src/main/java/org/scribe/model/Verifier.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.scribe.model; - -import org.scribe.utils.*; - -/** - * Represents an OAuth verifier code. - * - * @author Pablo Fernandez - */ -public class Verifier -{ - - private final String value; - - /** - * Default constructor. - * - * @param value verifier value - */ - public Verifier(String value) - { - Preconditions.checkNotNull(value, "Must provide a valid string as verifier"); - this.value = value; - } - - public String getValue() - { - return value; - } -} diff --git a/src/main/java/org/scribe/oauth/OAuth10aServiceImpl.java b/src/main/java/org/scribe/oauth/OAuth10aServiceImpl.java deleted file mode 100644 index ff5b5d642..000000000 --- a/src/main/java/org/scribe/oauth/OAuth10aServiceImpl.java +++ /dev/null @@ -1,188 +0,0 @@ -package org.scribe.oauth; - -import java.util.*; - -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.utils.*; -import java.util.concurrent.TimeUnit; - -/** - * OAuth 1.0a implementation of {@link OAuthService} - * - * @author Pablo Fernandez - */ -public class OAuth10aServiceImpl implements OAuthService -{ - private static final String VERSION = "1.0"; - - private OAuthConfig config; - private DefaultApi10a api; - - /** - * Default constructor - * - * @param api OAuth1.0a api information - * @param config OAuth 1.0a configuration param object - */ - public OAuth10aServiceImpl(DefaultApi10a api, OAuthConfig config) - { - this.api = api; - this.config = config; - } - - /** - * {@inheritDoc} - */ - public Token getRequestToken(int timeout, TimeUnit unit) - { - return getRequestToken(new TimeoutTuner(timeout, unit)); - } - - public Token getRequestToken() - { - return getRequestToken(2, TimeUnit.SECONDS); - } - - public Token getRequestToken(RequestTuner tuner) - { - config.log("obtaining request token from " + api.getRequestTokenEndpoint()); - OAuthRequest request = new OAuthRequest(api.getRequestTokenVerb(), api.getRequestTokenEndpoint()); - - config.log("setting oauth_callback to " + config.getCallback()); - request.addOAuthParameter(OAuthConstants.CALLBACK, config.getCallback()); - addOAuthParams(request, OAuthConstants.EMPTY_TOKEN); - appendSignature(request); - - config.log("sending request..."); - Response response = request.send(tuner); - String body = response.getBody(); - - config.log("response status code: " + response.getCode()); - config.log("response body: " + body); - return api.getRequestTokenExtractor().extract(body); - } - - private void addOAuthParams(OAuthRequest request, Token token) - { - request.addOAuthParameter(OAuthConstants.TIMESTAMP, api.getTimestampService().getTimestampInSeconds()); - request.addOAuthParameter(OAuthConstants.NONCE, api.getTimestampService().getNonce()); - request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, config.getApiKey()); - request.addOAuthParameter(OAuthConstants.SIGN_METHOD, api.getSignatureService().getSignatureMethod()); - request.addOAuthParameter(OAuthConstants.VERSION, getVersion()); - if(config.hasScope()) request.addOAuthParameter(OAuthConstants.SCOPE, config.getScope()); - request.addOAuthParameter(OAuthConstants.SIGNATURE, getSignature(request, token)); - - config.log("appended additional OAuth parameters: " + MapUtils.toString(request.getOauthParameters())); - } - - /** - * {@inheritDoc} - */ - public Token getAccessToken(Token requestToken, Verifier verifier, int timeout, TimeUnit unit) - { - return getAccessToken(requestToken, verifier, new TimeoutTuner(timeout, unit)); - } - - public Token getAccessToken(Token requestToken, Verifier verifier) - { - return getAccessToken(requestToken, verifier, 2, TimeUnit.SECONDS); - } - - public Token getAccessToken(Token requestToken, Verifier verifier, RequestTuner tuner) - { - config.log("obtaining access token from " + api.getAccessTokenEndpoint()); - OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint()); - request.addOAuthParameter(OAuthConstants.TOKEN, requestToken.getToken()); - request.addOAuthParameter(OAuthConstants.VERIFIER, verifier.getValue()); - - config.log("setting token to: " + requestToken + " and verifier to: " + verifier); - addOAuthParams(request, requestToken); - appendSignature(request); - Response response = request.send(tuner); - return api.getAccessTokenExtractor().extract(response.getBody()); - } - - /** - * {@inheritDoc} - */ - public void signRequest(Token token, OAuthRequest request) - { - config.log("signing request: " + request.getCompleteUrl()); - - // Do not append the token if empty. This is for two legged OAuth calls. - if (!token.isEmpty()) - { - request.addOAuthParameter(OAuthConstants.TOKEN, token.getToken()); - } - config.log("setting token to: " + token); - addOAuthParams(request, token); - appendSignature(request); - } - - /** - * {@inheritDoc} - */ - public String getVersion() - { - return VERSION; - } - - /** - * {@inheritDoc} - */ - public String getAuthorizationUrl(Token requestToken) - { - return api.getAuthorizationUrl(requestToken); - } - - private String getSignature(OAuthRequest request, Token token) - { - config.log("generating signature..."); - String baseString = api.getBaseStringExtractor().extract(request); - String signature = api.getSignatureService().getSignature(baseString, config.getApiSecret(), token.getSecret()); - - config.log("base string is: " + baseString); - config.log("signature is: " + signature); - return signature; - } - - private void appendSignature(OAuthRequest request) - { - switch (config.getSignatureType()) - { - case Header: - config.log("using Http Header signature"); - - String oauthHeader = api.getHeaderExtractor().extract(request); - request.addHeader(OAuthConstants.HEADER, oauthHeader); - break; - case QueryString: - config.log("using Querystring signature"); - - for (Map.Entry entry : request.getOauthParameters().entrySet()) - { - request.addQuerystringParameter(entry.getKey(), entry.getValue()); - } - break; - } - } - - private static class TimeoutTuner extends RequestTuner - { - private final int duration; - private final TimeUnit unit; - - public TimeoutTuner(int duration, TimeUnit unit) - { - this.duration = duration; - this.unit = unit; - } - - @Override - public void tune(Request request) - { - request.setReadTimeout(duration, unit); - } - } -} diff --git a/src/main/java/org/scribe/oauth/OAuth20ServiceImpl.java b/src/main/java/org/scribe/oauth/OAuth20ServiceImpl.java deleted file mode 100644 index 6262c3700..000000000 --- a/src/main/java/org/scribe/oauth/OAuth20ServiceImpl.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.scribe.oauth; - -import org.scribe.builder.api.*; -import org.scribe.model.*; - -public class OAuth20ServiceImpl implements OAuthService -{ - private static final String VERSION = "2.0"; - - private final DefaultApi20 api; - private final OAuthConfig config; - - /** - * Default constructor - * - * @param api OAuth2.0 api information - * @param config OAuth 2.0 configuration param object - */ - public OAuth20ServiceImpl(DefaultApi20 api, OAuthConfig config) - { - this.api = api; - this.config = config; - } - - /** - * {@inheritDoc} - */ - public Token getAccessToken(Token requestToken, Verifier verifier) - { - OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint()); - request.addQuerystringParameter(OAuthConstants.CLIENT_ID, config.getApiKey()); - request.addQuerystringParameter(OAuthConstants.CLIENT_SECRET, config.getApiSecret()); - request.addQuerystringParameter(OAuthConstants.CODE, verifier.getValue()); - request.addQuerystringParameter(OAuthConstants.REDIRECT_URI, config.getCallback()); - if(config.hasScope()) request.addQuerystringParameter(OAuthConstants.SCOPE, config.getScope()); - Response response = request.send(); - return api.getAccessTokenExtractor().extract(response.getBody()); - } - - /** - * {@inheritDoc} - */ - public Token getRequestToken() - { - throw new UnsupportedOperationException("Unsupported operation, please use 'getAuthorizationUrl' and redirect your users there"); - } - - /** - * {@inheritDoc} - */ - public String getVersion() - { - return VERSION; - } - - /** - * {@inheritDoc} - */ - public void signRequest(Token accessToken, OAuthRequest request) - { - request.addQuerystringParameter(OAuthConstants.ACCESS_TOKEN, accessToken.getToken()); - } - - /** - * {@inheritDoc} - */ - public String getAuthorizationUrl(Token requestToken) - { - return api.getAuthorizationUrl(config); - } - -} diff --git a/src/main/java/org/scribe/oauth/OAuthService.java b/src/main/java/org/scribe/oauth/OAuthService.java deleted file mode 100644 index 0c9c57e9b..000000000 --- a/src/main/java/org/scribe/oauth/OAuthService.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.scribe.oauth; - -import org.scribe.model.*; - -/** - * The main Scribe object. - * - * A facade responsible for the retrieval of request and access tokens and for the signing of HTTP requests. - * - * @author Pablo Fernandez - */ -public interface OAuthService -{ - /** - * Retrieve the request token. - * - * @return request token - */ - public Token getRequestToken(); - - /** - * Retrieve the access token - * - * @param requestToken request token (obtained previously) - * @param verifier verifier code - * @return access token - */ - public Token getAccessToken(Token requestToken, Verifier verifier); - - /** - * Signs am OAuth request - * - * @param accessToken access token (obtained previously) - * @param request request to sign - */ - public void signRequest(Token accessToken, OAuthRequest request); - - /** - * Returns the OAuth version of the service. - * - * @return oauth version as string - */ - public String getVersion(); - - /** - * Returns the URL where you should redirect your users to authenticate - * your application. - * - * @param requestToken the request token you need to authorize - * @return the URL where you should redirect your users - */ - public String getAuthorizationUrl(Token requestToken); -} diff --git a/src/main/java/org/scribe/services/HMACSha1SignatureService.java b/src/main/java/org/scribe/services/HMACSha1SignatureService.java deleted file mode 100644 index cadda6812..000000000 --- a/src/main/java/org/scribe/services/HMACSha1SignatureService.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.scribe.services; - -import javax.crypto.*; -import javax.crypto.spec.*; - -import org.apache.commons.codec.binary.*; -import org.scribe.exceptions.*; -import org.scribe.utils.*; - -/** - * HMAC-SHA1 implementation of {@SignatureService} - * - * @author Pablo Fernandez - * - */ -public class HMACSha1SignatureService implements SignatureService -{ - private static final String EMPTY_STRING = ""; - private static final String CARRIAGE_RETURN = "\r\n"; - private static final String UTF8 = "UTF-8"; - private static final String HMAC_SHA1 = "HmacSHA1"; - private static final String METHOD = "HMAC-SHA1"; - - /** - * {@inheritDoc} - */ - public String getSignature(String baseString, String apiSecret, String tokenSecret) - { - try - { - Preconditions.checkEmptyString(baseString, "Base string cant be null or empty string"); - Preconditions.checkEmptyString(apiSecret, "Api secret cant be null or empty string"); - return doSign(baseString, OAuthEncoder.encode(apiSecret) + '&' + OAuthEncoder.encode(tokenSecret)); - } - catch (Exception e) - { - throw new OAuthSignatureException(baseString, e); - } - } - - private String doSign(String toSign, String keyString) throws Exception - { - SecretKeySpec key = new SecretKeySpec((keyString).getBytes(UTF8), HMAC_SHA1); - Mac mac = Mac.getInstance(HMAC_SHA1); - mac.init(key); - byte[] bytes = mac.doFinal(toSign.getBytes(UTF8)); - return new String(Base64.encodeBase64(bytes)).replace(CARRIAGE_RETURN, EMPTY_STRING); - } - - /** - * {@inheritDoc} - */ - public String getSignatureMethod() - { - return METHOD; - } -} diff --git a/src/main/java/org/scribe/services/PlaintextSignatureService.java b/src/main/java/org/scribe/services/PlaintextSignatureService.java deleted file mode 100644 index 03306e8e3..000000000 --- a/src/main/java/org/scribe/services/PlaintextSignatureService.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.scribe.services; - -import org.scribe.exceptions.*; -import org.scribe.utils.*; - -/** - * plaintext implementation of {@SignatureService} - * - * @author Pablo Fernandez - * - */ -public class PlaintextSignatureService implements SignatureService -{ - private static final String METHOD = "PLAINTEXT"; - - /** - * {@inheritDoc} - */ - public String getSignature(String baseString, String apiSecret, String tokenSecret) - { - try - { - Preconditions.checkEmptyString(apiSecret, "Api secret cant be null or empty string"); - return OAuthEncoder.encode(apiSecret) + '&' + OAuthEncoder.encode(tokenSecret); - } - catch (Exception e) - { - throw new OAuthSignatureException(baseString, e); - } - } - - /** - * {@inheritDoc} - */ - public String getSignatureMethod() - { - return METHOD; - } -} - diff --git a/src/main/java/org/scribe/services/RSASha1SignatureService.java b/src/main/java/org/scribe/services/RSASha1SignatureService.java deleted file mode 100644 index 3b996f5c6..000000000 --- a/src/main/java/org/scribe/services/RSASha1SignatureService.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.scribe.services; - -import org.apache.commons.codec.binary.*; -import org.scribe.exceptions.*; -import java.security.*; - -/** - * A signature service that uses the RSA-SHA1 algorithm. - */ -public class RSASha1SignatureService implements SignatureService -{ - private static final String METHOD = "RSA-SHA1"; - private static final String RSA_SHA1 = "SHA1withRSA"; - - private PrivateKey privateKey; - - public RSASha1SignatureService(PrivateKey privateKey) - { - this.privateKey = privateKey; - } - - /** - * {@inheritDoc} - */ - public String getSignature(String baseString, String apiSecret, String tokenSecret) - { - try - { - Signature signature = Signature.getInstance(RSA_SHA1); - signature.initSign(privateKey); - signature.update(baseString.getBytes()); - return new String(Base64.encodeBase64(signature.sign(), false)); - } - catch (Exception e) - { - throw new OAuthSignatureException(baseString, e); - } - } - - /** - * {@inheritDoc} - */ - public String getSignatureMethod() - { - return METHOD; - } -} \ No newline at end of file diff --git a/src/main/java/org/scribe/services/SignatureService.java b/src/main/java/org/scribe/services/SignatureService.java deleted file mode 100644 index 229c2f60e..000000000 --- a/src/main/java/org/scribe/services/SignatureService.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.scribe.services; - -/** - * Signs a base string, returning the OAuth signature - * - * @author Pablo Fernandez - * - */ -public interface SignatureService -{ - /** - * Returns the signature - * - * @param baseString url-encoded string to sign - * @param apiSecret api secret for your app - * @param tokenSecret token secret (empty string for the request token step) - * - * @return signature - */ - public String getSignature(String baseString, String apiSecret, String tokenSecret); - - /** - * Returns the signature method/algorithm - * - * @return - */ - public String getSignatureMethod(); -} diff --git a/src/main/java/org/scribe/services/TimestampService.java b/src/main/java/org/scribe/services/TimestampService.java deleted file mode 100644 index 221a226b4..000000000 --- a/src/main/java/org/scribe/services/TimestampService.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.scribe.services; - -/** - * Unix epoch timestamp generator. - * - * This class is useful for stubbing in tests. - * - * @author Pablo Fernandez - */ -public interface TimestampService -{ - /** - * Returns the unix epoch timestamp in seconds - * - * @return timestamp - */ - public String getTimestampInSeconds(); - - /** - * Returns a nonce (unique value for each request) - * - * @return nonce - */ - public String getNonce(); -} diff --git a/src/main/java/org/scribe/services/TimestampServiceImpl.java b/src/main/java/org/scribe/services/TimestampServiceImpl.java deleted file mode 100644 index 4aa27e026..000000000 --- a/src/main/java/org/scribe/services/TimestampServiceImpl.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.scribe.services; - -import java.util.*; - -/** - * Implementation of {@link TimestampService} using plain java classes. - * - * @author Pablo Fernandez - */ -public class TimestampServiceImpl implements TimestampService -{ - private Timer timer; - - /** - * Default constructor. - */ - public TimestampServiceImpl() - { - timer = new Timer(); - } - - /** - * {@inheritDoc} - */ - public String getNonce() - { - Long ts = getTs(); - return String.valueOf(ts + timer.getRandomInteger()); - } - - /** - * {@inheritDoc} - */ - public String getTimestampInSeconds() - { - return String.valueOf(getTs()); - } - - private Long getTs() - { - return timer.getMilis() / 1000; - } - - void setTimer(Timer timer) - { - this.timer = timer; - } - - /** - * Inner class that uses {@link System} for generating the timestamps. - * - * @author Pablo Fernandez - */ - static class Timer - { - Long getMilis() - { - return System.currentTimeMillis(); - } - - Integer getRandomInteger() - { - return new Random().nextInt(); - } - } - -} diff --git a/src/main/java/org/scribe/utils/MapUtils.java b/src/main/java/org/scribe/utils/MapUtils.java deleted file mode 100644 index 9e461b803..000000000 --- a/src/main/java/org/scribe/utils/MapUtils.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.scribe.utils; - -import java.util.Map; - -/** - * @author: Pablo Fernandez - */ -public class MapUtils -{ - public static String toString(Map map) - { - if (map == null) return ""; - if (map.isEmpty()) return "{}"; - - StringBuilder result = new StringBuilder(); - for(Map.Entry entry : map.entrySet()) - { - result.append(String.format(", %s -> %s ", entry.getKey().toString(), entry.getValue().toString())); - } - return "{" + result.substring(1) + "}"; - } -} diff --git a/src/main/java/org/scribe/utils/OAuthEncoder.java b/src/main/java/org/scribe/utils/OAuthEncoder.java deleted file mode 100644 index 10beabd4f..000000000 --- a/src/main/java/org/scribe/utils/OAuthEncoder.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.scribe.utils; - -import java.io.*; -import java.net.*; -import java.util.*; -import java.util.regex.*; -import org.scribe.exceptions.*; - -/** - * @author: Pablo Fernandez - */ -public class OAuthEncoder -{ - private static String CHARSET = "UTF-8"; - private static final Map ENCODING_RULES; - - static - { - Map rules = new HashMap(); - rules.put("*", "%2A"); - rules.put("+", "%20"); - rules.put("%7E", "~"); - ENCODING_RULES = Collections.unmodifiableMap(rules); - } - - public static String encode(String plain) - { - Preconditions.checkNotNull(plain, "Cannot encode null object"); - String encoded = ""; - try - { - encoded = URLEncoder.encode(plain, CHARSET); - } - catch (UnsupportedEncodingException uee) - { - throw new OAuthException("Charset not found while encoding string: " + CHARSET, uee); - } - for(Map.Entry rule : ENCODING_RULES.entrySet()) - { - encoded = applyRule(encoded, rule.getKey(), rule.getValue()); - } - return encoded; - } - - private static String applyRule(String encoded, String toReplace, String replacement) - { - return encoded.replaceAll(Pattern.quote(toReplace), replacement); - } - - public static String decode(String encoded) - { - Preconditions.checkNotNull(encoded, "Cannot decode null object"); - try - { - return URLDecoder.decode(encoded, CHARSET); - } - catch(UnsupportedEncodingException uee) - { - throw new OAuthException("Charset not found while decoding string: " + CHARSET, uee); - } - } -} diff --git a/src/main/java/org/scribe/utils/Preconditions.java b/src/main/java/org/scribe/utils/Preconditions.java deleted file mode 100644 index 0ac134e3c..000000000 --- a/src/main/java/org/scribe/utils/Preconditions.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.scribe.utils; - -import java.util.regex.Pattern; - -import org.scribe.model.OAuthConstants; - -/** - * Utils for checking preconditions and invariants - * - * @author Pablo Fernandez - */ -public class Preconditions -{ - private static final String DEFAULT_MESSAGE = "Received an invalid parameter"; - - // scheme = alpha *( alpha | digit | "+" | "-" | "." ) - private static final Pattern URL_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9+.-]*://\\S+"); - - /** - * Checks that an object is not null. - * - * @param object any object - * @param errorMsg error message - * - * @throws IllegalArgumentException if the object is null - */ - public static void checkNotNull(Object object, String errorMsg) - { - check(object != null, errorMsg); - } - - /** - * Checks that a string is not null or empty - * - * @param string any string - * @param errorMsg error message - * - * @throws IllegalArgumentException if the string is null or empty - */ - public static void checkEmptyString(String string, String errorMsg) - { - check(string != null && !string.trim().equals(""), errorMsg); - } - - /** - * Checks that a URL is valid - * - * @param url any string - * @param errorMsg error message - */ - public static void checkValidUrl(String url, String errorMsg) - { - checkEmptyString(url, errorMsg); - check(isUrl(url), errorMsg); - } - - /** - * Checks that a URL is a valid OAuth callback - * - * @param url any string - * @param errorMsg error message - */ - public static void checkValidOAuthCallback(String url, String errorMsg) - { - checkEmptyString(url, errorMsg); - if(url.toLowerCase().compareToIgnoreCase(OAuthConstants.OUT_OF_BAND) != 0) - { - check(isUrl(url), errorMsg); - } - } - - private static boolean isUrl(String url) - { - return URL_PATTERN.matcher(url).matches(); - } - - private static void check(boolean requirements, String error) - { - String message = (error == null || error.trim().length() <= 0) ? DEFAULT_MESSAGE : error; - if (!requirements) - { - throw new IllegalArgumentException(message); - } - } - -} diff --git a/src/main/java/org/scribe/utils/StreamUtils.java b/src/main/java/org/scribe/utils/StreamUtils.java deleted file mode 100644 index 0799b9c1e..000000000 --- a/src/main/java/org/scribe/utils/StreamUtils.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.scribe.utils; - -import java.io.*; - -/** - * Utils to deal with Streams. - * - * @author Pablo Fernandez - */ -public class StreamUtils -{ - /** - * Returns the stream contents as an UTF-8 encoded string - * - * @param is input stream - * @return string contents - */ - public static String getStreamContents(InputStream is) - { - Preconditions.checkNotNull(is, "Cannot get String from a null object"); - try - { - final char[] buffer = new char[0x10000]; - StringBuilder out = new StringBuilder(); - Reader in = new InputStreamReader(is, "UTF-8"); - int read; - do - { - read = in.read(buffer, 0, buffer.length); - if (read > 0) - { - out.append(buffer, 0, read); - } - } while (read >= 0); - in.close(); - return out.toString(); - } catch (IOException ioe) - { - throw new IllegalStateException("Error while reading response body", ioe); - } - } -} diff --git a/src/test/java/org/scribe/builder/ServiceBuilderTest.java b/src/test/java/org/scribe/builder/ServiceBuilderTest.java deleted file mode 100644 index 8112d79b3..000000000 --- a/src/test/java/org/scribe/builder/ServiceBuilderTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.scribe.builder; - -import static org.junit.Assert.*; - -import org.junit.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class ServiceBuilderTest -{ - private ServiceBuilder builder; - - @Before - public void setup() - { - builder = new ServiceBuilder(); - } - - @Test - public void shouldReturnConfigDefaultValues() - { - builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").build(); - assertEquals(ApiMock.config.getApiKey(), "key"); - assertEquals(ApiMock.config.getApiSecret(), "secret"); - assertEquals(ApiMock.config.getCallback(), OAuthConstants.OUT_OF_BAND); - assertEquals(ApiMock.config.getSignatureType(), SignatureType.Header); - } - - @Test - public void shouldAcceptValidCallbackUrl() - { - builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").callback("http://example.com").build(); - assertEquals(ApiMock.config.getApiKey(), "key"); - assertEquals(ApiMock.config.getApiSecret(), "secret"); - assertEquals(ApiMock.config.getCallback(), "http://example.com"); - } - - @Test - public void shouldAcceptASignatureType() - { - builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").signatureType(SignatureType.QueryString).build(); - assertEquals(ApiMock.config.getApiKey(), "key"); - assertEquals(ApiMock.config.getApiSecret(), "secret"); - assertEquals(ApiMock.config.getSignatureType(), SignatureType.QueryString); - } - - @Test(expected=IllegalArgumentException.class) - public void shouldNotAcceptNullAsCallback() - { - builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").callback(null).build(); - } - - @Test - public void shouldAcceptAnScope() - { - builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").scope("rss-api").build(); - assertEquals(ApiMock.config.getApiKey(), "key"); - assertEquals(ApiMock.config.getApiSecret(), "secret"); - assertEquals(ApiMock.config.getScope(), "rss-api"); - } - - public static class ApiMock implements Api - { - public static OAuthConfig config; - - public OAuthService createService(OAuthConfig config) - { - ApiMock.config = config; - return null; - } - } -} diff --git a/src/test/java/org/scribe/examples/DiggExample.java b/src/test/java/org/scribe/examples/DiggExample.java deleted file mode 100644 index 63fea8b6a..000000000 --- a/src/test/java/org/scribe/examples/DiggExample.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.scribe.examples; - -import java.util.*; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class DiggExample -{ - private static final String NETWORK_NAME = "Digg"; - private static final String PROTECTED_RESOURCE_URL = "http://services.digg.com/2.0/comment.digg"; - - public static void main(String[] args) - { - // Replace these with your own api key and secret - String apiKey = "myKey"; - String apiSecret = "mySecret"; - OAuthService service = new ServiceBuilder().provider(DiggApi.class).apiKey(apiKey).apiSecret(apiSecret).build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); - System.out.println(); - - // Obtain the Request Token - System.out.println("Fetching the Request Token..."); - Token requestToken = service.getRequestToken(); - System.out.println("Got the Request Token!"); - System.out.println(); - - // Obtain the Authorization URL - System.out.println("Fetching the Authorization URL..."); - String authorizationUrl = service.getAuthorizationUrl(requestToken); - System.out.println("Got the Authorization URL!"); - System.out.println("Now go and authorize Scribe here:"); - System.out.println(authorizationUrl); - System.out.println("And paste the authorization code here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.POST, PROTECTED_RESOURCE_URL); - request.addBodyParameter("comment_id", "20100729223726:4fef610331ee46a3b5cbd740bf71313e"); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getCode()); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - - } -} \ No newline at end of file diff --git a/src/test/java/org/scribe/examples/FacebookExample.java b/src/test/java/org/scribe/examples/FacebookExample.java deleted file mode 100644 index d5dc3cb50..000000000 --- a/src/test/java/org/scribe/examples/FacebookExample.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.scribe.examples; - -import java.util.*; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class FacebookExample -{ - private static final String NETWORK_NAME = "Facebook"; - private static final String PROTECTED_RESOURCE_URL = "https://graph.facebook.com/me"; - private static final Token EMPTY_TOKEN = null; - - public static void main(String[] args) - { - // Replace these with your own api key and secret - String apiKey = "your_app_id"; - String apiSecret = "your_api_secret"; - OAuthService service = new ServiceBuilder() - .provider(FacebookApi.class) - .apiKey(apiKey) - .apiSecret(apiSecret) - .callback("http://www.example.com/oauth_callback/") - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); - System.out.println(); - - // Obtain the Authorization URL - System.out.println("Fetching the Authorization URL..."); - String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN); - System.out.println("Got the Authorization URL!"); - System.out.println("Now go and authorize Scribe here:"); - System.out.println(authorizationUrl); - System.out.println("And paste the authorization code here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getCode()); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - - } -} \ No newline at end of file diff --git a/src/test/java/org/scribe/examples/FlickrExample.java b/src/test/java/org/scribe/examples/FlickrExample.java deleted file mode 100644 index ac38ad32f..000000000 --- a/src/test/java/org/scribe/examples/FlickrExample.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.scribe.examples; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -import java.util.*; - -public class FlickrExample -{ - private static final String PROTECTED_RESOURCE_URL = "http://api.flickr.com/services/rest/"; - - public static void main(String[] args) - { - // Replace these with your own api key and secret - String apiKey = "your_app_id"; - String apiSecret = "your_api_secret"; - OAuthService service = new ServiceBuilder().provider(FlickrApi.class).apiKey(apiKey).apiSecret(apiSecret).build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== Flickr's OAuth Workflow ==="); - System.out.println(); - - // Obtain the Request Token - System.out.println("Fetching the Request Token..."); - Token requestToken = service.getRequestToken(); - System.out.println("Got the Request Token!"); - System.out.println(); - - System.out.println("Now go and authorize Scribe here:"); - String authorizationUrl = service.getAuthorizationUrl(requestToken); - System.out.println(authorizationUrl + "&perms=read"); - System.out.println("And paste the verifier here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - request.addQuerystringParameter("method", "flickr.test.login"); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - } -} diff --git a/src/test/java/org/scribe/examples/Foursquare2Example.java b/src/test/java/org/scribe/examples/Foursquare2Example.java deleted file mode 100644 index 35495a895..000000000 --- a/src/test/java/org/scribe/examples/Foursquare2Example.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.scribe.examples; - -import java.util.*; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class Foursquare2Example -{ - private static final String PROTECTED_RESOURCE_URL = "https://api.foursquare.com/v2/users/self/friends?oauth_token="; - private static final Token EMPTY_TOKEN = null; - - public static void main(String[] args) - { - // Replace these with your own api key and secret - String apiKey = "FEGFXJUFANVVDHVSNUAMUKTTXCP1AJQD53E33XKJ44YP1S4I"; - String apiSecret = "AYWKUL5SWPNC0CTQ202QXRUG2NLZYXMRA34ZSDW4AUYBG2RC"; - OAuthService service = new ServiceBuilder() - .provider(Foursquare2Api.class) - .apiKey(apiKey) - .apiSecret(apiSecret) - .callback("http://localhost:9000/") - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== Foursquare2's OAuth Workflow ==="); - System.out.println(); - - // Obtain the Authorization URL - System.out.println("Fetching the Authorization URL..."); - String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN); - System.out.println("Got the Authorization URL!"); - System.out.println("Now go and authorize Scribe here:"); - System.out.println(authorizationUrl); - System.out.println("And paste the authorization code here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL + accessToken.getToken()); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getCode()); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - - } -} diff --git a/src/test/java/org/scribe/examples/FoursquareExample.java b/src/test/java/org/scribe/examples/FoursquareExample.java deleted file mode 100644 index b227488c7..000000000 --- a/src/test/java/org/scribe/examples/FoursquareExample.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.scribe.examples; - -import java.util.Scanner; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class FoursquareExample -{ - private static final String PROTECTED_RESOURCE_URL = "http://api.foursquare.com/v1/user"; - - public static void main(String[] args) - { - OAuthService service = new ServiceBuilder() - .provider(FoursquareApi.class) - .apiKey("FEGFXJUFANVVDHVSNUAMUKTTXCP1AJQD53E33XKJ44YP1S4I") - .apiSecret("AYWKUL5SWPNC0CTQ202QXRUG2NLZYXMRA34ZSDW4AUYBG2RC") - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== Foursquare's OAuth Workflow ==="); - System.out.println(); - - // Obtain the Request Token - System.out.println("Fetching the Request Token..."); - Token requestToken = service.getRequestToken(); - System.out.println("Got the Request Token!"); - System.out.println(); - - System.out.println("Now go and authorize Scribe here:"); - System.out.println(service.getAuthorizationUrl(requestToken)); - System.out.println("And paste the verifier here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - } - -} \ No newline at end of file diff --git a/src/test/java/org/scribe/examples/FreelancerExample.java b/src/test/java/org/scribe/examples/FreelancerExample.java deleted file mode 100644 index d1d540723..000000000 --- a/src/test/java/org/scribe/examples/FreelancerExample.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.scribe.examples; - -import java.util.*; -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class FreelancerExample -{ - - private static final String NETWORK_NAME = "Freelancer"; - private static final String AUTHORIZE_URL = "http://www.sandbox.freelancer.com/users/api-token/auth.php?oauth_token="; - private static final String PROTECTED_RESOURCE_URL = "http://api.sandbox.freelancer.com/Job/getJobList.json"; - private static final String SCOPE = "http://api.sandbox.freelancer.com"; - - public static void main(String[] args) - { - OAuthService service = new ServiceBuilder() - .provider(FreelancerApi.Sandbox.class) - .signatureType(SignatureType.QueryString) - .apiKey("7f5a168a0bfdbd15b4a9ea2a969661c731cdea56") - .apiSecret("7bb8961b94873802f1c5344f671a518e087f5785") - .scope(SCOPE) - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); - System.out.println(); - - // Obtain the Request Token - System.out.println("Fetching the Request Token..."); - Token requestToken = service.getRequestToken(); - System.out.println("Got the Request Token!"); - System.out.println("(if your curious it looks like this: " + requestToken + " )"); - System.out.println(); - - System.out.println("Now go and authorize Scribe here:"); - System.out.println(AUTHORIZE_URL + requestToken.getToken()); - System.out.println("And paste the verifier here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - request.addHeader("GData-Version", "3.0"); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getCode()); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - } -} diff --git a/src/test/java/org/scribe/examples/GoogleExample.java b/src/test/java/org/scribe/examples/GoogleExample.java deleted file mode 100644 index fef1b43c9..000000000 --- a/src/test/java/org/scribe/examples/GoogleExample.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.scribe.examples; - -import java.util.*; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class GoogleExample -{ - private static final String NETWORK_NAME = "Google"; - private static final String AUTHORIZE_URL = "https://www.google.com/accounts/OAuthAuthorizeToken?oauth_token="; - private static final String PROTECTED_RESOURCE_URL = "https://docs.google.com/feeds/default/private/full/"; - private static final String SCOPE = "https://docs.google.com/feeds/"; - - public static void main(String[] args) - { - OAuthService service = new ServiceBuilder() - .provider(GoogleApi.class) - .apiKey("anonymous") - .apiSecret("anonymous") - .scope(SCOPE) - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); - System.out.println(); - - // Obtain the Request Token - System.out.println("Fetching the Request Token..."); - Token requestToken = service.getRequestToken(); - System.out.println("Got the Request Token!"); - System.out.println("(if your curious it looks like this: " + requestToken + " )"); - System.out.println(); - - System.out.println("Now go and authorize Scribe here:"); - System.out.println(AUTHORIZE_URL + requestToken.getToken()); - System.out.println("And paste the verifier here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - request.addHeader("GData-Version", "3.0"); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getCode()); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - - } -} \ No newline at end of file diff --git a/src/test/java/org/scribe/examples/ImgUrExample.java b/src/test/java/org/scribe/examples/ImgUrExample.java deleted file mode 100644 index 93fe91cb7..000000000 --- a/src/test/java/org/scribe/examples/ImgUrExample.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.scribe.examples; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -import java.util.*; - -public class ImgUrExample -{ - private static final String PROTECTED_RESOURCE_URL = "http://api.imgur.com/2/account.json"; - - public static void main(String[] args) - { - // Replace these with your own api key and secret (you'll need an read/write api key) - String apiKey = "your_app_id"; - String apiSecret = "your_api_secret"; - OAuthService service = new ServiceBuilder().provider(ImgUrApi.class).apiKey(apiKey).apiSecret(apiSecret).build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== ImgUr's OAuth Workflow ==="); - System.out.println(); - - // Obtain the Request Token - System.out.println("Fetching the Request Token..."); - Token requestToken = service.getRequestToken(); - System.out.println("Got the Request Token!"); - System.out.println(); - - System.out.println("Now go and authorize Scribe here:"); - String authorizationUrl = service.getAuthorizationUrl(requestToken); - System.out.println(authorizationUrl); - System.out.println("And paste the verifier here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - } -} diff --git a/src/test/java/org/scribe/examples/Kaixin20Example.java b/src/test/java/org/scribe/examples/Kaixin20Example.java deleted file mode 100644 index b3e9d66ba..000000000 --- a/src/test/java/org/scribe/examples/Kaixin20Example.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.scribe.examples; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; -import java.util.*; - -public class Kaixin20Example -{ - private static final String NETWORK_NAME = "Kaixin"; - private static final String PROTECTED_RESOURCE_URL = "https://api.kaixin001.com/users/me.json"; - private static final Token EMPTY_TOKEN = null; - - public static void main(String[] args) - { - // Replace these with your own api key and secret - String apiKey = "your api key"; - String apiSecret = "your api secret"; - OAuthService service = new ServiceBuilder() - .provider(KaixinApi20.class) - .apiKey(apiKey) - .apiSecret(apiSecret) - .callback("http://your.domain.com/handle") - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); - System.out.println(); - - // Obtain the Authorization URL - System.out.println("Fetching the Authorization URL..."); - String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN); - System.out.println("Got the Authorization URL!"); - System.out.println("Now go and authorize Scribe here:"); - System.out.println(authorizationUrl); - System.out.println("And paste the authorization code here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verifier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getCode()); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - - } -} diff --git a/src/test/java/org/scribe/examples/LinkedInExample.java b/src/test/java/org/scribe/examples/LinkedInExample.java deleted file mode 100644 index 703cc8275..000000000 --- a/src/test/java/org/scribe/examples/LinkedInExample.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.scribe.examples; - -import java.util.Scanner; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class LinkedInExample -{ - private static final String PROTECTED_RESOURCE_URL = "http://api.linkedin.com/v1/people/~/connections:(id,last-name)"; - - public static void main(String[] args) - { - OAuthService service = new ServiceBuilder() - .provider(LinkedInApi.class) - .apiKey("CiEgwWDkA5BFpNrc0RfGyVuSlOh4tig5kOTZ9q97qcXNrFl7zqk-Ts7DqRGaKDCV") - .apiSecret("dhho4dfoCmiQXrkw4yslork5XWLFnPSuMR-8gscPVjY4jqFFHPYWJKgpFl4uLTM6") - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== LinkedIn's OAuth Workflow ==="); - System.out.println(); - - // Obtain the Request Token - System.out.println("Fetching the Request Token..."); - Token requestToken = service.getRequestToken(); - System.out.println("Got the Request Token!"); - System.out.println(); - - System.out.println("Now go and authorize Scribe here:"); - System.out.println(service.getAuthorizationUrl(requestToken)); - System.out.println("And paste the verifier here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - } - -} diff --git a/src/test/java/org/scribe/examples/LiveExample.java b/src/test/java/org/scribe/examples/LiveExample.java deleted file mode 100644 index ade5a6ba9..000000000 --- a/src/test/java/org/scribe/examples/LiveExample.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.scribe.examples; - -import java.util.*; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class LiveExample -{ - private static final String PROTECTED_RESOURCE_URL = "https://api.foursquare.com/v2/users/self/friends?oauth_token="; - private static final Token EMPTY_TOKEN = null; - - public static void main(String[] args) - { - // Replace these with your own api key and secret - String apiKey = ""; - String apiSecret = ""; - OAuthService service = new ServiceBuilder() - .provider(LiveApi.class) - .apiKey(apiKey) - .apiSecret(apiSecret) - .scope("wl.basic") - .callback("http://localhost:9000/") - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== Windows Live's OAuth Workflow ==="); - System.out.println(); - - // Obtain the Authorization URL - System.out.println("Fetching the Authorization URL..."); - String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN); - System.out.println("Got the Authorization URL!"); - System.out.println("Now go and authorize Scribe here:"); - System.out.println(authorizationUrl); - System.out.println("And paste the authorization code here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL + accessToken.getToken()); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getCode()); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - - } -} diff --git a/src/test/java/org/scribe/examples/LoveFilmExample.java b/src/test/java/org/scribe/examples/LoveFilmExample.java deleted file mode 100644 index 9e800161e..000000000 --- a/src/test/java/org/scribe/examples/LoveFilmExample.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.scribe.examples; - -import java.util.*; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class LoveFilmExample -{ - private static final String NETWORK_NAME = "LoveFilm"; - private static final String PROTECTED_RESOURCE_URL = "https://api.lovefilm.com/users"; - - public static void main(String[] args) - { - // Replace these with your own api key and secret - String apiKey = "your_key"; - String apiSecret = "your_secret"; - OAuthService service = new ServiceBuilder().provider(LoveFilmApi.class).apiKey(apiKey).apiSecret(apiSecret).build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); - System.out.println(); - - // Grab a request token. - System.out.println("Fetching request token."); - Token requestToken = service.getRequestToken(); - System.out.println("Got it ... "); - System.out.println(requestToken.getToken()); - - // Obtain the Authorization URL - System.out.println("Fetching the Authorization URL..."); - String authorizationUrl = service.getAuthorizationUrl(requestToken); - System.out.println("Got the Authorization URL!"); - System.out.println("Now go and authorize Scribe here:"); - System.out.println(authorizationUrl); - System.out.println("And paste the authorization code here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getCode()); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - - } -} diff --git a/src/test/java/org/scribe/examples/MeetupExample.java b/src/test/java/org/scribe/examples/MeetupExample.java deleted file mode 100644 index 2185b5c27..000000000 --- a/src/test/java/org/scribe/examples/MeetupExample.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.scribe.examples; - -import java.util.Scanner; - -import org.scribe.builder.ServiceBuilder; -import org.scribe.builder.api.MeetupApi; -import org.scribe.model.OAuthRequest; -import org.scribe.model.Response; -import org.scribe.model.Token; -import org.scribe.model.Verb; -import org.scribe.model.Verifier; -import org.scribe.oauth.OAuthService; - -public class MeetupExample -{ - private static final String PROTECTED_RESOURCE_URL = "http://api.meetup.com/2/member/self"; - - public static void main(String[] args) - { - OAuthService service = new ServiceBuilder() - .provider(MeetupApi.class) - .apiKey("j1khkp0dus323ftve0sdcv6ffe") - .apiSecret("6s6gt6q59gvfjtsvgcmht62gq4") - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== Meetup's OAuth Workflow ==="); - System.out.println(); - - // Obtain the Request Token - System.out.println("Fetching the Request Token..."); - Token requestToken = service.getRequestToken(); - System.out.println("Got the Request Token!"); - System.out.println(); - - System.out.println("Now go and authorize Scribe here:"); - System.out.println(service.getAuthorizationUrl(requestToken)); - System.out.println("And paste the verifier here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - } -} diff --git a/src/test/java/org/scribe/examples/NeteaseWeiboExample.java b/src/test/java/org/scribe/examples/NeteaseWeiboExample.java deleted file mode 100644 index e65335e76..000000000 --- a/src/test/java/org/scribe/examples/NeteaseWeiboExample.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.scribe.examples; - -import java.util.*; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class NeteaseWeiboExample -{ - private static final String NETWORK_NAME = "NetEase(163.com) Weibo"; - private static final String PROTECTED_RESOURCE_URL = "http://api.t.163.com/account/verify_credentials.json"; - - public static void main(String[] args) - { - // Replace these with your own api key and secret - String apiKey = "your key"; - String apiSecret = "your secret"; - OAuthService service = new ServiceBuilder() - .provider(NeteaseWeibooApi.class) - .apiKey(apiKey) - .apiSecret(apiSecret) - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); - System.out.println(); - - // Grab a request token. - System.out.println("Fetching request token."); - Token requestToken = service.getRequestToken(); - System.out.println("Got it ... "); - System.out.println(requestToken.getToken()); - - // Obtain the Authorization URL - System.out.println("Fetching the Authorization URL..."); - String authorizationUrl = service.getAuthorizationUrl(requestToken); - System.out.println("Got the Authorization URL!"); - System.out.println("Now go and authorize Scribe here:"); - System.out.println(authorizationUrl); - System.out.println("And paste the authorization code here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " - + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getCode()); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - } -} diff --git a/src/test/java/org/scribe/examples/Px500Example.java b/src/test/java/org/scribe/examples/Px500Example.java deleted file mode 100644 index cdbe44997..000000000 --- a/src/test/java/org/scribe/examples/Px500Example.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.scribe.examples; - -import java.util.Scanner; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class Px500Example -{ - private static final String PROTECTED_RESOURCE_URL = "https://api.500px.com/v1/"; - - public static void main(String[] args) - { - OAuthService service = new ServiceBuilder() - .provider(Px500Api.class) - .apiKey("your-api-key") - .apiSecret("your-api-secret") - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== 500Px's OAuth Workflow ==="); - System.out.println(); - - // Obtain the Request Token - System.out.println("Fetching the Request Token..."); - Token requestToken = service.getRequestToken(); - System.out.println("Got the Request Token!"); - System.out.println(); - - System.out.println("Now go and authorize Scribe here:"); - System.out.println(service.getAuthorizationUrl(requestToken)); - System.out.println("And paste the verifier here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - - } - -} \ No newline at end of file diff --git a/src/test/java/org/scribe/examples/RenrenExample.java b/src/test/java/org/scribe/examples/RenrenExample.java deleted file mode 100644 index ae13375b8..000000000 --- a/src/test/java/org/scribe/examples/RenrenExample.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.scribe.examples; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; -import java.nio.charset.*; -import java.security.*; -import java.util.*; - -public class RenrenExample -{ - private static final String NETWORK_NAME = "Renren"; - private static final String PROTECTED_RESOURCE_URL = "http://api.renren.com/restserver.do"; - private static final Token EMPTY_TOKEN = null; - - public static void main(String[] args) - { - // Replace these with your own api key and secret - String apiKey = "your api key"; - String apiSecret = "your api secret"; - OAuthService service = new ServiceBuilder() - .provider(RenrenApi.class) - .apiKey(apiKey) - .apiSecret(apiSecret) - .scope("status_update publish_feed") - .callback("http://your.doman.com/oauth/renren") - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); - System.out.println(); - - // Obtain the Authorization URL - System.out.println("Fetching the Authorization URL..."); - String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN); - System.out.println("Got the Authorization URL!"); - System.out.println("Now go and authorize Scribe here:"); - System.out.println(authorizationUrl); - System.out.println("And paste the authorization code here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.POST, PROTECTED_RESOURCE_URL); - Map parameters = new HashMap(); - parameters.put("method", "users.getInfo"); - parameters.put("format", "json"); - parameters.put("v", "1.0"); - - List sigString = new ArrayList(parameters.size() + 1); - for (Map.Entry entry : parameters.entrySet()) - { - request.addQuerystringParameter(entry.getKey(), entry.getValue()); - sigString.add(String.format("%s=%s", entry.getKey(), entry.getValue())); - } - sigString.add(String.format("%s=%s", OAuthConstants.ACCESS_TOKEN, accessToken.getToken())); - Collections.sort(sigString); - StringBuilder b = new StringBuilder(); - for (String param : sigString) - { - b.append(param); - } - b.append(apiSecret); - System.out.println("Sig string: " + b.toString()); - request.addQuerystringParameter("sig", md5(b.toString())); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getCode()); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - - } - - public static String md5(String orgString) - { - try - { - java.security.MessageDigest md = MessageDigest.getInstance("MD5"); - byte[] array = md.digest(orgString.getBytes(Charset.forName("UTF-8"))); - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < array.length; ++i) - { - sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1, 3)); - } - return sb.toString(); - } - catch (NoSuchAlgorithmException e) - { - e.printStackTrace(); - } - return null; - } - -} diff --git a/src/test/java/org/scribe/examples/SinaWeibo2Example.java b/src/test/java/org/scribe/examples/SinaWeibo2Example.java deleted file mode 100644 index 89b14e117..000000000 --- a/src/test/java/org/scribe/examples/SinaWeibo2Example.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.scribe.examples; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; -import java.util.*; - -public class SinaWeibo2Example -{ - private static final String NETWORK_NAME = "SinaWeibo"; - private static final String PROTECTED_RESOURCE_URL = "https://api.weibo.com/2/account/get_uid.json"; - private static final Token EMPTY_TOKEN = null; - - public static void main(String[] args) - { - // Replace these with your own api key and secret - String apiKey = "your_api_key"; - String apiSecret = "your_api_secret"; - OAuthService service = new ServiceBuilder() - .provider(SinaWeiboApi20.class) - .apiKey(apiKey) - .apiSecret(apiSecret) - .callback("http://www.dajie.com/oauth/sina") - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); - System.out.println(); - - // Obtain the Authorization URL - System.out.println("Fetching the Authorization URL..."); - String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN); - System.out.println("Got the Authorization URL!"); - System.out.println("Now go and authorize Scribe here:"); - System.out.println(authorizationUrl); - System.out.println("And paste the authorization code here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verifier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getCode()); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - - } -} diff --git a/src/test/java/org/scribe/examples/SinaWeiboExample.java b/src/test/java/org/scribe/examples/SinaWeiboExample.java deleted file mode 100644 index 2dc4b7c04..000000000 --- a/src/test/java/org/scribe/examples/SinaWeiboExample.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.scribe.examples; - -import java.util.*; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class SinaWeiboExample -{ - private static final String NETWORK_NAME = "SinaWeibo"; - private static final String PROTECTED_RESOURCE_URL = "http://api.t.sina.com.cn/account/verify_credentials.json"; - - public static void main(String[] args) - { - // Replace these with your own api key and secret - String apiKey = "your key"; - String apiSecret = "your secret"; - OAuthService service = new ServiceBuilder() - .provider(SinaWeiboApi.class) - .apiKey(apiKey) - .apiSecret(apiSecret) - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); - System.out.println(); - - // Grab a request token. - System.out.println("Fetching request token."); - Token requestToken = service.getRequestToken(); - System.out.println("Got it ... "); - System.out.println(requestToken.getToken()); - - // Obtain the Authorization URL - System.out.println("Fetching the Authorization URL..."); - String authorizationUrl = service.getAuthorizationUrl(requestToken); - System.out.println("Got the Authorization URL!"); - System.out.println("Now go and authorize Scribe here:"); - System.out.println(authorizationUrl); - System.out.println("And paste the authorization code here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " - + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getCode()); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - } -} diff --git a/src/test/java/org/scribe/examples/SkyrockExample.java b/src/test/java/org/scribe/examples/SkyrockExample.java deleted file mode 100644 index 422d067e5..000000000 --- a/src/test/java/org/scribe/examples/SkyrockExample.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.scribe.examples; - -import java.util.Scanner; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class SkyrockExample -{ - private static final String PROTECTED_RESOURCE_URL = "https://api.skyrock.com/v2/user/get.json"; - - public static void main(String[] args) - { - OAuthService service = new ServiceBuilder() - .provider(SkyrockApi.class) - .apiKey("your-api-key") - .apiSecret("your-api-secret") - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== Skyrock's OAuth Workflow ==="); - System.out.println(); - - // Obtain the Request Token - System.out.println("Fetching the Request Token..."); - Token requestToken = service.getRequestToken(); - System.out.println("Got the Request Token!"); - System.out.println(); - - System.out.println("Now go and authorize Scribe here:"); - System.out.println(service.getAuthorizationUrl(requestToken)); - System.out.println("And paste the verifier here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getCode()); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - - } - -} diff --git a/src/test/java/org/scribe/examples/SohuWeiboExample.java b/src/test/java/org/scribe/examples/SohuWeiboExample.java deleted file mode 100644 index 49dd9fb72..000000000 --- a/src/test/java/org/scribe/examples/SohuWeiboExample.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.scribe.examples; - -import java.util.*; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class SohuWeiboExample -{ - private static final String NETWORK_NAME = "SohuWeibo"; - private static final String PROTECTED_RESOURCE_URL = "http://api.t.sohu.com/account/verify_credentials.json"; - - public static void main(String[] args) - { - // Replace these with your own api key and secret - String apiKey = "your_key"; - String apiSecret = "your_secret"; - OAuthService service = new ServiceBuilder() - .provider(SohuWeiboApi.class) - .apiKey(apiKey) - .apiSecret(apiSecret) - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); - System.out.println(); - - // Grab a request token. - System.out.println("Fetching request token."); - Token requestToken = service.getRequestToken(); - System.out.println("Got it ... "); - System.out.println(requestToken.getToken()); - - // Obtain the Authorization URL - System.out.println("Fetching the Authorization URL..."); - String authorizationUrl = service.getAuthorizationUrl(requestToken); - System.out.println("Got the Authorization URL!"); - System.out.println("Now go and authorize Scribe here:"); - System.out.println(authorizationUrl); - System.out.println("And paste the authorization code here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " - + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getCode()); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - } -} diff --git a/src/test/java/org/scribe/examples/TrelloExample.java b/src/test/java/org/scribe/examples/TrelloExample.java deleted file mode 100644 index 9888f5e90..000000000 --- a/src/test/java/org/scribe/examples/TrelloExample.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.scribe.examples; - -import java.util.Scanner; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class TrelloExample -{ - private static final String API_KEY = "your_api_key"; - private static final String API_SECRET = "your_api_secret"; - private static final String PROTECTED_RESOURCE_URL = "https://trello.com/1/members/me"; - public static void main(String[] args) - { - OAuthService service = new ServiceBuilder() - .provider(TrelloApi.class) - .apiKey(API_KEY) - .apiSecret(API_SECRET) - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== Trello's OAuth Workflow ==="); - System.out.println(); - - // Obtain the Request Token - System.out.println("Fetching the Request Token..."); - Token requestToken = service.getRequestToken(); - System.out.println("Got the Request Token!"); - System.out.println(); - - System.out.println("Now go and authorize Scribe here:"); - System.out.println(service.getAuthorizationUrl(requestToken)); - System.out.println("And paste the verifier here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - } - -} diff --git a/src/test/java/org/scribe/examples/TwitterExample.java b/src/test/java/org/scribe/examples/TwitterExample.java deleted file mode 100644 index 28d9bea54..000000000 --- a/src/test/java/org/scribe/examples/TwitterExample.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.scribe.examples; - -import java.util.Scanner; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class TwitterExample -{ - private static final String PROTECTED_RESOURCE_URL = "https://api.twitter.com/1/statuses/update.json"; - - public static void main(String[] args) - { - OAuthService service = new ServiceBuilder() - .provider(TwitterApi.class) - .apiKey("6icbcAXyZx67r8uTAUM5Qw") - .apiSecret("SCCAdUUc6LXxiazxH3N0QfpNUvlUy84mZ2XZKiv39s") - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== Twitter's OAuth Workflow ==="); - System.out.println(); - - // Obtain the Request Token - System.out.println("Fetching the Request Token..."); - Token requestToken = service.getRequestToken(); - System.out.println("Got the Request Token!"); - System.out.println(); - - System.out.println("Now go and authorize Scribe here:"); - System.out.println(service.getAuthorizationUrl(requestToken)); - System.out.println("And paste the verifier here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.POST, PROTECTED_RESOURCE_URL); - request.addBodyParameter("status", "this is sparta! *"); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - } - -} \ No newline at end of file diff --git a/src/test/java/org/scribe/examples/VkontakteExample.java b/src/test/java/org/scribe/examples/VkontakteExample.java deleted file mode 100644 index f9e4134e7..000000000 --- a/src/test/java/org/scribe/examples/VkontakteExample.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.scribe.examples; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -import java.util.*; - -/** - * @author Boris G. Tsirkin - * @since 20.4.2011 - */ -public class VkontakteExample -{ - private static final String NETWORK_NAME = "Vkontakte.ru"; - private static final String PROTECTED_RESOURCE_URL = "https://api.vkontakte.ru/method/friends.get"; - private static final Token EMPTY_TOKEN = null; - - public static void main(String[] args) - { - // Replace these with your own api key and secret - final String clientId = "your app id"; - final String apiSecret = "your api secret"; - OAuthService service = new ServiceBuilder() - .provider(VkontakteApi.class) - .apiKey(clientId) - .apiSecret(apiSecret) - .scope("friends,wall,offline") // replace with desired scope - .callback("http://your.site.com/callback") - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); - System.out.println(); - - // Obtain the Authorization URL - System.out.println("Fetching the Authorization URL..."); - String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN); - System.out.println("Got the Authorization URL!"); - System.out.println("Now go and authorize Scribe here:"); - System.out.println(authorizationUrl); - System.out.println("And paste the authorization code here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getCode()); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - } -} diff --git a/src/test/java/org/scribe/examples/YahooExample.java b/src/test/java/org/scribe/examples/YahooExample.java deleted file mode 100644 index 2e3f336f0..000000000 --- a/src/test/java/org/scribe/examples/YahooExample.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.scribe.examples; - -import java.util.Scanner; - -import org.scribe.builder.*; -import org.scribe.builder.api.*; -import org.scribe.model.*; -import org.scribe.oauth.*; - -public class YahooExample -{ - private static final String PROTECTED_RESOURCE_URL = "http://social.yahooapis.com/v1/user/A6ROU63MXWDCW3Y5MGCYWVHDJI/profile/status?format=json"; - - public static void main(String[] args) - { - OAuthService service = new ServiceBuilder() - .provider(YahooApi.class) - .apiKey("dj0yJmk9TXZDWVpNVVdGaVFmJmQ9WVdrOWMweHZXbkZLTkhVbWNHbzlNVEl5TWprd05qUTJNZy0tJnM9Y29uc3VtZXJzZWNyZXQmeD0wMw--") - .apiSecret("262be559f92a2be20c4c039419018f2b48cdfce9") - .build(); - Scanner in = new Scanner(System.in); - - System.out.println("=== Yahoo's OAuth Workflow ==="); - System.out.println(); - - // Obtain the Request Token - System.out.println("Fetching the Request Token..."); - Token requestToken = service.getRequestToken(); - System.out.println("Got the Request Token!"); - System.out.println(); - - System.out.println("Now go and authorize Scribe here:"); - System.out.println(service.getAuthorizationUrl(requestToken)); - System.out.println("And paste the verifier here"); - System.out.print(">>"); - Verifier verifier = new Verifier(in.nextLine()); - System.out.println(); - - // Trade the Request Token and Verfier for the Access Token - System.out.println("Trading the Request Token for an Access Token..."); - Token accessToken = service.getAccessToken(requestToken, verifier); - System.out.println("Got the Access Token!"); - System.out.println("(if your curious it looks like this: " + accessToken + " )"); - System.out.println(); - - // Now let's go and ask for a protected resource! - System.out.println("Now we're going to access a protected resource..."); - OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); - service.signRequest(accessToken, request); - Response response = request.send(); - System.out.println("Got it! Lets see what we found..."); - System.out.println(); - System.out.println(response.getCode()); - System.out.println(response.getBody()); - - System.out.println(); - System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); - - } -} diff --git a/src/test/java/org/scribe/extractors/BaseStringExtractorTest.java b/src/test/java/org/scribe/extractors/BaseStringExtractorTest.java deleted file mode 100644 index edc101d15..000000000 --- a/src/test/java/org/scribe/extractors/BaseStringExtractorTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.scribe.extractors; - -import static org.junit.Assert.*; - -import org.junit.*; -import org.scribe.exceptions.*; -import org.scribe.model.*; -import org.scribe.test.helpers.*; - -public class BaseStringExtractorTest -{ - - private BaseStringExtractorImpl extractor; - private OAuthRequest request; - - @Before - public void setup() - { - request = ObjectMother.createSampleOAuthRequest(); - extractor = new BaseStringExtractorImpl(); - } - - @Test - public void shouldExtractBaseStringFromOAuthRequest() - { - String expected = "GET&http%3A%2F%2Fexample.com&oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature%26oauth_timestamp%3D123456"; - String baseString = extractor.extract(request); - assertEquals(expected, baseString); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionIfRquestIsNull() - { - OAuthRequest nullRequest = null; - extractor.extract(nullRequest); - } - - @Test(expected = OAuthParametersMissingException.class) - public void shouldThrowExceptionIfRquestHasNoOAuthParameters() - { - OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com"); - extractor.extract(request); - } - - @Test - public void shouldProperlyEncodeSpaces() - { - String expected = "GET&http%3A%2F%2Fexample.com&body%3Dthis%2520param%2520has%2520whitespace%26oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature%26oauth_timestamp%3D123456"; - request.addBodyParameter("body", "this param has whitespace"); - assertEquals(expected, extractor.extract(request)); - } -} diff --git a/src/test/java/org/scribe/extractors/HeaderExtractorTest.java b/src/test/java/org/scribe/extractors/HeaderExtractorTest.java deleted file mode 100644 index bdc727cd8..000000000 --- a/src/test/java/org/scribe/extractors/HeaderExtractorTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.scribe.extractors; - -import static org.junit.Assert.*; - -import org.junit.*; -import org.scribe.exceptions.*; -import org.scribe.model.*; -import org.scribe.test.helpers.*; - -public class HeaderExtractorTest -{ - - private HeaderExtractorImpl extractor; - private OAuthRequest request; - - @Before - public void setup() - { - request = ObjectMother.createSampleOAuthRequest(); - extractor = new HeaderExtractorImpl(); - } - - @Test - public void shouldExtractStandardHeader() - { - String expected = "OAuth oauth_callback=\"http%3A%2F%2Fexample%2Fcallback\", " + "oauth_signature=\"OAuth-Signature\", " - + "oauth_consumer_key=\"AS%23%24%5E%2A%40%26\", " + "oauth_timestamp=\"123456\""; - String header = extractor.extract(request); - assertEquals(expected, header); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldExceptionIfRequestIsNull() - { - OAuthRequest nullRequest = null; - extractor.extract(nullRequest); - } - - @Test(expected = OAuthParametersMissingException.class) - public void shouldExceptionIfRequestHasNoOAuthParams() - { - OAuthRequest emptyRequest = new OAuthRequest(Verb.GET, "http://example.com"); - extractor.extract(emptyRequest); - } -} diff --git a/src/test/java/org/scribe/extractors/JsonTokenExtractorTest.java b/src/test/java/org/scribe/extractors/JsonTokenExtractorTest.java deleted file mode 100644 index 412e13141..000000000 --- a/src/test/java/org/scribe/extractors/JsonTokenExtractorTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.scribe.extractors; - -import static org.junit.Assert.*; - -import org.junit.*; -import org.scribe.model.*; - -public class JsonTokenExtractorTest -{ - private String response = "'{ \"access_token\":\"I0122HHJKLEM21F3WLPYHDKGKZULAUO4SGMV3ABKFTDT3T3X\"}'"; - private JsonTokenExtractor extractor = new JsonTokenExtractor(); - - @Test - public void shouldParseResponse() - { - Token token = extractor.extract(response); - assertEquals(token.getToken(), "I0122HHJKLEM21F3WLPYHDKGKZULAUO4SGMV3ABKFTDT3T3X"); - } - - @Test(expected=IllegalArgumentException.class) - public void shouldThrowExceptionIfForNullParameters() - { - extractor.extract(null); - } - - @Test(expected=IllegalArgumentException.class) - public void shouldThrowExceptionIfForEmptyStrings() - { - extractor.extract(""); - } -} diff --git a/src/test/java/org/scribe/extractors/TokenExtractor20Test.java b/src/test/java/org/scribe/extractors/TokenExtractor20Test.java deleted file mode 100644 index 0fde22f8e..000000000 --- a/src/test/java/org/scribe/extractors/TokenExtractor20Test.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.scribe.extractors; - -import static org.junit.Assert.*; - -import org.junit.*; -import org.scribe.exceptions.*; -import org.scribe.model.*; - -public class TokenExtractor20Test -{ - - private TokenExtractor20Impl extractor; - - @Before - public void setup() - { - extractor = new TokenExtractor20Impl(); - } - - @Test - public void shouldExtractTokenFromOAuthStandardResponse() - { - String response = "access_token=166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE"; - Token extracted = extractor.extract(response); - assertEquals("166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE", extracted.getToken()); - assertEquals("", extracted.getSecret()); - } - - @Test - public void shouldExtractTokenFromResponseWithExpiresParam() - { - String response = "access_token=166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE&expires=5108"; - Token extracted = extractor.extract(response); - assertEquals("166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE", extracted.getToken()); - assertEquals("", extracted.getSecret()); - } - - @Test - public void shouldExtractTokenFromResponseWithManyParameters() - { - String response = "access_token=foo1234&other_stuff=yeah_we_have_this_too&number=42"; - Token extracted = extractor.extract(response); - assertEquals("foo1234", extracted.getToken()); - assertEquals("", extracted.getSecret()); - } - - @Test(expected = OAuthException.class) - public void shouldThrowExceptionIfTokenIsAbsent() - { - String response = "&expires=5108"; - extractor.extract(response); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionIfResponseIsNull() - { - String response = null; - extractor.extract(response); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionIfResponseIsEmptyString() - { - String response = ""; - extractor.extract(response); - } -} diff --git a/src/test/java/org/scribe/extractors/TokenExtractorTest.java b/src/test/java/org/scribe/extractors/TokenExtractorTest.java deleted file mode 100644 index aca5ad1a7..000000000 --- a/src/test/java/org/scribe/extractors/TokenExtractorTest.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.scribe.extractors; - -import static org.junit.Assert.*; - -import org.junit.*; -import org.scribe.exceptions.*; -import org.scribe.model.*; - -public class TokenExtractorTest -{ - - private TokenExtractorImpl extractor; - - @Before - public void setup() - { - extractor = new TokenExtractorImpl(); - } - - @Test - public void shouldExtractTokenFromOAuthStandardResponse() - { - String response = "oauth_token=hh5s93j4hdidpola&oauth_token_secret=hdhd0244k9j7ao03"; - Token extracted = extractor.extract(response); - assertEquals("hh5s93j4hdidpola", extracted.getToken()); - assertEquals("hdhd0244k9j7ao03", extracted.getSecret()); - } - - @Test - public void shouldExtractTokenFromInvertedOAuthStandardResponse() - { - String response = "oauth_token_secret=hh5s93j4hdidpola&oauth_token=hdhd0244k9j7ao03"; - Token extracted = extractor.extract(response); - assertEquals("hh5s93j4hdidpola", extracted.getSecret()); - assertEquals("hdhd0244k9j7ao03", extracted.getToken()); - } - - @Test - public void shouldExtractTokenFromResponseWithCallbackConfirmed() - { - String response = "oauth_token=hh5s93j4hdidpola&oauth_token_secret=hdhd0244k9j7ao03&callback_confirmed=true"; - Token extracted = extractor.extract(response); - assertEquals("hh5s93j4hdidpola", extracted.getToken()); - assertEquals("hdhd0244k9j7ao03", extracted.getSecret()); - } - - @Test - public void shouldExtractTokenWithEmptySecret() - { - String response = "oauth_token=hh5s93j4hdidpola&oauth_token_secret="; - Token extracted = extractor.extract(response); - assertEquals("hh5s93j4hdidpola", extracted.getToken()); - assertEquals("", extracted.getSecret()); - } - - @Test(expected = OAuthException.class) - public void shouldThrowExceptionIfTokenIsAbsent() - { - String response = "oauth_secret=hh5s93j4hdidpola&callback_confirmed=true"; - extractor.extract(response); - } - - @Test(expected = OAuthException.class) - public void shouldThrowExceptionIfSecretIsAbsent() - { - String response = "oauth_token=hh5s93j4hdidpola&callback_confirmed=true"; - extractor.extract(response); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionIfResponseIsNull() - { - String response = null; - extractor.extract(response); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionIfResponseIsEmptyString() - { - String response = ""; - extractor.extract(response); - } -} diff --git a/src/test/java/org/scribe/model/ConnectionStub.java b/src/test/java/org/scribe/model/ConnectionStub.java deleted file mode 100644 index 7e9331397..000000000 --- a/src/test/java/org/scribe/model/ConnectionStub.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.scribe.model; - -import java.io.*; -import java.net.*; -import java.util.*; - -public class ConnectionStub extends HttpURLConnection -{ - - private Map headers = new HashMap(); - private Map> responseHeaders = new HashMap>(); - private int inputStreamCalled = 0; - - public ConnectionStub() throws Exception - { - super(new URL("http://example.com")); - } - - @Override - public void setRequestProperty(String key, String value) - { - headers.put(key, value); - } - - @Override - public String getRequestProperty(String s) - { - return headers.get(s); - } - - public Map getHeaders() - { - return headers; - } - - @Override - public int getResponseCode() throws IOException - { - return 200; - } - - @Override - public InputStream getInputStream() throws IOException - { - inputStreamCalled++; - return new ByteArrayInputStream("contents".getBytes()); - } - - public int getTimesCalledInpuStream() - { - return inputStreamCalled; - } - - @Override - public OutputStream getOutputStream() throws IOException - { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - baos.write("contents".getBytes()); - return baos; - } - - @Override - public Map> getHeaderFields() - { - return responseHeaders; - } - - public void addResponseHeader(String key, String value) - { - responseHeaders.put(key, Arrays.asList(value)); - } - - public void connect() throws IOException - { - } - - public void disconnect() - { - } - - public boolean usingProxy() - { - return false; - } - -} diff --git a/src/test/java/org/scribe/model/OAuthRequestTest.java b/src/test/java/org/scribe/model/OAuthRequestTest.java deleted file mode 100644 index 1ea2f2fb9..000000000 --- a/src/test/java/org/scribe/model/OAuthRequestTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.scribe.model; - -import static org.junit.Assert.*; - -import org.junit.*; - -public class OAuthRequestTest -{ - - private OAuthRequest request; - - @Before - public void setup() - { - request = new OAuthRequest(Verb.GET, "http://example.com"); - } - - @Test - public void shouldAddOAuthParamters() - { - request.addOAuthParameter(OAuthConstants.TOKEN, "token"); - request.addOAuthParameter(OAuthConstants.NONCE, "nonce"); - request.addOAuthParameter(OAuthConstants.TIMESTAMP, "ts"); - request.addOAuthParameter(OAuthConstants.SCOPE, "feeds"); - - assertEquals(4, request.getOauthParameters().size()); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionIfParameterIsNotOAuth() - { - request.addOAuthParameter("otherParam", "value"); - } -} diff --git a/src/test/java/org/scribe/model/ParameterListTest.java b/src/test/java/org/scribe/model/ParameterListTest.java deleted file mode 100644 index 657e8e218..000000000 --- a/src/test/java/org/scribe/model/ParameterListTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.scribe.model; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotSame; - -/** - * @author: Pablo Fernandez - */ -public class ParameterListTest -{ - private ParameterList params; - - @Before - public void setup() - { - this.params = new ParameterList(); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionWhenAppendingNullMapToQuerystring() - { - String url = null; - params.appendTo(url); - } - - @Test - public void shouldAppendNothingToQuerystringIfGivenEmptyMap() - { - String url = "http://www.example.com"; - Assert.assertEquals(url, params.appendTo(url)); - } - - @Test - public void shouldAppendParametersToSimpleUrl() - { - String url = "http://www.example.com"; - String expectedUrl = "http://www.example.com?param1=value1¶m2=value%20with%20spaces"; - - params.add("param1", "value1"); - params.add("param2", "value with spaces"); - - url = params.appendTo(url); - Assert.assertEquals(url, expectedUrl); - } - - @Test - public void shouldAppendParametersToUrlWithQuerystring() - { - String url = "http://www.example.com?already=present"; - String expectedUrl = "http://www.example.com?already=present¶m1=value1¶m2=value%20with%20spaces"; - - params.add("param1", "value1"); - params.add("param2", "value with spaces"); - - url = params.appendTo(url); - Assert.assertEquals(url, expectedUrl); - } - - @Test - public void shouldProperlySortParameters() - { - params.add("param1", "v1"); - params.add("param6", "v2"); - params.add("a_param", "v3"); - params.add("param2", "v4"); - Assert.assertEquals("a_param=v3¶m1=v1¶m2=v4¶m6=v2", params.sort().asFormUrlEncodedString()); - } - - @Test - public void shouldProperlySortParametersWithTheSameName() - { - params.add("param1", "v1"); - params.add("param6", "v2"); - params.add("a_param", "v3"); - params.add("param1", "v4"); - Assert.assertEquals("a_param=v3¶m1=v1¶m1=v4¶m6=v2", params.sort().asFormUrlEncodedString()); - } - - @Test - public void shouldNotModifyTheOriginalParameterList() - { - params.add("param1", "v1"); - params.add("param6", "v2"); - - assertNotSame(params, params.sort()); - } -} diff --git a/src/test/java/org/scribe/model/RequestTest.java b/src/test/java/org/scribe/model/RequestTest.java deleted file mode 100644 index c473e779c..000000000 --- a/src/test/java/org/scribe/model/RequestTest.java +++ /dev/null @@ -1,128 +0,0 @@ -package org.scribe.model; - -import static org.junit.Assert.*; - -import org.junit.*; - -public class RequestTest -{ - private Request getRequest; - private Request postRequest; - private ConnectionStub connection; - - @Before - public void setup() throws Exception - { - connection = new ConnectionStub(); - postRequest = new Request(Verb.POST, "http://example.com"); - postRequest.addBodyParameter("param", "value"); - postRequest.addBodyParameter("param with spaces", "value with spaces"); - postRequest.setConnection(connection); - getRequest = new Request(Verb.GET, "http://example.com?qsparam=value&other+param=value+with+spaces"); - getRequest.setConnection(connection); - } - - @Test - public void shouldSetRequestVerb() - { - getRequest.send(); - assertEquals("GET", connection.getRequestMethod()); - } - - @Test - public void shouldGetQueryStringParameters() - { - assertEquals(2, getRequest.getQueryStringParams().size()); - assertEquals(0, postRequest.getQueryStringParams().size()); - assertTrue(getRequest.getQueryStringParams().contains(new Parameter("qsparam", "value"))); - } - - @Test - public void shouldAddRequestHeaders() - { - getRequest.addHeader("Header", "1"); - getRequest.addHeader("Header2", "2"); - getRequest.send(); - assertEquals(2, getRequest.getHeaders().size()); - assertEquals(2, connection.getHeaders().size()); - } - - @Test - public void shouldSetBodyParamsAndAddContentLength() - { - assertEquals("param=value¶m%20with%20spaces=value%20with%20spaces", postRequest.getBodyContents()); - postRequest.send(); - assertTrue(connection.getHeaders().containsKey("Content-Length")); - } - - @Test - public void shouldSetPayloadAndHeaders() - { - postRequest.addPayload("PAYLOAD"); - postRequest.send(); - assertEquals("PAYLOAD", postRequest.getBodyContents()); - assertTrue(connection.getHeaders().containsKey("Content-Length")); - } - - @Test - public void shouldAllowAddingQuerystringParametersAfterCreation() - { - Request request = new Request(Verb.GET, "http://example.com?one=val"); - request.addQuerystringParameter("two", "other val"); - request.addQuerystringParameter("more", "params"); - assertEquals(3, request.getQueryStringParams().size()); - } - - @Test - public void shouldReturnTheCompleteUrl() - { - Request request = new Request(Verb.GET, "http://example.com?one=val"); - request.addQuerystringParameter("two", "other val"); - request.addQuerystringParameter("more", "params"); - assertEquals("http://example.com?one=val&two=other%20val&more=params", request.getCompleteUrl()); - } - - @Test - public void shouldHandleQueryStringSpaceEncodingProperly() - { - assertTrue(getRequest.getQueryStringParams().contains(new Parameter("other param","value with spaces"))); - } - - @Test - public void shouldAutomaticallyAddContentTypeForPostRequestsWithBytePayload() - { - postRequest.addPayload("PAYLOAD".getBytes()); - postRequest.send(); - assertEquals(Request.DEFAULT_CONTENT_TYPE, connection.getHeaders().get("Content-Type")); - } - - @Test - public void shouldAutomaticallyAddContentTypeForPostRequestsWithStringPayload() - { - postRequest.addPayload("PAYLOAD"); - postRequest.send(); - assertEquals(Request.DEFAULT_CONTENT_TYPE, connection.getHeaders().get("Content-Type")); - } - - @Test - public void shouldAutomaticallyAddContentTypeForPostRequestsWithBodyParameters() - { - postRequest.send(); - assertEquals(Request.DEFAULT_CONTENT_TYPE, connection.getHeaders().get("Content-Type")); - } - - @Test - public void shouldBeAbleToOverrideItsContentType() - { - postRequest.addHeader("Content-Type", "my-content-type"); - postRequest.send(); - assertEquals("my-content-type", connection.getHeaders().get("Content-Type")); - } - - @Test - public void shouldNotAddContentTypeForGetRequests() - { - getRequest.send(); - assertFalse(connection.getHeaders().containsKey("Content-Type")); - } -} \ No newline at end of file diff --git a/src/test/java/org/scribe/model/ResponseTest.java b/src/test/java/org/scribe/model/ResponseTest.java deleted file mode 100644 index a58fc0355..000000000 --- a/src/test/java/org/scribe/model/ResponseTest.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.scribe.model; - -import static org.junit.Assert.*; - -import java.io.*; - -import org.junit.*; - -public class ResponseTest -{ - - private Response response; - private ConnectionStub connection; - - @Before - public void setup() throws Exception - { - connection = new ConnectionStub(); - connection.addResponseHeader("one", "one"); - connection.addResponseHeader("two", "two"); - response = new Response(connection); - } - - @Test - public void shouldPopulateResponseHeaders() - { - assertEquals(2, response.getHeaders().size()); - assertEquals("one", response.getHeader("one")); - } - - @Test - public void shouldParseBodyContents() - { - assertEquals("contents", response.getBody()); - assertEquals(1, connection.getTimesCalledInpuStream()); - } - - @Test - public void shouldParseBodyContentsOnlyOnce() - { - assertEquals("contents", response.getBody()); - assertEquals("contents", response.getBody()); - assertEquals("contents", response.getBody()); - assertEquals(1, connection.getTimesCalledInpuStream()); - } - - @Test - public void shouldHandleAConnectionWithErrors() throws Exception - { - Response errResponse = new Response(new FaultyConnection()); - assertEquals(400, errResponse.getCode()); - assertEquals("errors", errResponse.getBody()); - } - - private static class FaultyConnection extends ConnectionStub - { - - public FaultyConnection() throws Exception - { - super(); - } - - @Override - public InputStream getErrorStream() - { - return new ByteArrayInputStream("errors".getBytes()); - } - - @Override - public int getResponseCode() throws IOException - { - return 400; - } - } -} diff --git a/src/test/java/org/scribe/model/TokenTest.java b/src/test/java/org/scribe/model/TokenTest.java deleted file mode 100644 index dff59ccf7..000000000 --- a/src/test/java/org/scribe/model/TokenTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.scribe.model; - -import static junit.framework.Assert.*; -import org.junit.*; - -public class TokenTest -{ - @Test - public void shouldTestEqualityBasedOnTokenAndSecret() throws Exception - { - Token expected = new Token("access","secret"); - Token actual = new Token("access","secret"); - - assertEquals(expected, actual); - assertEquals(actual, actual); - } - - @Test - public void shouldNotDependOnRawString() throws Exception - { - Token expected = new Token("access","secret", "raw_string"); - Token actual = new Token("access","secret", "different_raw_string"); - - assertEquals(expected, actual); - } - - @Test - public void shouldReturnSameHashCodeForEqualObjects() throws Exception - { - Token expected = new Token("access","secret"); - Token actual = new Token("access","secret"); - - assertEquals(expected.hashCode(), actual.hashCode()); - } - - @Test - public void shouldNotBeEqualToNullOrOtherObjects() throws Exception - { - Token expected = new Token("access","secret","response"); - - assertNotSame(expected, null); - assertNotSame(expected, new Object()); - } -} diff --git a/src/test/java/org/scribe/services/HMACSha1SignatureServiceTest.java b/src/test/java/org/scribe/services/HMACSha1SignatureServiceTest.java deleted file mode 100644 index ec058a773..000000000 --- a/src/test/java/org/scribe/services/HMACSha1SignatureServiceTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.scribe.services; - -import static org.junit.Assert.*; - -import org.junit.*; -import org.scribe.exceptions.*; - -public class HMACSha1SignatureServiceTest -{ - - private HMACSha1SignatureService service; - - @Before - public void setup() - { - service = new HMACSha1SignatureService(); - } - - @Test - public void shouldReturnSignatureMethodString() - { - String expected = "HMAC-SHA1"; - assertEquals(expected, service.getSignatureMethod()); - } - - @Test - public void shouldReturnSignature() - { - String apiSecret = "api secret"; - String tokenSecret = "token secret"; - String baseString = "base string"; - String signature = "uGymw2KHOTWI699YEaoi5xyLT50="; - assertEquals(signature, service.getSignature(baseString, apiSecret, tokenSecret)); - } - - @Test(expected = OAuthException.class) - public void shouldThrowExceptionIfBaseStringIsNull() - { - service.getSignature(null, "apiSecret", "tokenSecret"); - } - - @Test(expected = OAuthException.class) - public void shouldThrowExceptionIfBaseStringIsEmpty() - { - service.getSignature(" ", "apiSecret", "tokenSecret"); - } - - @Test(expected = OAuthException.class) - public void shouldThrowExceptionIfApiSecretIsNull() - { - service.getSignature("base string", null, "tokenSecret"); - } - - @Test(expected = OAuthException.class) - public void shouldThrowExceptionIfApiSecretIsEmpty() - { - service.getSignature("base string", " ", "tokenSecret"); - } -} diff --git a/src/test/java/org/scribe/services/RSASha1SignatureServiceTest.java b/src/test/java/org/scribe/services/RSASha1SignatureServiceTest.java deleted file mode 100644 index 9e375c5be..000000000 --- a/src/test/java/org/scribe/services/RSASha1SignatureServiceTest.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.scribe.services; - -import static org.junit.Assert.*; - -import org.junit.*; -import org.apache.commons.codec.binary.*; -import java.security.*; -import java.security.spec.*; - -public class RSASha1SignatureServiceTest -{ - - RSASha1SignatureService service = new RSASha1SignatureService(getPrivateKey()); - - @Test - public void shouldReturnSignatureMethodString() - { - String expected = "RSA-SHA1"; - assertEquals(expected, service.getSignatureMethod()); - } - - @Test - public void shouldReturnSignature() - { - String apiSecret = "api secret"; - String tokenSecret = "token secret"; - String baseString = "base string"; - String signature = "LUNRzQAlpdNyM9mLXm96Va6g/qVNnEAb7p7K1KM0g8IopOFQJPoOO7cvppgt7w3QyhijWJnCmvqXaaIAGrqvdyr3fIzBULh8D/iZQUNLMi08GCOA34P81XBvsc7A5uJjPDsGhJg2MzoVJ8nWJhU/lMMk4c92S1WGskeoDofRwpo="; - assertEquals(signature, service.getSignature(baseString, apiSecret, tokenSecret)); - } - - /** - *Created primary key using openssl. - * - * openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj '/C=GB/ST=/L=Manchester/CN=www.example.com' -keyout myrsakey.pem -out /tmp/myrsacert.pem - * openssl pkcs8 -in myrsakey.pem -topk8 -nocrypt -out myrsakey.pk8 - */ - private static PrivateKey getPrivateKey() - { - String str = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMPQ5BCMxlUq2TYy\n"+ - "iRIoEUsz6HGTJhHuasS2nx1Se4Co3lxwxyubVdFj8AuhHNJSmJvjlpbTsGOjLZpr\n"+ - "HyDEDdJmf1Fensh1MhUnBZ4a7uLrZrKzFHHJdamX9pxapB89vLeHlCot9hVXdrZH\n"+ - "nNtg6FdmRKH/8gbs8iDyIayFvzYDAgMBAAECgYA+c9MpTBy9cQsR9BAvkEPjvkx2\n"+ - "XL4ZnfbDgpNA4Nuu7yzsQrPjPomiXMNkkiAFHH67yVxwAlgRjyuuQlgNNTpKvyQt\n"+ - "XcHxffnU0820VmE23M+L7jg2TlB3+rUnEDmDvCoyjlwGDR6lNb7t7Fgg2iR+iaov\n"+ - "0iVzz+l9w0slRlyGsQJBAPWXW2m3NmFgqfDxtw8fsKC2y8o17/cnPjozRGtWb8LQ\n"+ - "g3VCb8kbOFHOYNGazq3M7+wD1qILF2h/HecgK9eQrZ0CQQDMHXoJMfKKbrFrTKgE\n"+ - "zyggO1gtuT5OXYeFewMEb5AbDI2FfSc2YP7SHij8iQ2HdukBrbTmi6qxh3HmIR58\n"+ - "I/AfAkEA0Y9vr0tombsUB8cZv0v5OYoBZvCTbMANtzfb4AOHpiKqqbohDOevLQ7/\n"+ - "SpvgVCmVaDz2PptcRAyEBZ5MCssneQJAB2pmvaDH7Ambfod5bztLfOhLCtY5EkXJ\n"+ - "n6rZcDbRaHorRhdG7m3VtDKOUKZ2DF7glkQGV33phKukErVPUzlHBwJAScD9TqaG\n"+ - "wJ3juUsVtujV23SnH43iMggXT7m82STpPGam1hPfmqu2Z0niePFo927ogQ7H1EMJ\n"+ - "UHgqXmuvk2X/Ww=="; - - try - { - KeyFactory fac = KeyFactory.getInstance("RSA"); - PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(str.getBytes())); - return fac.generatePrivate(privKeySpec); - } - catch (Exception e) - { - throw new RuntimeException(e); - } - } -} diff --git a/src/test/java/org/scribe/services/TimestampServiceTest.java b/src/test/java/org/scribe/services/TimestampServiceTest.java deleted file mode 100644 index 352b962ca..000000000 --- a/src/test/java/org/scribe/services/TimestampServiceTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.scribe.services; - -import static org.junit.Assert.*; - -import org.junit.*; - -public class TimestampServiceTest -{ - - private TimestampServiceImpl service; - private TimestampServiceImpl.Timer timerStub; - - @Before - public void setup() - { - service = new TimestampServiceImpl(); - timerStub = new TimerStub(); - service.setTimer(timerStub); - } - - @Test - public void shouldReturnTimestampInSeconds() - { - String expected = "1000"; - assertEquals(expected, service.getTimestampInSeconds()); - } - - @Test - public void shouldReturnNonce() - { - String expected = "1042"; - assertEquals(expected, service.getNonce()); - } - - private static class TimerStub extends TimestampServiceImpl.Timer - { - - @Override - public Long getMilis() - { - return 1000000L; - } - - @Override - public Integer getRandomInteger() - { - return 42; - } - } -} diff --git a/src/test/java/org/scribe/test/helpers/ObjectMother.java b/src/test/java/org/scribe/test/helpers/ObjectMother.java deleted file mode 100644 index a69a3c13a..000000000 --- a/src/test/java/org/scribe/test/helpers/ObjectMother.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.scribe.test.helpers; - -import org.scribe.model.*; - -public class ObjectMother -{ - - public static OAuthRequest createSampleOAuthRequest() - { - OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com"); - request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456"); - request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, "AS#$^*@&"); - request.addOAuthParameter(OAuthConstants.CALLBACK, "http://example/callback"); - request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature"); - return request; - } -} diff --git a/src/test/java/org/scribe/utils/MapUtilsTest.java b/src/test/java/org/scribe/utils/MapUtilsTest.java deleted file mode 100644 index f44a0f57b..000000000 --- a/src/test/java/org/scribe/utils/MapUtilsTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.scribe.utils; - -import java.util.*; -import org.junit.*; - -/** - * @author: Pablo Fernandez - */ -public class MapUtilsTest -{ - - @Test - public void shouldPrettyPrintMap() - { - Map map = new HashMap(); - map.put(1, "one"); - map.put(2, "two"); - map.put(3, "three"); - map.put(4, "four"); - Assert.assertEquals("{ 1 -> one , 2 -> two , 3 -> three , 4 -> four }", MapUtils.toString(map)); - } - - @Test - public void shouldHandleEmptyMap() - { - Map map = new HashMap(); - Assert.assertEquals("{}", MapUtils.toString(map)); - } - - @Test - public void shouldHandleNullInputs() - { - Assert.assertEquals("", MapUtils.toString(null)); - } -} diff --git a/src/test/java/org/scribe/utils/OAuthEncoderTest.java b/src/test/java/org/scribe/utils/OAuthEncoderTest.java deleted file mode 100644 index cf986a295..000000000 --- a/src/test/java/org/scribe/utils/OAuthEncoderTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.scribe.utils; - -import org.junit.*; -import static org.junit.Assert.*; - -/** - * @author: Pablo Fernandez - */ -public class OAuthEncoderTest -{ - @Test - public void shouldPercentEncodeString() - { - String plain = "this is a test &^"; - String encoded = "this%20is%20a%20test%20%26%5E"; - assertEquals(encoded, OAuthEncoder.encode(plain)); - } - - @Test - public void shouldFormURLDecodeString() - { - String encoded = "this+is+a+test+%26%5E"; - String plain = "this is a test &^"; - assertEquals(plain, OAuthEncoder.decode(encoded)); - } - - @Test - public void shouldPercentEncodeAllSpecialCharacters() - { - String plain = "!*'();:@&=+$,/?#[]"; - String encoded = "%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%23%5B%5D"; - assertEquals(encoded, OAuthEncoder.encode(plain)); - assertEquals(plain, OAuthEncoder.decode(encoded)); - } - - @Test - public void shouldNotPercentEncodeReservedCharacters() - { - String plain = "abcde123456-._~"; - String encoded = plain; - assertEquals(encoded, OAuthEncoder.encode(plain)); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionIfStringToEncodeIsNull() - { - String toEncode = null; - OAuthEncoder.encode(toEncode); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionIfStringToDecodeIsNull() - { - String toDecode = null; - OAuthEncoder.decode(toDecode); - } - - @Test - public void shouldPercentEncodeCorrectlyTwitterCodingExamples() - { - // These tests are part of the Twitter dev examples here -> https://dev.twitter.com/docs/auth/percent-encoding-parameters - String sources[] = {"Ladies + Gentlemen", "An encoded string!", "Dogs, Cats & Mice"}; - String encoded[] = {"Ladies%20%2B%20Gentlemen", "An%20encoded%20string%21", "Dogs%2C%20Cats%20%26%20Mice"}; - - for(int i = 0; i < sources.length; i++) - { - Assert.assertEquals(encoded[i], OAuthEncoder.encode(sources[i])); - } - } -} diff --git a/src/test/java/org/scribe/utils/PreconditionsTest.java b/src/test/java/org/scribe/utils/PreconditionsTest.java deleted file mode 100644 index 84bc117e9..000000000 --- a/src/test/java/org/scribe/utils/PreconditionsTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.scribe.utils; - -import org.junit.*; - -public class PreconditionsTest -{ - - private static final String ERROR_MSG = ""; - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionForNullObjects() - { - Preconditions.checkNotNull(null, ERROR_MSG); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionForNullStrings() - { - Preconditions.checkEmptyString(null, ERROR_MSG); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionForEmptyStrings() - { - Preconditions.checkEmptyString("", ERROR_MSG); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionForSpacesOnlyStrings() - { - Preconditions.checkEmptyString(" ", ERROR_MSG); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionForInvalidUrls() - { - Preconditions.checkValidUrl("this/is/not/a/valid/url", ERROR_MSG); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldThrowExceptionForNullUrls() - { - Preconditions.checkValidUrl(null, ERROR_MSG); - } - - @Test - public void shouldAllowValidUrls() - { - Preconditions.checkValidUrl("http://www.example.com", ERROR_MSG); - } - - @Test - public void shouldAllowSSLUrls() - { - Preconditions.checkValidUrl("https://www.example.com", ERROR_MSG); - } - - @Test - public void shouldAllowSpecialCharsInScheme() - { - Preconditions.checkValidUrl("custom+9.3-1://www.example.com", ERROR_MSG); - } - - @Test - public void shouldAllowNonStandarProtocolsForAndroid() - { - Preconditions.checkValidUrl("x-url-custom://www.example.com", ERROR_MSG); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldNotAllowStrangeProtocolNames() - { - Preconditions.checkValidUrl("$weird*://www.example.com", ERROR_MSG); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldNotAllowUnderscoreInScheme() - { - Preconditions.checkValidUrl("http_custom://www.example.com", ERROR_MSG); - } - - @Test - public void shouldAllowOutOfBandAsValidCallbackValue() - { - Preconditions.checkValidOAuthCallback("oob", ERROR_MSG); - } -} diff --git a/src/test/java/org/scribe/utils/StreamUtilsTest.java b/src/test/java/org/scribe/utils/StreamUtilsTest.java deleted file mode 100644 index 976914d05..000000000 --- a/src/test/java/org/scribe/utils/StreamUtilsTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.scribe.utils; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; - -import org.junit.Test; - -import static org.junit.Assert.*; - -public class StreamUtilsTest -{ - - @Test - public void shouldCorrectlyDecodeAStream() - { - String value = "expected"; - InputStream is = new ByteArrayInputStream(value.getBytes()); - String decoded = StreamUtils.getStreamContents(is); - assertEquals("expected", decoded); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldFailForNullParameter() - { - InputStream is = null; - StreamUtils.getStreamContents(is); - fail("Must throw exception before getting here"); - } -} diff --git a/changelog.txt b/v1-changelog similarity index 99% rename from changelog.txt rename to v1-changelog index 617567805..5423c6237 100644 --- a/changelog.txt +++ b/v1-changelog @@ -95,3 +95,4 @@ [1.3.3] * FEATURE: accessToken and requestToken timeouts default to 2 seconds and can be specified. + * FEATURE: New Apis. diff --git a/v2pre-changelog b/v2pre-changelog new file mode 100644 index 000000000..6f456136e --- /dev/null +++ b/v2pre-changelog @@ -0,0 +1,57 @@ +[SNAPSHOT] + * prepare to merge back to the ScribeJava + * backport 'news' from scribejava + +[3.4] + * add doktornarabote.ru API support + +[3.3] + * upgrade ning async http client 1.9.20 -> 1.9.26 + * add possibility to use ProxyServer per-request (async only) + * rename maven modules, add "subscribe-" prefix + * backport anything new from scribe-java + +[3.2] + * add possibility to set non-default httpProvider Class Name for ning async http client + +[3.1] + * update FaceBook API version from 2.0 to 2.2 + * update ning dependency for async functionality + * allow 'realm' parameter in OAuthParameters + +[3.0] + * make compilable with OpenJDK8 + * add async functionality + * add GitHub API + * split on two maven modules (+repackaging) + +[2.3] + + * add state parameter in LinkedInAPI 2.0 + * update FB Graph API to version 2.0 + * add tut.by OAuth API + * add default parameter grant_type for Google, LinkedIn and Mail.ru + * update host for requests in VkontakteExample + * add Yinxiang Biji endpoint in EvernoteApi + * switch Flickr and Twitter to https + * update domain for LiveAPI + * add support for the Authorization parameter 'realm' + * add TumblrExample + * update TwitterExample to v1.1 + * merge Request class in OAuthRequest. No need in separate Request class. + No planned usages of 'clean' http requests. + * add required OAuthService parameter in constructor for OAuthRequest, + so it can use OAuthConfig always (Default timeouts for all OAuthRequests + per OAuthService instance are now possible 'from-the-box'). + * remove messy RequestTuner. Use OAuthConfig instead of it. + +[2.1] + + * add OpenID id_token parsing from response to GoogleAPI 2.0 + * add optional OAuth 'state' request parameter + * Add hh api support + * fix Mailru API + +[2.0] + + * New release. First release. Formalizations of new project.