oAuth SSO on Liferay 6.2 - oauth

I need to integrate on Liferay 6.2 GA6 a SSO from a web application that provide info by oAuth
A native support doesn't exist.
My problem is to create the automatic login on Liferay (after the user creation or if the user already exists). Any help ?

You have to create a hook where you create an AutoLogin class that extends BaseAutoLogin. Read the oAuth documentation and write a login logic in that hook, then set it in auto.login.hooks property in portal-ext.properties(properties reference). Then you will have to create a filter that extends BasePortalFilter and implemets processFilter method. You can model on CASFilter and CASAutologin

override portal.properties adding
auto.login.hooks=com.yourpackage.hook.MyAutoLogin
Create the class:
package com.yourpackage.hook;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.model.User;
import com.liferay.portal.security.auth.AutoLogin;
import com.liferay.portal.security.auth.AutoLoginException;
import com.liferay.portal.service.UserLocalServiceUtil;
import com.liferay.portal.util.PortalUtil;
//based on example
// https://bitbucket.org/brandizzi/liferay-examples/src/a41d71eba8f2fb2d4272a3ce8f393e77cec41d60/unsafe-login-hook/docroot/WEB-INF/src/br/brandizzi/adam/liferay/unsecure/UnsecureAutoLogin.java?at=default&fileviewer=file-view-default
public class MyAutoLogin implements AutoLogin {
#Override
public String[] login(HttpServletRequest request,HttpServletResponse response) throws AutoLoginException {
HttpSession session = request.getSession();
String emailAddress = (String) session.getAttribute("LIFERAY_SHARED_EMAIL");
if (emailAddress == null || emailAddress.isEmpty())
return null;
long companyId = PortalUtil.getCompanyId(request);
User user = null;
try {
user = UserLocalServiceUtil.getUserByEmailAddress(companyId, emailAddress);
} catch (PortalException | SystemException e) {
e.printStackTrace();
}
String redirect = ParamUtil.getString(request, "redirect");
if (Validator.isNotNull(redirect)) {
request.setAttribute(AutoLogin.AUTO_LOGIN_REDIRECT_AND_CONTINUE,PortalUtil.escapeRedirect(redirect));
}
String[] credentials = new String[3];
credentials[0] = String.valueOf(user.getUserId());
credentials[1] = user.getPassword();
credentials[2] = String.valueOf(user.isPasswordEncrypted());
// credentials[2] = Boolean.FALSE.toString();
return credentials;
}
#Override
public String[] handleException(HttpServletRequest arg0,
HttpServletResponse arg1, Exception arg2)
throws AutoLoginException {
System.out.println("AutoLogin handleException ");
return null;
}
}
create an other class with the static methods:
public static JSONObject doSSO(String firstname, String surname, String email, String username,String accessToken, ActionRequest actionRequest, ActionResponse actionResponse){
JSONObject jsonResp = JSONFactoryUtil.createJSONObject();
//Get default Liferay company
String webId = new String("liferay.com");
Company company = null;
try {
company = CompanyLocalServiceUtil.getCompanyByWebId(webId);
} catch (PortalException | SystemException e) {
e.printStackTrace();
}
System.out.println("email "+email);
User currentUser = null;
try {
currentUser = UserLocalServiceUtil.getUserByEmailAddress(company.getCompanyId(), email);
} catch (SystemException | PortalException e) {
System.out.println("User to create");
}
if (Validator.isNull(currentUser)){
long newUserId = 0;
try {
jsonResp = addNewUser( firstname, surname, email, username );
} catch (Exception e) {
e.printStackTrace();
}
String newUserIdS = jsonResp.getString("newUserId");
newUserId = Long.valueOf(newUserIdS);
try {
currentUser = UserLocalServiceUtil.fetchUser(newUserId);
} catch (SystemException e) {
e.printStackTrace();
}
notifyAuthorAboutInvited(email, currentUser);
}
setExistingUserOnSession( actionRequest,currentUser, accessToken);
//Login the user
HttpServletRequest request = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(actionRequest));
HttpServletResponse response = PortalUtil.getHttpServletResponse(actionResponse);
MyAutoLogin myLogin = new MyAutoLogin();
try {
myLogin.login(request, response);
jsonResp.put("message","OK - User logged on Liferay");
} catch (AutoLoginException e1) {
e1.printStackTrace();
}
//set Token on customfield
//remember to set permission guest to view and update
ServiceContext serviceContext = null;
try {
serviceContext = ServiceContextFactory.getInstance(User.class.getName(), actionRequest);
} catch (PortalException | SystemException e) {
e.printStackTrace();
}
Map<String,Serializable> expandoBridgeAttributes = new HashMap<String, Serializable>();
expandoBridgeAttributes.put("token", accessToken);
serviceContext.setExpandoBridgeAttributes(expandoBridgeAttributes);
currentUser.setExpandoBridgeAttributes(serviceContext);
try {
UserLocalServiceUtil.updateUser(currentUser);
} catch (SystemException e) {
e.printStackTrace();
}
String userToken =currentUser.getExpandoBridge().getAttribute("token").toString();
//System.out.println("doSSO accessToken dopo "+userToken);
return jsonResp;
}
and:
private static void setExistingUserOnSession(ActionRequest actionRequest,User user, String accessToken) {
HttpServletRequest req = PortalUtil.getHttpServletRequest(actionRequest);
HttpSession session = req.getSession();
session.setAttribute("LIFERAY_SHARED_EMAIL", user.getEmailAddress());
}

