/*
* JBoss, Home of Professional Open Source
*
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
*
* 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.picketlink.oauth.client;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.PropertyNamingStrategy;
import org.picketlink.oauth.common.OAuthConstants;
import org.picketlink.oauth.messages.AccessTokenRequest;
import org.picketlink.oauth.messages.AccessTokenResponse;
import org.picketlink.oauth.messages.AuthorizationRequest;
import org.picketlink.oauth.messages.AuthorizationResponse;
import org.picketlink.oauth.messages.OAuthRequest;
import org.picketlink.oauth.messages.RegistrationRequest;
import org.picketlink.oauth.messages.RegistrationResponse;
import org.picketlink.oauth.messages.ResourceAccessRequest;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
/**
* OAuth Client
*
* @author anil saldhana
* @since Sep 23, 2012
*/
public class ClientOAuth {
protected OAuthRequest request;
protected ObjectMapper objectMapper;
/**
* Create a client for making Authorization Code Requests
*
* @return
*/
public AuthorizationClient authorizationClient() {
clear();
return new AuthorizationClient();
}
/**
* Create a client for making Registration Requests
*
* @return
*/
public RegistrationClient registrationClient() {
clear();
return new RegistrationClient();
}
/**
* Create a client for making Access Token Requests
*
* @return
*/
public AccessTokenClient tokenClient() {
clear();
return new AccessTokenClient();
}
/**
* Create a client for making resource requests
*
* @param accessToken
* @return
*/
public ResourceClient resourceClient(String accessToken) {
clear();
return new ResourceClient(accessToken);
}
private void clear() {
request = null;
objectMapper = null;
}
/**
* Create a client that can make authorization code grant requests
*
* @author anil saldhana
*/
public class AuthorizationClient {
private String authorizationEndpoint, clientID, authCodeRedirectURL;
public String getAuthorizationEndpoint() {
return authorizationEndpoint;
}
public AuthorizationClient setAuthorizationEndpoint(String authorizationEndpoint) {
this.authorizationEndpoint = authorizationEndpoint;
return this;
}
public String getClientID() {
return clientID;
}
public AuthorizationClient setClientID(String clientID) {
this.clientID = clientID;
return this;
}
public String getAuthCodeRedirectURL() {
return authCodeRedirectURL;
}
public AuthorizationClient setAuthCodeRedirectURL(String authCodeRedirectURL) {
this.authCodeRedirectURL = authCodeRedirectURL;
return this;
}
public AuthorizationClient build() throws OAuthClientException {
AuthorizationRequest authorizationRequest = new AuthorizationRequest();
authorizationRequest.setLocation(authorizationEndpoint).setClientId(clientID).setRedirectUri(authCodeRedirectURL)
.setResponseType(OAuthConstants.CODE);
request = authorizationRequest;
return this;
}
public AuthorizationResponse execute() throws OAuthClientException {
if (request == null) {
throw new OAuthClientException("Request has not been built. Use build() method");
}
AuthorizationResponse response = new AuthorizationResponse();
try {
AuthorizationRequest authorizationRequest = (AuthorizationRequest) request;
String locationURL = authorizationRequest.getLocation() + "?" + authorizationRequest.asQueryParams();
URL url = new URL(locationURL);
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setInstanceFollowRedirects(true);
c.connect();
response.setStatusCode(c.getResponseCode());
response.setResponseMessage(c.getResponseMessage());
} catch (Exception e) {
throw new OAuthClientException(e);
}
return response;
}
}
/**
* Create a client that can make access token requests
*
* @author anil saldhana
*/
public class AccessTokenClient {
private String tokenEndpoint, authorizationCode, authCodeRedirectURL, clientID, clientSecret;
public String getTokenEndpoint() {
return tokenEndpoint;
}
public AccessTokenClient setTokenEndpoint(String tokenEndpoint) {
this.tokenEndpoint = tokenEndpoint;
return this;
}
public String getAuthorizationCode() {
return authorizationCode;
}
public AccessTokenClient setAuthorizationCode(String authorizationCode) {
this.authorizationCode = authorizationCode;
return this;
}
public String getAuthCodeRedirectURL() {
return authCodeRedirectURL;
}
public AccessTokenClient setAuthCodeRedirectURL(String authCodeRedirectURL) {
this.authCodeRedirectURL = authCodeRedirectURL;
return this;
}
public String getClientID() {
return clientID;
}
public AccessTokenClient setClientID(String clientID) {
this.clientID = clientID;
return this;
}
public String getClientSecret() {
return clientSecret;
}
public AccessTokenClient setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
return this;
}
public AccessTokenClient build() throws OAuthClientException {
AccessTokenRequest accessTokenRequest = new AccessTokenRequest();
accessTokenRequest.setLocation(tokenEndpoint).setGrantType(OAuthConstants.AUTHORIZATION_CODE)
.setCode(authorizationCode).setRedirectUri(authCodeRedirectURL).setClientId(clientID);
request = accessTokenRequest;
return this;
}
public AccessTokenResponse execute() throws OAuthClientException {
if (request == null) {
throw new OAuthClientException("Request has not been built. Use build() method");
}
AccessTokenRequest accessTokenRequest = (AccessTokenRequest) request;
String url = accessTokenRequest.getLocation();
String body = accessTokenRequest.asQueryParams();
InputStream is = executePost(url, body, false);
ObjectMapper mapper = getObjectMapper();
try {
return mapper.readValue(is, AccessTokenResponse.class);
} catch (Exception e) {
throw new OAuthClientException(e);
}
}
}
/**
* Create a client that can make client registration requests
*
* @author anil saldhana
*/
public class RegistrationClient {
String location, appName, appURL, appDescription, appIcon, appRedirectURL;
public String getLocation() {
return location;
}
public RegistrationClient setLocation(String location) {
this.location = location;
return this;
}
public String getAppName() {
return appName;
}
public RegistrationClient setAppName(String appName) {
this.appName = appName;
return this;
}
public String getAppURL() {
return appURL;
}
public RegistrationClient setAppURL(String appURL) {
this.appURL = appURL;
return this;
}
public String getAppDescription() {
return appDescription;
}
public RegistrationClient setAppDescription(String appDescription) {
this.appDescription = appDescription;
return this;
}
public String getAppIcon() {
return appIcon;
}
public RegistrationClient setAppIcon(String appIcon) {
this.appIcon = appIcon;
return this;
}
public String getAppRedirectURL() {
return appRedirectURL;
}
public RegistrationClient setAppRedirectURL(String appRedirectURL) {
this.appRedirectURL = appRedirectURL;
return this;
}
public RegistrationClient build() throws OAuthClientException {
RegistrationRequest registrationRequest = new RegistrationRequest();
registrationRequest.setLocation(location);
registrationRequest.setClientName(appName).setClientUrl(appURL).setClientDescription(appDescription)
.setClientRedirecturl(appRedirectURL).setClient_Icon(appIcon);
request = registrationRequest;
return this;
}
public RegistrationResponse execute() throws OAuthClientException {
if (request == null) {
throw new OAuthClientException("Request has not been built. Use build() method");
}
RegistrationRequest registrationRequest = (RegistrationRequest) request;
String url = registrationRequest.getLocation();
String body = registrationRequest.asQueryParams();
InputStream is = executePost(url, body, false);
ObjectMapper mapper = getObjectMapper();
try {
return mapper.readValue(is, RegistrationResponse.class);
} catch (Exception e) {
throw new OAuthClientException(e);
}
}
public RegistrationResponse registerAsJSON() throws OAuthClientException {
if (request == null) {
throw new OAuthClientException("Request has not been built. Use build() method");
}
RegistrationRequest registrationRequest = (RegistrationRequest) request;
String url = registrationRequest.getLocation();
String body = registrationRequest.asJSON();
InputStream is = executePost(url, body, true);
ObjectMapper mapper = getObjectMapper();
try {
return mapper.readValue(is, RegistrationResponse.class);
} catch (Exception e) {
throw new OAuthClientException(e);
}
}
}
/**
* Create a client that can make access requests for OAuth Resources
*
* @author anil saldhana
*/
public class ResourceClient {
private String resourceURL;
public ResourceClient(String token) {
ResourceAccessRequest resourceAccessRequest = new ResourceAccessRequest();
resourceAccessRequest.setAccessToken(token);
request = resourceAccessRequest;
}
public ResourceClient setResourceURL(String resourceURL) {
this.resourceURL = resourceURL;
return this;
}
public InputStream execute() throws OAuthClientException {
ResourceAccessRequest resourceAccessRequest = (ResourceAccessRequest) request;
String body = resourceAccessRequest.asQueryParams();
return executePost(resourceURL, body, false);
}
}
private ObjectMapper getObjectMapper() {
if (objectMapper == null) {
objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
}
return objectMapper;
}
private InputStream executePost(String endpointURL, String body, boolean isJSON) throws OAuthClientException {
InputStream inputStream = null;
try {
URL resUrl = new URL(endpointURL);
URLConnection urlConnection = resUrl.openConnection();
if (urlConnection instanceof HttpURLConnection) {
HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setDoOutput(true);
httpURLConnection.setAllowUserInteraction(false);
if (isJSON) {
httpURLConnection.setRequestProperty("Content-Type", "application/json");
} else {
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
}
httpURLConnection.setRequestProperty("Content-Length", Integer.toString(body.length()));
OutputStream ost = httpURLConnection.getOutputStream();
PrintWriter pw = new PrintWriter(ost);
pw.print(body);
pw.flush();
pw.close();
if (httpURLConnection.getResponseCode() == 400) {
inputStream = httpURLConnection.getErrorStream();
} else {
inputStream = httpURLConnection.getInputStream();
}
} else {
throw new RuntimeException("Wrong url conn");
}
} catch (Exception e) {
throw new OAuthClientException(e);
}
return inputStream;
}
}