package com.cattong.commons.http.auth;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;
import com.cattong.commons.LibException;
import com.cattong.commons.LibResultCode;
import com.cattong.commons.LibRuntimeException;
import com.cattong.commons.Logger;
import com.cattong.commons.ServiceProvider;
import com.cattong.commons.http.HttpMethod;
import com.cattong.commons.http.HttpRequestHelper;
import com.cattong.commons.http.HttpRequestWrapper;
import com.cattong.commons.oauth.OAuth2;
import com.cattong.commons.oauth.OAuth2.DisplayType;
import com.cattong.commons.oauth.OAuth2.GrantType;
import com.cattong.commons.oauth.config.OAuthConfig;
import com.cattong.commons.util.ParseUtil;
import com.cattong.commons.util.StringUtil;
import com.cattong.commons.util.UrlUtil;
public class OAuth2AuthorizeHelper {
public OAuth2AuthorizeHelper() throws LibException {
}
public String getAuthorizeUrl(Authorization auth, GrantType grantType, DisplayType displayType) throws LibException {
String authorizeUrl = null;
if (auth == null) {
throw new LibException(LibResultCode.E_PARAM_NULL);
}
OAuthConfig oAuthConfig = auth.getoAuthConfig();
Map<String, String> paramMap = new HashMap<String, String>();
paramMap.put(OAuth2.CLIENT_ID, oAuthConfig.getConsumerKey());
if (grantType == GrantType.IMPLICIT) {
paramMap.put(OAuth2.RESPONSE_TYPE, OAuth2.ResponseType.TOKEN.getTypeValue());
} else if (grantType == GrantType.AUTHORIZATION_CODE) {
paramMap.put(OAuth2.RESPONSE_TYPE, OAuth2.ResponseType.CODE.getTypeValue());
}
paramMap.put(OAuth2.DISPLAY_TYPE, displayType.getTypeValue());
if (StringUtil.isNotEmpty(oAuthConfig.getCallbackUrl())) {
paramMap.put(OAuth2.REDIRECT_URI, oAuthConfig.getCallbackUrl());
}
paramMap.put(OAuth2.SCOPE, oAuthConfig.getOAuthScope());
try {
authorizeUrl = UrlUtil.appendQueryParameters(
oAuthConfig.getAuthorizeUrl(), paramMap, "UTF-8");
} catch (UnsupportedEncodingException e) {
Logger.error(e.getMessage(), e);
}
return authorizeUrl;
}
// public Authorization getAccessTokenByRefreshToken(
// Authorization auth, String refreshToken,
// String state, String... scope) throws LibException {
// if (auth == null || StringUtil.isEmpty(refreshToken)) {
// throw new LibException(LibResultCode.E_PARAM_NULL);
// }
//
// OAuthConfiguration oAuthConfig = auth.getoAuthConfig();
// HttpRequestMessage httpRequestMessage =
// new HttpRequestMessage(HttpMethod.POST, oAuthConfig.getAccessTokenUrl(), auth);
// httpRequestMessage.addParameter(OAuth2.GRANT_TYPE, GrantType.REFRESH_TOKEN.getTypeValue());
// httpRequestMessage.addParameter(OAuth2.REFRESH_TOKEN, refreshToken);
// httpRequestMessage.addParameter(OAuth2.CLIENT_ID, oAuthConfig.getConsumerKey());
// httpRequestMessage.addParameter(OAuth2.CLIENT_SECRET,oAuthConfig.getConsumerSecret());
//
// httpRequestMessage.addParameter(OAuth2.SCOPE, oAuthConfig.getOAuthScope());
//
// if (StringUtil.isNotEmpty(state)) {
// httpRequestMessage.addParameter(OAuth2.STATE, state);
// }
//
//
// auth = HttpRequestHelper.execute(httpRequestMessage,
// new OAuth2AccessTokenResponseHandler(auth));
//
// return auth;
// }
public Authorization retrieveAccessToken(Authorization auth,
String authorizationCode, String state) throws LibException {
if (auth == null || StringUtil.isEmpty(authorizationCode)) {
throw new LibException(LibResultCode.E_PARAM_NULL);
}
OAuthConfig oAuthConfig = auth.getoAuthConfig();
HttpRequestWrapper httpRequestMessage = new HttpRequestWrapper(
HttpMethod.POST, oAuthConfig.getAccessTokenUrl(), auth);
httpRequestMessage.addParameter(OAuth2.GRANT_TYPE, GrantType.AUTHORIZATION_CODE.getTypeValue());
httpRequestMessage.addParameter(OAuth2.CODE, authorizationCode);
httpRequestMessage.addParameter(OAuth2.CLIENT_ID, oAuthConfig.getConsumerKey());
httpRequestMessage.addParameter(OAuth2.CLIENT_SECRET, oAuthConfig.getConsumerSecret());
httpRequestMessage.addParameter(OAuth2.SCOPE, oAuthConfig.getOAuthScope());
if (StringUtil.isNotEmpty(state)) {
httpRequestMessage.addParameter(OAuth2.STATE, state);
}
if (StringUtil.isNotEmpty(oAuthConfig.getCallbackUrl())) {
httpRequestMessage.addParameter(OAuth2.REDIRECT_URI, oAuthConfig.getCallbackUrl());
}
OAuth2AccessTokenResponseHandler responseHandler = new OAuth2AccessTokenResponseHandler(auth);
auth = HttpRequestHelper.execute(httpRequestMessage, responseHandler);
return auth;
}
public Authorization retrieveAccessToken(Authorization auth) throws LibException {
if (auth == null) {
throw new LibException(LibResultCode.E_PARAM_NULL);
}
String username = auth.getAccessToken();
String password = auth.getAccessSecret();
OAuthConfig oAuthConfig = auth.getoAuthConfig();
HttpRequestWrapper httpRequestMessage = new HttpRequestWrapper(
HttpMethod.POST, oAuthConfig.getAccessTokenUrl(), auth);
httpRequestMessage.addParameter(OAuth2.CLIENT_ID, oAuthConfig.getConsumerKey());
httpRequestMessage.addParameter(OAuth2.CLIENT_SECRET, oAuthConfig.getConsumerSecret());
httpRequestMessage.addParameter(OAuth2.GRANT_TYPE,
GrantType.RESOURCE_OWNER_PASSWORD_CREDENTIALS.getTypeValue());
httpRequestMessage.addParameter(OAuth2.USERNAME, username);
httpRequestMessage.addParameter(OAuth2.PASSWORD, password);
httpRequestMessage.addParameter(OAuth2.SCOPE, oAuthConfig.getOAuthScope());
OAuth2AccessTokenResponseHandler responseHandler = new OAuth2AccessTokenResponseHandler(auth);
auth = HttpRequestHelper.execute(httpRequestMessage, responseHandler);
return auth;
}
public static String retrieveAuthorizationCodeFromQueryString(String url) {
URI uri = URI.create(url);
Map<String, String> parameters = UrlUtil.extractQueryStringParameters(uri);
String code = null;
if (parameters != null) {
code = parameters.get(OAuth2.CODE);
}
return code;
}
public static Authorization retrieveAccessTokenFromFragment(String url) {
URI uri = URI.create(url);
Map<String, String> parameters = null;
final String fragment = uri.getFragment();
if (StringUtil.isNotEmpty(fragment)) {
parameters = new HashMap<String, String>();
Scanner scanner = new Scanner(fragment);
scanner.useDelimiter("&");
while (scanner.hasNext()) {
final String[] nameValue = scanner.next().split("=");
if (nameValue.length == 0 || nameValue.length > 2){
throw new IllegalArgumentException("Bad parameter");
}
final String name = nameValue[0];
String value = null;
if (nameValue.length == 2){
value = nameValue[1];
}
parameters.put(name, value);
}
}
Authorization auth = new Authorization(ServiceProvider.None);
if (parameters != null) {
if (parameters.containsKey(OAuth2.ACCESS_TOKEN)) {
String accessToken = parameters.get(OAuth2.ACCESS_TOKEN);
Long expiresIn = Long.valueOf(parameters.get(OAuth2.EXPIRES_IN));
Date expiredAt = new Date(System.currentTimeMillis() + expiresIn * 1000);
auth.setAccessToken(accessToken);
auth.setExpiredAt(expiredAt);
auth.setRefreshToken(parameters.get(OAuth2.REFRESH_TOKEN));
}
}
return auth;
}
private class OAuth2AccessTokenResponseHandler implements ResponseHandler<Authorization> {
private Authorization auth;
private ServiceProvider sp;
public OAuth2AccessTokenResponseHandler(Authorization auth) {
this.auth = auth;
this.sp = auth.getServiceProvider();
}
@Override
public Authorization handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
try {
StatusLine statusLine = response.getStatusLine();
HttpEntity entity = response.getEntity();
final String responseString = EntityUtils.toString(entity);
Logger.debug("OAuth2AccessTokenResponseHandler : {}", responseString);
if (statusLine.getStatusCode() >= 300) {
JSONObject exceptionJson = new JSONObject(responseString);
String error = ParseUtil.getRawString(OAuth2.ERROR, exceptionJson);
if (exceptionJson.has(OAuth2.ERROR_DESCRIPTION)) {
error += (": " + ParseUtil.getRawString(OAuth2.ERROR_DESCRIPTION, exceptionJson));
}
String requestPath = ParseUtil.getRawString(OAuth2.ERROR_URI, exceptionJson);
throw new LibRuntimeException(LibResultCode.OAUTH_EXCEPTION,
requestPath, error, sp);
}
JSONObject json = null;
try {
json = new JSONObject(responseString);
} catch (JSONException e) {
// 响应格式非JSON时,分析字符串
json = new JSONObject();
Scanner scanner = new Scanner(responseString);
scanner.useDelimiter("&");
while (scanner.hasNext()) {
final String[] nameValue = scanner.next().split("=");
if (nameValue.length == 0 || nameValue.length > 2){
throw new IllegalArgumentException("Bad parameter.");
}
json.put(nameValue[0], nameValue.length == 2 ? nameValue[1] : null);
}
if (!json.has(OAuth2.ACCESS_TOKEN)) {
Logger.debug(e.getMessage(), e);
throw e;
}
}
String accessToken = ParseUtil.getRawString(OAuth2.ACCESS_TOKEN, json);
Long expiresIn = ParseUtil.getLong(OAuth2.EXPIRES_IN, json);
Date expiredAt = new Date(System.currentTimeMillis() + expiresIn * 1000);
auth.setAccessToken(accessToken);
auth.setExpiredAt(expiredAt);
auth.setRefreshToken(ParseUtil.getRawString(OAuth2.REFRESH_TOKEN, json));
return auth;
} catch (JSONException e) {
throw new LibRuntimeException(LibResultCode.JSON_PARSE_ERROR, e, sp);
}
}
}
}