Last active
August 29, 2015 14:21
-
-
Save Kozlov-V/f92756a7fb59b5f31ff3 to your computer and use it in GitHub Desktop.
CrossClient
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Arrays; | |
import java.util.List; | |
import com.google.android.gms.auth.GoogleAuthUtil; | |
import com.google.android.gms.auth.UserRecoverableAuthException; | |
import com.google.android.gms.common.AccountPicker; | |
import android.support.v7.app.ActionBarActivity; | |
import android.text.TextUtils; | |
import android.accounts.AccountManager; | |
import android.content.Intent; | |
import android.os.AsyncTask; | |
import android.os.Bundle; | |
import android.util.Log; | |
import android.view.Menu; | |
import android.view.MenuItem; | |
import android.view.View; | |
import android.widget.Button; | |
import android.widget.EditText; | |
import android.widget.Toast; | |
public class MainActivity extends ActionBarActivity { | |
final private String CLIENT_ID = "12345----.apps.googleusercontent.com"; | |
static final int REQUEST_CODE_PICK_ACCOUNT = 1000; | |
private String mEmail; | |
//private static final String SCOPE = | |
// "oauth2:https://www.googleapis.com/auth/userinfo.profile"; | |
final private List<String> SCOPES = Arrays.asList(new String[]{ | |
"https://www.googleapis.com/auth/plus.login", | |
"https://www.googleapis.com/auth/youtube"}); | |
private EditText mExchangeCodeEditText; | |
private EditText mIdTokenEditText; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
mExchangeCodeEditText = (EditText) findViewById(R.id.editTextExchangeCode); | |
mIdTokenEditText = (EditText) findViewById(R.id.editTextIdToken); | |
Button b1=(Button) findViewById(R.id.button1); | |
b1.setOnClickListener(new View.OnClickListener(){ | |
@Override | |
public void onClick(View v) { | |
// TODO Auto-generated method stub | |
// static final int REQUEST_CODE_PICK_ACCOUNT = 1000; | |
String[] accountTypes = new String[]{"com.google"}; | |
Intent intent = AccountPicker.newChooseAccountIntent(null, null, | |
accountTypes, false, null, null, null, null); | |
startActivityForResult(intent, REQUEST_CODE_PICK_ACCOUNT); | |
} | |
}); | |
} | |
@Override | |
public boolean onCreateOptionsMenu(Menu menu) { | |
// Inflate the menu; this adds items to the action bar if it is present. | |
getMenuInflater().inflate(R.menu.main, menu); | |
return true; | |
} | |
@Override public boolean onOptionsItemSelected(MenuItem item) { | |
// Handle action bar item clicks here. The action bar will | |
// automatically handle clicks on the Home/Up button, so long | |
// as you specify a parent activity in AndroidManifest.xml. | |
int id = item.getItemId(); | |
if (id == R.id.action_settings) { | |
return true; | |
} | |
return super.onOptionsItemSelected(item); | |
} | |
@Override | |
protected void onActivityResult(int requestCode, int resultCode, Intent data) { | |
if (requestCode == REQUEST_CODE_PICK_ACCOUNT) { | |
// Receiving a result from the AccountPicker | |
if (resultCode == RESULT_OK) { | |
mEmail = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); | |
// With the account name acquired, go get the auth token | |
// getUsername(); | |
Log.v("MY_UNAME",mEmail); | |
new RetrieveJwtAsyncTask().execute(); | |
new RetrieveExchangeCodeAsyncTask().execute(); | |
} else if (resultCode == RESULT_CANCELED) { | |
// The account picker dialog closed without selecting an account. | |
// Notify users that they must pick an account to proceed. | |
Toast.makeText(this, R.string.pick_account, Toast.LENGTH_SHORT).show(); | |
} | |
} | |
// Later, more code will go here to handle the result from some exceptions... | |
} | |
public class RetrieveJwtAsyncTask | |
extends AsyncTask<Void, Boolean, String> { | |
@Override | |
protected String doInBackground(Void... params) { | |
String scope = "audience:server:client_id:" + CLIENT_ID; | |
try { | |
return GoogleAuthUtil.getToken( | |
MainActivity.this, mEmail, scope); | |
} catch (Exception e) { | |
e.printStackTrace(); // TODO: handle the exception | |
} | |
return null; | |
} | |
@Override | |
protected void onPostExecute(String idToken) { | |
// exchange encrypted idToken with server-side to identify the user | |
mIdTokenEditText.setText(idToken); | |
Log.v("Second One"," "+ idToken); | |
} | |
} | |
public class RetrieveExchangeCodeAsyncTask | |
extends AsyncTask<Void, Boolean, String> { | |
@Override | |
protected String doInBackground(Void... params) { | |
String scope = String.format("oauth2:server:client_id:%s:api_scope:%s", | |
CLIENT_ID, TextUtils.join(" ", SCOPES)); | |
try { | |
return GoogleAuthUtil.getToken( | |
MainActivity.this, mEmail, scope); | |
} catch (Exception e) { | |
e.printStackTrace(); // TODO: handle the exception | |
} | |
return null; | |
} | |
@Override | |
protected void onPostExecute(String code) { | |
// exchange code with server-side to retrieve an additional | |
// access token on the server-side. | |
Log.v("first One","1"+ code); | |
mExchangeCodeEditText.setText(code); | |
} | |
} | |
} | |
i'm trying to integrate 'Log in with Google' in app that have an android and web component. Everything in the web component is working fine with the following steps: 1. Rendering the view with an anti-forgery token, client id and app name. | |
$state = md5(rand()); | |
Session::set('state', $state); | |
$this->view->render('login', array( | |
'CLIENT_ID' => 'my_web_client_id', | |
'STATE' => $state, | |
'APPLICATION_NAME' => 'my_app_name')); | |
2. When user clicks on the Google's SignIn button, obtain the one-time code from Google's servers and send it to my server. 3. After my server receives the one-time code using https://github.com/google/google-api-php-client to authenticate the user with that code. | |
if ($_SESSION['state'] != $_POST['state']) { // Where state is the anti-forgery token | |
return 'some error'; | |
} | |
$code = $_POST['code']; | |
$client = new Google_Client(); | |
$client->setApplicationName("my_app_name"); | |
$client->setClientId('my_web_client_id'); | |
$client->setClientSecret('client_secret'); | |
$client->setRedirectUri('postmessage'); | |
$client->addScope("https://www.googleapis.com/auth/urlshortener"); | |
$client->authenticate($code); | |
$token = json_decode($client->getAccessToken()); | |
// Verify the token | |
$reqUrl = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' . $token->access_token; | |
$req = new Google_Http_Request($reqUrl); | |
$tokenInfo = json_decode($client->getAuth()->authenticatedRequest($req)->getResponseBody()); | |
// If there was an error in the token info, abort. | |
if ($tokenInfo->error) { | |
return 'some error'; | |
} | |
// Make sure the token we got is for our app. | |
if ($tokenInfo->audience != "my_web_client_id") { | |
return 'some error'; | |
} | |
// Saving user in db | |
... | |
// Load the app view | |
Now, for android client should be something similar, right? Following these tutorials:https://developers.google.com/+/mobile/android/sign-in and http://www.androidhive.info/2014/02/android-login-with-google-plus-account-1/ | |
Executing async task in onConnected method | |
class CreateToken extends AsyncTask<Void, Void, String> { | |
@Override | |
protected String doInBackground(Void... voids) { | |
oneTimeCode = getOneTimeCode(); | |
String email = getUserGPlusEmail(); | |
try { | |
// Opens connection and sends the one-time code and email to the server with 'POST' request | |
googleLogin(oneTimeCode, email); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
return oneTimeCode; | |
} | |
} | |
private String getOneTimeCode() { | |
String scopes = "oauth2:server:client_id:" + SERVER_CLIENT_ID + ":api_scope:" + SCOPE_EMAIL; | |
String code = null; | |
try { | |
code = GoogleAuthUtil.getToken( | |
LoginActivity.this, // Context context | |
Plus.AccountApi.getAccountName(mGoogleApiClient), // String accountName | |
scopes // String scope | |
); | |
} catch (IOException transientEx) { | |
Log.e(Constants.TAG, "IOException"); | |
transientEx.printStackTrace(); | |
// network or server error, the call is expected to succeed if you try again later. | |
// Don't attempt to call again immediately - the request is likely to | |
// fail, you'll hit quotas or back-off. | |
} catch (UserRecoverableAuthException e) { | |
Log.e(Constants.TAG, "UserRecoverableAuthException"); | |
e.printStackTrace(); | |
// Requesting an authorization code will always throw | |
// UserRecoverableAuthException on the first call to GoogleAuthUtil.getToken | |
// because the user must consent to offline access to their data. After | |
// consent is granted control is returned to your activity in onActivityResult | |
// and the second call to GoogleAuthUtil.getToken will succeed. | |
startActivityForResult(e.getIntent(), AUTH_CODE_REQUEST_CODE); | |
} catch (GoogleAuthException authEx) { | |
// Failure. The call is not expected to ever succeed so it should not be | |
// retried. | |
Log.e(Constants.TAG, "GoogleAuthException"); | |
authEx.printStackTrace(); | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
Log.e(Constants.TAG, "ONE TIME CODE: " + code); | |
return code; | |
} | |
After obtaining the code successfully, send it to my server for authentication. And here's the code on the server: | |
$code = $_POST['code']; | |
$client = new Google_Client(); | |
$client->setApplicationName("my_app_name"); | |
$client->setClientId('my_web_client_id'); // Web component's client id | |
$client->setClientSecret('client_secret'); // Web component's secret | |
$client->addScope("email"); | |
$client->setAccessType("offline"); | |
$client->authenticate($code); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment