Package com.baasbox.service.sociallogin

Source Code of com.baasbox.service.sociallogin.SocialLoginService$Tokens

/*
* Copyright (c) 2014.
*
* BaasBox - info-at-baasbox.com
*
* 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 com.baasbox.service.sociallogin;

import java.io.IOException;
import java.io.Serializable;

import org.apache.commons.lang.StringUtils;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
import org.scribe.builder.ServiceBuilder;
import org.scribe.builder.api.Api;
import org.scribe.model.OAuthRequest;
import org.scribe.model.Response;
import org.scribe.model.Token;
import org.scribe.model.Verifier;
import org.scribe.oauth.OAuthService;

import play.Logger;
import play.cache.Cache;
import play.mvc.Http.Request;
import play.mvc.Http.Session;

import com.baasbox.BBConfiguration;
import com.baasbox.configuration.Application;
import com.baasbox.configuration.SocialLoginConfiguration;
import com.baasbox.db.DbHelper;
import com.baasbox.exception.InvalidAppCodeException;
import com.orientechnologies.orient.core.db.record.ODatabaseRecordTx;

public abstract class SocialLoginService {

  private static final String PROTOCOL = "http://";
  private static final String SECURE_PROTOCOL = "https://";
  private static final String DEFAULT_HOST = "localhost";
  private static final String DEFAULT_PORT = "9000";

  protected OAuthService service;


  public OAuthService getService() {
    return service;
  }

  protected Tokens token;
  protected String socialNetwork;
  protected String appcode;
  public abstract Class<? extends Api> provider();
  public abstract Boolean needToken();
  public abstract String userInfoUrl();

  public abstract String getVerifierFromRequest(Request r);
  public abstract Token getAccessTokenFromRequest(Request r,Session s);


  public void build(){
    StringBuilder serverUrl = new StringBuilder();
    //since this method can be called by the /callback endpoint that does not open a DB connection, we need to manage it here
    try{
      DbHelper.getOrOpenConnectionWIthHTTPUsername();   
      Boolean isSSL = (Boolean)Application.NETWORK_HTTP_SSL.getValueAsBoolean();
      if(isSSL){
        serverUrl.append(SECURE_PROTOCOL);
      }else{
        serverUrl.append(PROTOCOL);
      }
      String serverName = Application.NETWORK_HTTP_URL.getValueAsString();
      serverUrl.append(serverName!=null?serverName:DEFAULT_HOST);
      String serverPort = Application.NETWORK_HTTP_PORT.getValueAsString();
      serverUrl.append(serverPort!=null?":"+serverPort:":"+DEFAULT_PORT);
      this.service = new ServiceBuilder().
          provider(provider())
          .apiKey(this.token.getToken())
          .apiSecret(this.token.getSecret())
          .callback(serverUrl.toString()+"/login/"+socialNetwork+"/callback")
          .build();
    }catch(InvalidAppCodeException iace){
      throw new RuntimeException(iace);
    }

  }

  public SocialLoginService(String socialNetwork,String appcode){
    this.socialNetwork = socialNetwork;
    this.appcode = appcode;
    this.token = getTokens();
    build();
  }

  public String getAuthorizationURL(Session s){
    Token t = null;
    if(this.needToken()){
      t = this.service.getRequestToken();
      if(this.socialNetwork.equals("twitter")){
        if (Logger.isDebugEnabled()) Logger.debug("setting token");
        s.put("twitter.token",t.getToken());
        s.put("twitter.secret",t.getSecret());
      }
    }
    return this.service.getAuthorizationUrl(t);
  }

  public Token requestAccessToken(Request r,Session s){
    Token t = getAccessTokenFromRequest(r,s);
    Verifier v = new Verifier(getVerifierFromRequest(r));
    return this.service.getAccessToken(t, v);
  }

  public UserInfo getUserInfo(Token accessToken) throws BaasBoxSocialException{

    OAuthRequest request = buildOauthRequestForUserInfo(accessToken);

    this.service.signRequest(accessToken, request);
    Response response = request.send();
    return extractUserInfo(response);
  }

  protected abstract OAuthRequest buildOauthRequestForUserInfo(Token accessToken);

  public boolean isClientEnabled(){
    String keyFormat = socialNetwork.toUpperCase()+"_ENABLED";
    Boolean enabled = SocialLoginConfiguration.valueOf(keyFormat).getValueAsBoolean();
    return enabled == null ? false : enabled;
  }

  public  Tokens getTokens() throws UnsupportedSocialNetworkException{
    //since this method can be called by the /callback endpoint that does not open a DB connection, we need to manage it here
    if (BBConfiguration.getSocialMock())  return new Tokens("fake_token","fake_secret");
    ODatabaseRecordTx db=null;
    try {
      db = DbHelper.getOrOpenConnection(BBConfiguration.getAPPCODE(), BBConfiguration.getBaasBoxUsername(), BBConfiguration.getBaasBoxPassword());   
      String keyFormat = socialNetwork.toUpperCase()+"_TOKEN";
      String token = (String)Cache.get(keyFormat);
      if(token ==null){
        token = SocialLoginConfiguration.valueOf(keyFormat).getValueAsString();
        Cache.set(keyFormat,token,0);
      }
      keyFormat =  socialNetwork.toUpperCase()+"_SECRET";
      String secret =  (String)Cache.get(keyFormat);;
      if(secret ==null){
        secret = SocialLoginConfiguration.valueOf(keyFormat).getValueAsString();
        Cache.set(keyFormat,secret,0);
      }
      if(secret==null || token == null){
        throw new UnsupportedSocialNetworkException("Social login for "+socialNetwork+" is not enabled.Please add app token and secret to configuration");
      }
      return new Tokens(token,secret);
    } catch (InvalidAppCodeException e) {
      //a very strange thing happened here!
      throw new RuntimeException(e);
    }finally{
      if (db!=null && !db.isClosed()) db.close();
    }
  }

  public static class Tokens implements Serializable{
    private String token;
    private String secret;

    public Tokens(String token,String secret){
      assert(!(StringUtils.isEmpty(token) || StringUtils.isEmpty(secret)));

      this.token = token;
      this.secret = secret;
    }

    public String getToken() {
      return token;
    }

    public String getSecret() {
      return secret;
    }

    public String toString(){
      return "Tokens:{token:"+this.token+",secret:"+this.secret+"}";
    }

  }

  public abstract  UserInfo extractUserInfo(Response r) throws BaasBoxSocialException;

  public static SocialLoginService by(String socialNetwork,String appcode) {
    if (BBConfiguration.getSocialMock()) return new SocialLoginServiceMock(socialNetwork,appcode);

    if(socialNetwork.equals("facebook")){
      return new FacebookLoginService(appcode);
    }else if(socialNetwork.equals("github")){
      return new GithubLoginService(appcode);
    }else if(socialNetwork.equals("google")){
      return new GooglePlusLoginService(appcode);
    }

    return null;
  }

  public abstract String getPrefix();
  protected abstract String getValidationURL(String token);

  public boolean validationRequest(String token) throws BaasBoxSocialTokenValidationException{
    String url = getValidationURL(token);
    HttpClient client = new DefaultHttpClient();
    HttpGet method = new HttpGet(url);

    BasicResponseHandler brh = new BasicResponseHandler();

    String body;
    try {
      body = client.execute(method,brh);

      if(StringUtils.isEmpty(body)){
        return false;
      }else{
        ObjectMapper mapper = new ObjectMapper();
        JsonFactory factory = mapper.getJsonFactory(); // since 2.1 use mapper.getFactory() instead
        JsonParser jp = factory.createJsonParser(body);
        JsonNode jn = mapper.readTree(jp);
        return validate(jn);
      }
    } catch (IOException e) {
      throw new BaasBoxSocialTokenValidationException("There was an error in the token validation process:"+e.getMessage());
    }

  }

  protected abstract boolean validate(Object response);


  public  String getPrefixByName(String from) {
    if(from.equals("facebook")){
      return FacebookLoginService.PREFIX;
    }else if(socialNetwork.equals("github")){
      return GithubLoginService.PREFIX;
    }else if(socialNetwork.equals("google")){
      return GooglePlusLoginService.PREFIX;
    }
    throw new InvalidSocialNetworkNameException(from);
  }



}
TOP

Related Classes of com.baasbox.service.sociallogin.SocialLoginService$Tokens

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.