Java tutorial
/* * Copyright 2015 Open mHealth * * 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.openmhealth.shim; import oauth.signpost.OAuth; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.impl.client.HttpClients; import org.springframework.data.domain.Sort; import org.springframework.http.HttpMethod; import org.springframework.web.client.HttpClientErrorException; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.net.URL; import java.util.HashMap; import java.util.Map; import static org.springframework.data.domain.Sort.Direction.DESC; /** * Common code for all OAuth1.0 based shims. * * @author Danilo Bonilla */ public abstract class OAuth1ShimBase extends ShimBase implements OAuth1Shim { private AccessParametersRepo accessParametersRepo; protected HttpClient httpClient = HttpClients.createDefault(); private AuthorizationRequestParametersRepo authorizationRequestParametersRepo; private ShimServerConfig shimServerConfig; protected OAuth1ShimBase(ApplicationAccessParametersRepo applicationParametersRepo, AuthorizationRequestParametersRepo authorizationRequestParametersRepo, ShimServerConfig shimServerConfig, AccessParametersRepo accessParametersRepo) { super(applicationParametersRepo); this.authorizationRequestParametersRepo = authorizationRequestParametersRepo; this.shimServerConfig = shimServerConfig; this.accessParametersRepo = accessParametersRepo; } @Override @SuppressWarnings("unchecked") public AuthorizationRequestParameters getAuthorizationRequestParameters(String username, Map<String, String> additionalParameters) throws ShimException { String stateKey = OAuth1Utils.generateStateKey(); AccessParameters accessParams = accessParametersRepo.findByUsernameAndShimKey(username, getShimKey(), new Sort(DESC, "dateCreated")); if (accessParams != null && accessParams.getAccessToken() != null) { return AuthorizationRequestParameters.authorized(); } HttpRequestBase tokenRequest = null; try { String callbackUrl = shimServerConfig.getCallbackUrl(getShimKey(), stateKey); Map<String, String> requestTokenParameters = new HashMap<>(); requestTokenParameters.put("oauth_callback", callbackUrl); String initiateAuthUrl = getBaseRequestTokenUrl(); tokenRequest = getRequestTokenRequest(initiateAuthUrl, null, null, requestTokenParameters); HttpResponse httpResponse = httpClient.execute(tokenRequest); Map<String, String> tokenParameters = OAuth1Utils.parseRequestTokenResponse(httpResponse); String token = tokenParameters.get(OAuth.OAUTH_TOKEN); String tokenSecret = tokenParameters.get(OAuth.OAUTH_TOKEN_SECRET); if (tokenSecret == null) { throw new ShimException("Request token could not be retrieved"); } URL authorizeUrl = signUrl(getBaseAuthorizeUrl(), token, tokenSecret, null); System.out.println("The authorization url is: "); System.out.println(authorizeUrl); /** * Build the auth parameters entity to return */ AuthorizationRequestParameters parameters = new AuthorizationRequestParameters(); parameters.setUsername(username); parameters.setRedirectUri(callbackUrl); parameters.setStateKey(stateKey); parameters.setAuthorizationUrl(authorizeUrl.toString()); parameters.setRequestParams(tokenParameters); /** * Store the parameters in a repo. */ authorizationRequestParametersRepo.save(parameters); return parameters; } catch (HttpClientErrorException e) { e.printStackTrace(); throw new ShimException("HTTP Error: " + e.getMessage()); } catch (IOException e) { e.printStackTrace(); throw new ShimException("Unable to initiate OAuth1 authorization, could not parse token parameters"); } finally { if (tokenRequest != null) { tokenRequest.releaseConnection(); } } } @Override public AuthorizationResponse handleAuthorizationResponse(HttpServletRequest servletRequest) throws ShimException { // Fetch the access token. String stateKey = servletRequest.getParameter("state"); String requestToken = servletRequest.getParameter(OAuth.OAUTH_TOKEN); final String requestVerifier = servletRequest.getParameter(OAuth.OAUTH_VERIFIER); AuthorizationRequestParameters authParams = authorizationRequestParametersRepo.findByStateKey(stateKey); if (authParams == null) { throw new ShimException("Invalid state, could not find corresponding auth parameters"); } // Get the token secret from the original access request. String requestTokenSecret = authParams.getRequestParams().get(OAuth.OAUTH_TOKEN_SECRET); HttpResponse response; HttpRequestBase accessTokenRequest = null; try { accessTokenRequest = getAccessTokenRequest(getBaseTokenUrl(), requestToken, requestTokenSecret, new HashMap<String, String>() { { put(OAuth.OAUTH_VERIFIER, requestVerifier); } }); response = httpClient.execute(accessTokenRequest); } catch (IOException e) { e.printStackTrace(); throw new ShimException("Could not retrieve response from token URL"); } finally { if (accessTokenRequest != null) { accessTokenRequest.releaseConnection(); } } Map<String, String> accessTokenParameters = OAuth1Utils.parseRequestTokenResponse(response); String accessToken = accessTokenParameters.get(OAuth.OAUTH_TOKEN); String accessTokenSecret = accessTokenParameters.get(OAuth.OAUTH_TOKEN_SECRET); if (accessToken == null) { throw new ShimException("Access token could not be retrieved"); } ApplicationAccessParameters parameters = findApplicationAccessParameters(); AccessParameters accessParameters = new AccessParameters(); accessParameters.setClientId(parameters.getClientId()); accessParameters.setClientSecret(parameters.getClientSecret()); accessParameters.setStateKey(stateKey); accessParameters.setUsername(authParams.getUsername()); accessParameters.setAccessToken(accessToken); accessParameters.setTokenSecret(accessTokenSecret); accessParameters.setAdditionalParameters(new HashMap<String, Object>() { { put(OAuth.OAUTH_VERIFIER, requestVerifier); } }); loadAdditionalAccessParameters(servletRequest, accessParameters); return AuthorizationResponse.authorized(accessParameters); } protected void loadAdditionalAccessParameters(HttpServletRequest request, AccessParameters accessParameters) { //noop, override if additional parameters must be set here } protected HttpRequestBase getSignedRequest(String unsignedUrl, String token, String tokenSecret, Map<String, String> oauthParams) throws ShimException { ApplicationAccessParameters parameters = findApplicationAccessParameters(); return OAuth1Utils.getSignedRequest(unsignedUrl, parameters.getClientId(), parameters.getClientSecret(), token, tokenSecret, oauthParams); } protected URL signUrl(String unsignedUrl, String token, String tokenSecret, Map<String, String> oauthParams) throws ShimException { ApplicationAccessParameters parameters = findApplicationAccessParameters(); return OAuth1Utils.buildSignedUrl(unsignedUrl, parameters.getClientId(), parameters.getClientSecret(), token, tokenSecret, oauthParams); } /** * Some external data providers require POST vs GET. In which case the signing of the requests may differ. * * @param unsignedUrl - The unsigned URL for the request. * @param token - The request token or access token. * @param tokenSecret - The token secret, if any. * @param oauthParams - Any additional Oauth params. * @return - The appropriate request, signed. */ protected HttpRequestBase getRequestTokenRequest(String unsignedUrl, String token, String tokenSecret, Map<String, String> oauthParams) throws ShimException { if (HttpMethod.GET == getRequestTokenMethod()) { return new HttpGet(signUrl(unsignedUrl, token, tokenSecret, oauthParams).toString()); } else { return getSignedRequest(unsignedUrl, token, tokenSecret, oauthParams); } } /** * NOTE: Same as getRequestTokenRequest with difference being that this is for access tokens. * <p> * Some external data providers require POST vs GET. In which case the signing of the requests may differ. * * @param unsignedUrl - The unsigned URL for the request. * @param token - The request token or access token. * @param tokenSecret - The token secret, if any. * @param oauthParams - Any additional Oauth params. * @return - The appropriate request, signed. */ protected HttpRequestBase getAccessTokenRequest(String unsignedUrl, String token, String tokenSecret, Map<String, String> oauthParams) throws ShimException { if (HttpMethod.GET == getAccessTokenMethod()) { return new HttpGet(signUrl(unsignedUrl, token, tokenSecret, oauthParams).toString()); } else { return getSignedRequest(unsignedUrl, token, tokenSecret, oauthParams); } } protected HttpMethod getRequestTokenMethod() { return HttpMethod.GET; } protected HttpMethod getAccessTokenMethod() { return HttpMethod.GET; } }