Related

Swagger 2 Feign client code oAuth flow throwing error url values must be not be absolute

I exposed Rest APIs, and I generated client code using Swagger 2 Java language with Feign library. The code gen generated the below OAuth RequestInterceptor. I am getting the below error when I use the oAuth as auth.
Error
feign.RetryableException: url values must be not be absolute.
at com.sam.feign.auth.OAuth.updateAccessToken(OAuth.java:95)
at com.sam.feign.auth.OAuth.apply(OAuth.java:83)
at feign.SynchronousMethodHandler.targetRequest(SynchronousMethodHandler.java:161)
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:110)
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:89)
at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100)
at com.sun.proxy.$Proxy9.getUser(Unknown Source)
at com.sam.feign.clients.UserApiTest.getUserTest(UserApiTest.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: java.lang.IllegalArgumentException: url values must be not be absolute.
at feign.RequestTemplate.uri(RequestTemplate.java:434)
at feign.RequestTemplate.uri(RequestTemplate.java:421)
at feign.RequestTemplate.append(RequestTemplate.java:388)
at com.sam.feign.auth.OAuth$OAuthFeignClient.execute(OAuth.java:163)
at org.apache.oltu.oauth2.client.OAuthClient.accessToken(OAuthClient.java:65)
at org.apache.oltu.oauth2.client.OAuthClient.accessToken(OAuthClient.java:55)
at org.apache.oltu.oauth2.client.OAuthClient.accessToken(OAuthClient.java:71)
at com.sam.feign.auth.OAuth.updateAccessToken(OAuth.java:93)
... 34 more
Swagger Generated oAuth supporting file
public class OAuth implements RequestInterceptor {
static final int MILLIS_PER_SECOND = 1000;
public interface AccessTokenListener {
void notify(BasicOAuthToken token);
}
private volatile String accessToken;
private Long expirationTimeMillis;
private OAuthClient oauthClient;
private TokenRequestBuilder tokenRequestBuilder;
private AuthenticationRequestBuilder authenticationRequestBuilder;
private AccessTokenListener accessTokenListener;
public OAuth(Client client, TokenRequestBuilder requestBuilder) {
this.oauthClient = new OAuthClient(new OAuthFeignClient(client));
this.tokenRequestBuilder = requestBuilder;
}
public OAuth(Client client, OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) {
this(client, OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes));
switch(flow) {
case accessCode:
case implicit:
tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE);
break;
case password:
tokenRequestBuilder.setGrantType(GrantType.PASSWORD);
break;
case application:
tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS);
break;
default:
break;
}
authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl);
}
public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) {
this(new Client.Default(null, null), flow, authorizationUrl, tokenUrl, scopes);
}
#Override
public void apply(RequestTemplate template) {
// If the request already have an authorization (eg. Basic auth), do nothing
if (template.headers().containsKey("Authorization")) {
return;
}
// If first time, get the token
if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) {
updateAccessToken(template);
}
if (getAccessToken() != null) {
template.header("Authorization", "Bearer " + getAccessToken());
}
}
public synchronized void updateAccessToken(RequestTemplate template) {
OAuthJSONAccessTokenResponse accessTokenResponse;
try {
accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage());
} catch (Exception e) {
throw new RetryableException(400, e.getMessage(), template.request().httpMethod(), e, null, template.request());
}
if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) {
setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn());
if (accessTokenListener != null) {
accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken());
}
}
}
public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) {
this.accessTokenListener = accessTokenListener;
}
public synchronized String getAccessToken() {
return accessToken;
}
public synchronized void setAccessToken(String accessToken, Long expiresIn) {
this.accessToken = accessToken;
this.expirationTimeMillis = System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND;
}
public TokenRequestBuilder getTokenRequestBuilder() {
return tokenRequestBuilder;
}
public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) {
this.tokenRequestBuilder = tokenRequestBuilder;
}
public AuthenticationRequestBuilder getAuthenticationRequestBuilder() {
return authenticationRequestBuilder;
}
public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) {
this.authenticationRequestBuilder = authenticationRequestBuilder;
}
public OAuthClient getOauthClient() {
return oauthClient;
}
public void setOauthClient(OAuthClient oauthClient) {
this.oauthClient = oauthClient;
}
public void setOauthClient(Client client) {
this.oauthClient = new OAuthClient( new OAuthFeignClient(client));
}
public static class OAuthFeignClient implements HttpClient {
private Client client;
public OAuthFeignClient() {
this.client = new Client.Default(null, null);
}
public OAuthFeignClient(Client client) {
this.client = client;
}
public <T extends OAuthClientResponse> T execute(OAuthClientRequest request, Map<String, String> headers,
String requestMethod, Class<T> responseClass)
throws OAuthSystemException, OAuthProblemException {
RequestTemplate req = new RequestTemplate()
.append(request.getLocationUri())
.method(requestMethod)
.body(request.getBody());
for (Entry<String, String> entry : headers.entrySet()) {
req.header(entry.getKey(), entry.getValue());
}
Response feignResponse;
String body = "";
try {
feignResponse = client.execute(req.request(), new Options());
body = Util.toString(feignResponse.body().asReader());
} catch (IOException e) {
throw new OAuthSystemException(e);
}
String contentType = null;
Collection<String> contentTypeHeader = feignResponse.headers().get("Content-Type");
if(contentTypeHeader != null) {
contentType = StringUtil.join(contentTypeHeader.toArray(new String[0]), ";");
}
return OAuthClientResponseFactory.createCustomResponse(
body,
contentType,
feignResponse.status(),
responseClass
);
}
public void shutdown() {
// Nothing to do here
}
}
}
ApiClient.java have the below absolute URL which configured in swagger spec
public ApiClient() {
objectMapper = createObjectMapper();
apiAuthorizations = new LinkedHashMap<String, RequestInterceptor>();
feignBuilder = Feign.builder()
.encoder(new FormEncoder(new JacksonEncoder(objectMapper)))
.decoder(new JacksonDecoder(objectMapper))
.logger(new Slf4jLogger());
}
public ApiClient(String[] authNames) {
this();
for(String authName : authNames) {
RequestInterceptor auth = null;
if ("client-credentils-oauth2".equals(authName)) {
auth = new OAuth(OAuthFlow.application, "", "http://localhost:8080/app/oauth/token", "user.create");
} else if ("password-oauth2".equals(authName)) {
auth = new OAuth(OAuthFlow.password, "", "http://localhost:8080/app/oauth/token", "openid");
} else {
throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names");
}
addAuthorization(authName, auth);
}
}
Used the below dependencies
swagger-codegen-maven-plugin v2.4.28
feign-version 11.6
feign-form-version 3.8.0
oltu-version 1.0.1
Java 8
I am invoking the client by using below code
UserApi api = new ApiClient("client-credentils-oauth2","admin", "admin", null, null).buildClient(UserApi.class);
api.getUser(login, tenant)
I made the few changes in the generated oAuth.java file to make it work. Expecting the client generated code should work without making any manual changes.
public <T extends OAuthClientResponse> T execute(OAuthClientRequest request, Map<String, String> headers,
String requestMethod, Class<T> responseClass)
throws OAuthSystemException, OAuthProblemException {
// Added the below 3 lines
URI targetUri = URI.create(uri);
String target = targetUri.getScheme() + "://" + targetUri.getAuthority() ;
String path = targetUri.getPath();
RequestTemplate req = new RequestTemplate()
.uri(path)
.method(requestMethod)
.body(request.getBody())
.target(target); // Added this line
for (Entry<String, String> entry : headers.entrySet()) {
req.header(entry.getKey(), entry.getValue());
}
req = req.resolve(new HashMap<String, Object>()); // Added this line
Response feignResponse;
String body = "";
try {
feignResponse = client.execute(req.request(), new Options());
body = Util.toString(feignResponse.body().asReader());
} catch (IOException e) {
throw new OAuthSystemException(e);
}
String contentType = null;
Collection<String> contentTypeHeader = feignResponse.headers().get("Content-Type");
if(contentTypeHeader != null) {
contentType = StringUtil.join(contentTypeHeader.toArray(new String[0]), ";");
}
return OAuthClientResponseFactory.createCustomResponse(
body,
contentType,
feignResponse.status(),
responseClass
);
}
Appreciate if someone can assist me with this issue

