package com.apigee.sdk.data.client.activities;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.google.api.client.auth.oauth2.AuthorizationCodeRequestUrl;
import com.google.api.client.auth.oauth2.AuthorizationCodeTokenRequest;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson.JacksonFactory;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* OAuth2WebViewActivity is used for logging in to an OAuth 2 provider with using the authorization_code or implicit grant_types.
*
* Created by ApigeeCorporation on 11/19/14.
*/
public class OAuth2WebViewActivity extends android.app.Activity {
// Extras that need to be set on the Intent when starting this Activity.
public static final String OAuth2GrantTypeExtraKey = "grantType";
public static final String OAuth2AccessCodeURLExtraKey = "accessCodeURL";
public static final String OAuth2AccessTokenURLExtraKey = "accessTokenURL";
public static final String OAuth2RedirectURLExtraKey = "redirectURL";
public static final String OAuth2ClientIDExtraKey = "clientId";
public static final String OAuth2ClientSecretExtraKey = "clientSecret";
// Extras that will set on the Intent when returning from this Activity within the method named onActivityResult.
public static final String OAuth2AccessTokenExtraKey = "access_token";
public static final String OAuth2RefreshTokenExtraKey = "refresh_token";
public static final String OAuth2AccessCodeExtraKey = "code";
public static final String OAuth2ExpiresInExtraKey = "expires_in";
public static final String OAuth2ErrorExtraKey = "error";
private String grantType;
private String accessCodeURL;
private String accessTokenURL;
private String redirectURL;
private String clientId;
private String clientSecret;
private Boolean handledRedirect;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.handledRedirect = false;
this.grantType = this.getIntent().getStringExtra(OAuth2GrantTypeExtraKey);
this.accessCodeURL = this.getIntent().getStringExtra(OAuth2AccessCodeURLExtraKey);
this.accessTokenURL = this.getIntent().getStringExtra(OAuth2AccessTokenURLExtraKey);
this.redirectURL = this.getIntent().getStringExtra(OAuth2RedirectURLExtraKey);
this.clientId = this.getIntent().getStringExtra(OAuth2ClientIDExtraKey);
this.clientSecret = this.getIntent().getStringExtra(OAuth2ClientSecretExtraKey);
WebView webview = new WebView(this);
webview.getSettings().setJavaScriptEnabled(true);
webview.setVisibility(View.VISIBLE);
setContentView(webview);
webview.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
@Override
public void onPageFinished(final WebView webView, final String url) {
if (url.startsWith(OAuth2WebViewActivity.this.redirectURL)) {
webView.setVisibility(View.INVISIBLE);
if (!OAuth2WebViewActivity.this.handledRedirect) {
new ProcessToken(url,OAuth2WebViewActivity.this.redirectURL,OAuth2WebViewActivity.this.accessTokenURL).execute();
}
} else {
webView.setVisibility(View.VISIBLE);
}
}});
AuthorizationCodeRequestUrl authorizationRequestUrl = new AuthorizationCodeRequestUrl(this.accessCodeURL,this.clientId);
authorizationRequestUrl.setRedirectUri(this.redirectURL);
authorizationRequestUrl.setResponseTypes(Collections.singleton(this.grantType));
webview.loadUrl(authorizationRequestUrl.build());
}
private class ProcessToken extends AsyncTask<String, Void, Void> {
private String url;
private String redirectURL;
private String accessTokenURL;
private Intent resultIntent;
public ProcessToken(String url,String redirectURL,String accessTokenURL) {
this.url = url;
this.redirectURL = redirectURL;
this.accessTokenURL = accessTokenURL;
}
@Override
protected Void doInBackground(String...params) {
if (this.url.startsWith(this.redirectURL))
{
OAuth2WebViewActivity.this.handledRedirect = true;
this.resultIntent = new Intent();
try {
Map<String,String> urlQueryParams = this.extractQueryParams(url);
if( urlQueryParams.get(OAuth2AccessTokenExtraKey) != null ) {
this.resultIntent.putExtra(OAuth2AccessTokenExtraKey,urlQueryParams.get(OAuth2AccessTokenExtraKey));
if( urlQueryParams.get(OAuth2ExpiresInExtraKey) != null ) {
this.resultIntent.putExtra(OAuth2ExpiresInExtraKey,urlQueryParams.get(OAuth2ExpiresInExtraKey));
}
if( urlQueryParams.get(OAuth2RefreshTokenExtraKey) != null ) {
this.resultIntent.putExtra(OAuth2RefreshTokenExtraKey, urlQueryParams.get(OAuth2RefreshTokenExtraKey));
}
} else if ( urlQueryParams.get(OAuth2AccessCodeExtraKey) != null ) {
String authorizationCode = urlQueryParams.get(OAuth2AccessCodeExtraKey);
resultIntent.putExtra(OAuth2AccessCodeExtraKey, authorizationCode);
OAuth2WebViewActivity.this.setResult(RESULT_OK,resultIntent);
AuthorizationCodeTokenRequest codeTokenRequest = new AuthorizationCodeTokenRequest(new NetHttpTransport(),new JacksonFactory(),new GenericUrl(this.accessTokenURL),authorizationCode);
codeTokenRequest.setRedirectUri(this.redirectURL);
if( clientId != null ) {
codeTokenRequest.set("client_id", clientId);
}
if( clientSecret != null ) {
codeTokenRequest.set("client_secret", clientSecret);
}
HttpResponse response = codeTokenRequest.executeUnparsed();
InputStream in = response.getContent();
InputStreamReader is = new InputStreamReader(in);
StringBuilder sb=new StringBuilder();
BufferedReader br = new BufferedReader(is);
String read = br.readLine();
while(read != null) {
sb.append(read);
read =br.readLine();
}
String accessTokenStringData = sb.toString();
Map<String,String> queryParams = this.extractQueryParams(accessTokenStringData);
if( queryParams.get(OAuth2AccessTokenExtraKey) != null ) {
this.resultIntent.putExtra(OAuth2AccessTokenExtraKey,queryParams.get(OAuth2AccessTokenExtraKey));
}
if( queryParams.get(OAuth2ExpiresInExtraKey) != null ) {
this.resultIntent.putExtra(OAuth2ExpiresInExtraKey, queryParams.get(OAuth2ExpiresInExtraKey));
}
if( queryParams.get(OAuth2RefreshTokenExtraKey) != null ) {
this.resultIntent.putExtra(OAuth2RefreshTokenExtraKey, queryParams.get(OAuth2RefreshTokenExtraKey));
}
} else if (urlQueryParams.get(OAuth2ErrorExtraKey) != null) {
this.resultIntent.putExtra(OAuth2ErrorExtraKey,urlQueryParams.get(OAuth2ErrorExtraKey));
OAuth2WebViewActivity.this.setResult(RESULT_OK, resultIntent);
}
} catch (Exception e) {
this.resultIntent.putExtra("error",e.getLocalizedMessage());
e.printStackTrace();
}
}
return null;
}
private Map<String,String> extractQueryParams(String stringWithParams) {
Map<String,String> params = new HashMap<String, String>();
int indexOfQuestion = stringWithParams.indexOf("?");
if( indexOfQuestion != -1 ) {
stringWithParams = stringWithParams.substring(indexOfQuestion+1,stringWithParams.length()-1);
}
String[] paramsSeperated = stringWithParams.split("&");
for( String param : paramsSeperated ) {
String[] paramSeperatedByEquals = param.split("=");
if( paramSeperatedByEquals.length > 1 ) {
String paramName = paramSeperatedByEquals[0];
if( paramName.contains(OAuth2AccessTokenExtraKey) ) {
paramName = OAuth2AccessTokenExtraKey;
}
if( paramName.contains(OAuth2AccessCodeExtraKey) ) {
paramName = OAuth2AccessCodeExtraKey;
}
if( paramName.contains("expires") ) {
paramName = OAuth2ExpiresInExtraKey;
}
if( paramName.contains(OAuth2RefreshTokenExtraKey) ) {
paramName = OAuth2RefreshTokenExtraKey;
}
if( paramName.contains(OAuth2ErrorExtraKey) ) {
paramName = OAuth2ErrorExtraKey;
}
params.put(paramName,paramSeperatedByEquals[1]);
}
}
return params;
}
@Override
protected void onPostExecute(Void result) {
if( this.resultIntent != null ) {
OAuth2WebViewActivity.this.setResult(RESULT_OK,this.resultIntent);
OAuth2WebViewActivity.this.finish();
}
}
}
}