To verify a JWT token with RSA

I am trying to verify a jwt token and getting the exception: Exception in thread "main" java.lang.IllegalArgumentException: Only private key data is currently supported
Any pointers on how to verify a jwt token with public key?
import org.springframework.security.jwt.JwtHelper;
public boolean verify(String jwtToken) {
ResponseEntity<JwtKey> response = restTemplate.getForEntity(tokenKey, JwtKey.class);
JwtKey jwtKey = response.getBody();
Jwt decode = JwtHelper.decode(jwtToken);
System.out.println(decode);
System.out.println(decode.getClaims());
JwtHelper.decodeAndVerify(jwtToken, new RsaVerifier(jwtKey.getValue()));
return true;
}
Finally, I went with the below solution.
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.RsaVerifier;
import org.apache.commons.lang.StringUtils;
public boolean verify(String jwtToken) {
JWTKey jwtKey = restTemplateManager.getTokenPublicKey();
try {
JwtHelper.decodeAndVerify(jwtToken, new RsaVerifier(getRSAPublicKey(jwtKey.getValue())));
} catch (Exception e) {
logger.error("Error in verifying token{}", e);
return false;
}
return true;
}
private RSAPublicKey getRSAPublicKey(String publicKey) {
if( StringUtils.isBlank(publicKey)) return null;
publicKey = sanitaize(publicKey);
try {
KeyFactory keyFactory = java.security.KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(java.util.Base64.getDecoder().decode(publicKey));
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
logger.error("Error forming RSA key {}", e);
throw new GatewayException(e);
}
}
Create a RsaVerifier with public key:
#Bean RsaVerifier rsaVerifier(){
Resource resource = new ClassPathResource(pubKeyFilename);
try {
String pubKey = IOUtils.toString(resource.getInputStream(), "UTF-8");
return new RsaVerifier(pubKey);
} catch (final IOException e) {
throw new Exception("Cannot get public key to check JWT",e);
}
}
Use it when you want to decode:
Jwt jwt = JwtHelper.decodeAndVerify(token, rsaVerifier());

Posting to HTTPS in Java

I want to post to an url https://host:0101 with a request body. I have done this with non-ssl, http, but having trouble with https.
I have both the trust store (JKS) and keystore (PKCS12)'s full path, and their passwords as properties in a .properties file.
What i have to far is:
public sendPost () throws Exception {
SSLContext sslContext = getContext();
SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient client = HttpClients.custom().setSSLSocketFactory(factory).build();
HttpPost post = new HttpPost("https://host:0101/post");
StringEntity entity = new StringEntity(jsonData);
post.setEntity(entity);
response=client.execute(request);
responseCode = response.getStatusLine().getStatusCode();
}
public SSLContext getContext() throws Exception {
KeyStore keyStore = KeyStore.getInstance("JKS");
FileInputStream instream = new FileInputStream(new File(PATH_TO_KEYSTORE));
try {
keyStore.load(instream, "password".toCharArray());
}finally {instream.close()}
return SSLContexts.custom().loadTrustMaterial(keyStore).build();
}
I am testing this by running a Junit test just to verify that it works before deploying.
#Test
public void test() throws Exception {
int responseCode = entityUnderTest.sendPost();
assertEquals(200, responseCode);
}
The error is at line: response=client.execute(request); with the HttpHostConnectException
Failed: Connection Refused
Is the service available through HTTPS? The connection refused error occurs when there is some problem with the availability of your service.
This could be caused by a lot of problems:
your service is not running
your service is not available through HTTPS
a proxy/routing error (does your test system reach the host and port?)
If there was a problem with the authentication you would get a different message (eg: SSLPeerUnverifiedException, SSLHandshakeException).
This is working for me.. try it
Here is the post method
public static CookieManager msCookieManager = null;
private boolean isPinBuild=false;
public static String[] post(Context context, String Url, List<NameValuePair> values, List<NameValuePair> header_list)
throws ConnectTimeoutException {
String[] result = { "", "" };
try {
URL url = new URL(Url);
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
Log.i("TAG_URL : ", Url);
if (isPinBuild) {
KeyPinStore keystore = KeyPinStore.getInstance(context);
javax.net.ssl.SSLSocketFactory factory = keystore.getContext().getSocketFactory();
SSLSocket socket = (SSLSocket)factory.createSocket();
socket.setEnabledCipherSuites(new String[]{"RC4-MD5", "DES-CBC-SHA", "DES-CBC3-SHA"});
socket.setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
socket.setSoTimeout(60000);
urlConnection.setSSLSocketFactory(factory);
} else {
KeyUnPinStore keystore = KeyUnPinStore.getInstance(context);
javax.net.ssl.SSLSocketFactory factory = keystore.getContext().getSocketFactory();
SSLSocket socket = (SSLSocket)factory.createSocket();
socket.setEnabledCipherSuites(new String[]{"RC4-MD5", "DES-CBC-SHA", "DES-CBC3-SHA"});
socket.setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
socket.setSoTimeout(60000);
urlConnection.setSSLSocketFactory(factory);
}
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.STRICT_HOSTNAME_VERIFIER;
urlConnection.setRequestMethod("POST");
urlConnection.setConnectTimeout(connection_timeout);
urlConnection.setHostnameVerifier(hostnameVerifier);
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
for (NameValuePair header : header_list) {
urlConnection.addRequestProperty(header.getName(), header.getValue());
}
if (msCookieManager == null) {
msCookieManager = new CookieManager();
}
if (msCookieManager != null && msCookieManager.getCookieStore().getCookies().size() > 0) {
urlConnection.setRequestProperty(COOKIE, TextUtils.join(";", msCookieManager.getCookieStore().getCookies()));
}
Log.i("TAG_POST_COOKIE : ", msCookieManager.getCookieStore().getCookies().toString());
String postData = "";
for (NameValuePair value : values) {
postData = postData + value.getName() + "=" + URLEncoder.encode(value.getValue(), "UTF-8") + "&";
}
if (!TextUtils.isEmpty(postData) && postData.length() > 2) {
postData = postData.substring(0, postData.length() - 1);
}
Log.i("TAG_POSTDATA : ", postData);
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setFixedLengthStreamingMode(postData.getBytes().length);
PrintWriter out = new PrintWriter(urlConnection.getOutputStream());
out.print(postData);
out.close();
// always check HTTP response code first
int responseCode = urlConnection.getResponseCode();
result[0] = responseCode + "";
if (responseCode == HttpURLConnection.HTTP_OK) {
// Get Response
InputStream is = urlConnection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
while ((line = rd.readLine()) != null) {
response.append(line);
response.append('\r');
}
rd.close();
Map<String, List<String>> headerFields = urlConnection.getHeaderFields();
List<String> cookiesHeader = headerFields.get(COOKIES_HEADER);
/*if (cookiesHeader != null) {
for (String cookie : cookiesHeader) {
if (HttpCookie.parse(cookie).get(0).toString().contains(JSESSIONID)) {
msCookieManager.getCookieStore().add(null, HttpCookie.parse(cookie).get(0));
}
}
}*/
if (!TextUtils.isEmpty(response)) {
result[0] = HttpConnectionUrl.RESPONSECODE_REQUESTSUCCESS;
result[1] = response.toString();
Log.i("TAG_RESPONSE : ", result[1]);
}
}
} catch (UnsupportedEncodingException e) {
result[0] = HttpConnectionUrl.RESPONSECODE_CONNECTIONTIMEOUT;
e.printStackTrace();
} catch (ClientProtocolException e) {
result[0] = HttpConnectionUrl.RESPONSECODE_CONNECTIONTIMEOUT;
e.printStackTrace();
} catch (ConnectTimeoutException e) {
result[0] = HttpConnectionUrl.RESPONSECODE_CONNECTIONTIMEOUT;
e.printStackTrace();
} catch (IOException e) {
result[0] = HttpConnectionUrl.RESPONSECODE_CONNECTIONTIMEOUT;
e.printStackTrace();
} catch (Exception e) {
result[0] = HttpConnectionUrl.RESPONSECODE_CONNECTIONTIMEOUT;
e.printStackTrace();
}
return result;
}
here isPinBuild variable use for you have any certificate file or not. If you use any trusted certificate then set true.
Here the KeyPinStore class
public class KeyPinStore {
private static Context context = null;
private static KeyPinStore instance = null;
private SSLContext sslContext = SSLContext.getInstance("SSLv3");
//private SSLContext sslContext = SSLContext.getInstance("TLS");
public static synchronized KeyPinStore getInstance(Context mContext) throws CertificateException, IOException, KeyStoreException,
NoSuchAlgorithmException, KeyManagementException {
if (instance == null) {
context = mContext;
instance = new KeyPinStore();
}
return instance;
}
private KeyPinStore() throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// randomCA.crt should be in the Assets directory
InputStream caInput = new BufferedInputStream(context.getAssets().open("yourCertificate.crt"));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
// SSLContext context = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
}
public SSLContext getContext() {
return sslContext;
}
}
and KeyUnpinStore class
public class KeyUnPinStore {
private static Context context = null;
private static KeyUnPinStore instance = null;
private SSLContext sslContext = SSLContext.getInstance("TLS");
public static synchronized KeyUnPinStore getInstance(Context mContext) throws CertificateException, IOException, KeyStoreException,
NoSuchAlgorithmException, KeyManagementException {
if (instance == null) {
context = mContext;
instance = new KeyUnPinStore();
}
return instance;
}
private KeyUnPinStore() throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} };
// Create all-trusting host name verifier
// Create an SSLContext that uses our TrustManager
// SSLContext context = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
}
public SSLContext getContext() {
return sslContext;
}
}
Why don't you try using httpbin? It's an external resource that's guaranteed to work. For example:
import java.io.IOException;
import java.net.URI;
import net.minidev.json.JSONObject;
import net.minidev.json.JSONValue;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
public class Post {
public static void main(String[] args) throws Exception {
HttpClient client = new DefaultHttpClient();
int result = post(client, new URI("https://httpbin.org/post"), (JSONObject)JSONValue.parse("{'answer':42}"));
System.err.println(result);
}
public static int post(HttpClient httpClient, URI url, JSONObject content) throws IOException {
final HttpPost post = new HttpPost(url);
post.addHeader("Content-type", ContentType.APPLICATION_JSON.getMimeType());
post.setEntity(new StringEntity(content.toString(), ContentType.APPLICATION_JSON));
final HttpResponse response = httpClient.execute(post);
EntityUtils.consumeQuietly(response.getEntity());
return response.getStatusLine().getStatusCode();
}
}
Assuming that you have generated public/private keypairs using java "keytool" and both trustStore & keyStores are configured properly at client-side & in HOST container(in case of Tomcat server.xml).
In Method:"sendPost()", you may like to get SSL-Connection as follows:
try {
String endpoint="https://host:0101/post";
URL url = new URL(endpoint);
HttpsURLConnection conn = getConnection(url, "POST", uname, passwd);
conn.connect();
writeBody(conn);
catch(Exception e) { throw new RuntimeException(e); }
conn.disconnect();
}
catch(Exception e) { throw new RuntimeException(e); }
private void writeBody(HttpsURLConnection conn) {
try {
String pairs = "who=Freddy&what=Avoid Friday nights if possible.";
OutputStream out = conn.getOutputStream();
out.write(pairs.getBytes());
out.flush();
}
catch(Exception e) { throw new RuntimeException(e); }
}

Spring websocket messaging template isn't publishing data from Controller without #Scheduler annotation

#Controller
public class WebServiceController {
private static Logger logger = LoggerFactory.getLogger(WebServiceController.class.getName());
#Autowired
private SimpMessagingTemplate template;
public static Response response;
private final MessageSendingOperations<String> messagingTemplate;
#Autowired
private XmlCommandFactory xmlCommandFactory;
#Autowired
public WebServiceController(final MessageSendingOperations<String> messagingTemplate) {
this.messagingTemplate = messagingTemplate;
}
#RequestMapping(value = "/handleResponse.htm/{sessionId}")
public void handleRequest(final HttpServletRequest request, final HttpServletResponse httpResponse,
#PathVariable final String sessionId) throws Exception {
httpResponse.setStatus(200);
final StringBuilder buffer = new StringBuilder();
final BufferedReader reader = request.getReader();
String line = null;
while ((line = reader.readLine()) != null) {
buffer.append(line.trim());
}
if (!buffer.toString().isEmpty()) {
try {
response = xmlCommandFactory.createCommand(buffer.toString(), sessionId);
publishData();
} catch (final Exception ex) {
logger.warn(" Error while processing response ", ex);
}
}
}
#Scheduled(fixedDelay = 2000)
public void publishData() {
try {
if (null != response && !response.getData().isEmpty()) {
this.messagingTemplate.convertAndSend("/update/config/" + response.getSessionId(), response);
}
} catch (final Exception e) {
logger.warn("exception " + e);
}
}
The above code publishes data to the UI at the scheduled delay. But if I comment out #Scheduler annotation and call this method from handleRequest, it doesn't publish data to UI. What could be the reason?

Which Google api to use for getting user's first name, last name, picture, etc?

I have the oauth authorization with google working correctly and am getting data from the contacts api. Now, I want to programmatically get a gmail user's first name, last name and picture. Which google api can i use to get this data?
The contacts API perhaps works, but you have to request permission from the user to access all contacts. If I were a user, that would make me wary of granting the permission (because this essentially gives you permission to spam all my contacts...)
I found the response here to be useful, and only asks for "basic profile information":
Get user info via Google API
I have successfully used this approach, and can confirm it returns the following Json object:
{
"id": "..."
"email": "...",
"verified_email": true,
"name": "....",
"given_name": "...",
"family_name": "...",
"link": "...",
"picture": "...",
"gender": "male",
"locale": "en"
}
Use this code to get firstName and lastName of a google user:
final HttpTransport transport = new NetHttpTransport();
final JsonFactory jsonFactory = new JacksonFactory();
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
.setAudience(Arrays.asList(clientId))
.setIssuer("https://accounts.google.com")
.build();
GoogleIdToken idToken = null;
try {
idToken = verifier.verify(googleAuthenticationPostResponse.getId_token());
} catch (GeneralSecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
GoogleIdToken.Payload payload = null;
if (idToken != null) {
payload = idToken.getPayload();
}
String firstName = payload.get("given_name").toString();
String lastName = payload.get("family_name").toString();
If you're using the google javascript API, you can use the new "auth2" API after authenticating to get the user's profile, containing:
name
email
image URL
https://developers.google.com/identity/sign-in/web/reference#googleusergetbasicprofile
For the picture, you can use the Google contacts Data API too: see http://code.google.com/intl/fr/apis/contacts/docs/3.0/developers_guide_protocol.html#retrieving_photo
The simplest way to get this information would be from the Google + API. Specifically the
https://developers.google.com/+/api/latest/people/get
When using the api use the following HTTP GET:
GET https://www.googleapis.com/plus/v1/people/me
This will return all of the above information requested from the user.
I found the answer while looking around in the contacts API forum. When you get the result-feed, just do the following in Java-
String Name = resultFeed.getAuthors().get(0).getName();
String emailId = resultFeed.getId();
I am still looking for a way to get the user profile picture.
Use this Code for Access Google Gmail Login Credential oAuth2 :
Class Name : OAuthHelper
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map.Entry;
import java.util.SortedSet;
import oauth.signpost.OAuth;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthProvider;
import oauth.signpost.commonshttp.HttpRequestAdapter;
import oauth.signpost.exception.OAuthCommunicationException;
import oauth.signpost.exception.OAuthExpectationFailedException;
import oauth.signpost.exception.OAuthMessageSignerException;
import oauth.signpost.exception.OAuthNotAuthorizedException;
import oauth.signpost.http.HttpParameters;
import oauth.signpost.signature.HmacSha1MessageSigner;
import oauth.signpost.signature.OAuthMessageSigner;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.util.Log;
public class OAuthHelper {
private static final String TAG = "OAuthHelper";
private OAuthConsumer mConsumer;
private OAuthProvider mProvider;
private String mCallbackUrl;
public OAuthHelper(String consumerKey, String consumerSecret, String scope, String callbackUrl) throws UnsupportedEncodingException {
mConsumer = new CommonsHttpOAuthConsumer(consumerKey, consumerSecret);
mProvider = new CommonsHttpOAuthProvider("https://www.google.com/accounts/OAuthGetRequestToken?scope=" + URLEncoder.encode(scope, "utf-8"), "https://www.google.com/accounts/OAuthGetAccessToken", "https://www.google.com/accounts/OAuthAuthorizeToken?hd=default");
mProvider.setOAuth10a(true);
mCallbackUrl = (callbackUrl == null ? OAuth.OUT_OF_BAND : callbackUrl);
}
public String getRequestToken() throws OAuthMessageSignerException, OAuthNotAuthorizedException, OAuthExpectationFailedException, OAuthCommunicationException {
String authUrl = mProvider.retrieveRequestToken(mConsumer, mCallbackUrl);
System.out.println("Gautam AUTH URL : " + authUrl);
return authUrl;
}
public String[] getAccessToken(String verifier) throws OAuthMessageSignerException, OAuthNotAuthorizedException, OAuthExpectationFailedException, OAuthCommunicationException {
mProvider.retrieveAccessToken(mConsumer, verifier);
return new String[] { mConsumer.getToken(), mConsumer.getTokenSecret() };
}
public String[] getToken() {
return new String[] { mConsumer.getToken(), mConsumer.getTokenSecret() };
}
public void setToken(String token, String secret) {
mConsumer.setTokenWithSecret(token, secret);
}
public String getUrlContent(String url) throws OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException, IOException {
HttpGet request = new HttpGet(url);
// sign the request
mConsumer.sign(request);
// send the request
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
// get content
BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null)
sb.append(line + NL);
in.close();
System.out.println("gautam INFO : " + sb.toString());
return sb.toString();
}
public String getUserProfile(String t0, String t1, String url) {
try {
OAuthConsumer consumer = new CommonsHttpOAuthConsumer(t0, t1);
HttpGet request = new HttpGet(url);
// sign the request
consumer.sign(request);
// send the request
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
//String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null)
sb.append(line );
in.close();
System.out.println("Gautam Profile : " + sb.toString());
return sb.toString();
} catch (Exception e) {
System.out.println("Error in Geting profile Info : " + e);
return "";
}
}
public String buildXOAuth(String email) {
String url = String.format("https://mail.google.com/mail/b/%s/smtp/", email);
HttpRequestAdapter request = new HttpRequestAdapter(new HttpGet(url));
// Sign the request, the consumer will add any missing parameters
try {
mConsumer.sign(request);
} catch (OAuthMessageSignerException e) {
Log.e(TAG, "failed to sign xoauth http request " + e);
return null;
} catch (OAuthExpectationFailedException e) {
Log.e(TAG, "failed to sign xoauth http request " + e);
return null;
} catch (OAuthCommunicationException e) {
Log.e(TAG, "failed to sign xoauth http request " + e);
return null;
}
HttpParameters params = mConsumer.getRequestParameters();
// Since signpost doesn't put the signature into params,
// we've got to create it again.
OAuthMessageSigner signer = new HmacSha1MessageSigner();
signer.setConsumerSecret(mConsumer.getConsumerSecret());
signer.setTokenSecret(mConsumer.getTokenSecret());
String signature;
try {
signature = signer.sign(request, params);
} catch (OAuthMessageSignerException e) {
Log.e(TAG, "invalid oauth request or parameters " + e);
return null;
}
params.put(OAuth.OAUTH_SIGNATURE, OAuth.percentEncode(signature));
StringBuilder sb = new StringBuilder();
sb.append("GET ");
sb.append(url);
sb.append(" ");
int i = 0;
for (Entry<String, SortedSet<String>> entry : params.entrySet()) {
String key = entry.getKey();
String value = entry.getValue().first();
int size = entry.getValue().size();
if (size != 1)
Log.d(TAG, "warning: " + key + " has " + size + " values");
if (i++ != 0)
sb.append(",");
sb.append(key);
sb.append("=\"");
sb.append(value);
sb.append("\"");
}
Log.d(TAG, "xoauth encoding " + sb);
Base64 base64 = new Base64();
try {
byte[] buf = base64.encode(sb.toString().getBytes("utf-8"));
return new String(buf, "utf-8");
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "invalid string " + sb);
}
return null;
}
}
//===================================
Create : WebViewActivity.class
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.Window;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class WebViewActivity extends Activity {
//WebView webview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_PROGRESS);
WebView webview = new WebView(this);
webview.getSettings().setJavaScriptEnabled(true);
setContentView(webview);
// Load the page
Intent intent = getIntent();
if (intent.getData() != null) {
webview.loadUrl(intent.getDataString());
}
webview.setWebChromeClient(new WebChromeClient() {
// Show loading progress in activity's title bar.
#Override
public void onProgressChanged(WebView view, int progress) {
setProgress(progress * 100);
}
});
webview.setWebViewClient(new WebViewClient() {
// When start to load page, show url in activity's title bar
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
setTitle(url);
if (url.startsWith("my-activity")) {
Intent result = new Intent();
System.out.println("Gautam my-activity : " + url);
result.putExtra("myurl", url);
setResult(RESULT_OK, result);
finish();
}
}
#Override
public void onPageFinished(WebView view, String url) {
System.out.println("Gautam Page Finish...");
CookieSyncManager.getInstance().sync();
// Get the cookie from cookie jar.
String cookie = CookieManager.getInstance().getCookie(url);
System.out.println("Gautam Cookie : " + cookie);
if (cookie == null) {
return;
}
// Cookie is a string like NAME=VALUE [; NAME=VALUE]
String[] pairs = cookie.split(";");
for (int i = 0; i < pairs.length; ++i) {
String[] parts = pairs[i].split("=", 2);
// If token is found, return it to the calling activity.
System.out.println("Gautam=> "+ parts[0] + " = " + parts[1]);
if (parts.length == 2 && parts[0].equalsIgnoreCase("oauth_token")) {
Intent result = new Intent();
System.out.println("Gautam AUTH : " + parts[1]);
result.putExtra("token", parts[1]);
setResult(RESULT_OK, result);
finish();
}
}
}
});
}
}
//=========================
Call From : MainActivity.class
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.http.HttpResponse;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener{
Button btnLogin;
OAuthHelper MyOuthHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnLogin = (Button)findViewById(R.id.btnLogin);
btnLogin.setOnClickListener(this);
}
#Override
protected void onResume() {
/*System.out.println("On Resume call ");
try {
String[] token = getVerifier();
if (token != null){
String accessToken[] = MyOuthHelper.getAccessToken(token[1]);
}
} catch (Exception e) {
System.out.println("gautam error on Resume : " + e);
}*/
super.onResume();
}
private String[] getVerifier(String url) {
// extract the token if it exists
Uri uri = Uri.parse(url);
if (uri == null) {
return null;
}
String token = uri.getQueryParameter("oauth_token");
String verifier = uri.getQueryParameter("oauth_verifier");
return new String[] { token, verifier };
}
#Override
public void onClick(View v) {
try {
MyOuthHelper = new OAuthHelper("YOUR CLIENT ID", "YOUR SECRET KEY", "https://www.googleapis.com/auth/userinfo.profile", "my-activity://localhost");
} catch (Exception e) {
System.out.println("gautam errorin Class call : " + e);
}
try {
String uri = MyOuthHelper.getRequestToken();
Intent intent = new Intent(MainActivity.this, WebViewActivity.class);
intent.setData(Uri.parse(uri));
startActivityForResult(intent, 0);
/* startActivity(new Intent("android.intent.action.VIEW",
Uri.parse(uri)));*/
} catch (Exception e) {
System.out.println("Gautm Error in getRequestTokan : " + e);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 0:
if (resultCode != RESULT_OK || data == null) {
return;
}
// Get the token.
String url = data.getStringExtra("myurl");
try {
String[] token = getVerifier(url);
if (token != null){
String accessToken[] = MyOuthHelper.getAccessToken(token[1]);
System.out.println("Gautam Final [0] : " + accessToken[0] + " , [1] : " + accessToken[1]);
//https://www.googleapis.com/oauth2/v1/userinfo?alt=json
// String myProfile = MyOuthHelper.getUserProfile(accessToken[0], accessToken[1], "https://www.googleapis.com/oauth2/v1/userinfo?alt=json");
String myProfile = MyOuthHelper.getUrlContent("https://www.googleapis.com/oauth2/v1/userinfo?alt=json");
}
} catch (Exception e) {
System.out.println("gautam error on Resume : " + e);
}
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
}
//=================================
And Finally Your Profile Information coming, Just Look in your Logcat message print.
Note : Not Forgot to put Internet Permission in Manifest File
And Your App Register in Google Console for Client ID and Secret Key
For App Registration Please Looking this Step : App Registration Step

Resources