OAuth2 and android

4256
2
09-19-2013 04:44 AM
MatejSkerjanc
Occasional Contributor
Is there any implementation of OAuth2 (https://developers.arcgis.com/en/authentication/) example available. I've not yet found any. If anyone knows url to any example i'd be really greatful.


P.S. there's example code for wpf and ios, but none for android


Regards Matej
0 Kudos
2 Replies
DanO_Neill
Occasional Contributor III
With the v10.1.1-u1 release you can access OAuth2 services but there is not support in the API.  You can authenticate OAuth2 services by requesting a token via URL and parse response via JSON.  Once authenticated you can load the resource.

Here is an example DialogFragment that authenticates OAuth2 using Android, Jackson, and Java API.

public class WebViewDialogFragment extends DialogFragment {

 // The redirect_uri can be either a special value of urn:ietf:wg:oauth:2.0:oob 
 // or an application-specific custom URI that is handled on the device.
 private static final String REDIRECT_URI = "";
 // OAuth2 client_id = APPID
 private static final String CLIENT_ID = "";
 String username;
 String access_token;
 String refresh_token;
 private CountDownLatch latch; 
 
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
  Bundle savedInstanceState) {
  getDialog().setTitle("Sign in to ArcGIS Online"); 
 
  final View root = inflater.inflate(R.layout.activity_main, null);
  root.findViewById(R.id.progressbar).setVisibility(View.VISIBLE);
  final WebView webView = (WebView) root.findViewById(R.id.webview);
  webView.getSettings().setJavaScriptEnabled(true);
  webView.getSettings().setBuiltInZoomControls(true);
  webView.setWebViewClient(new WebViewClient() {
   @Override
   public boolean shouldOverrideUrlLoading(WebView view, String url) {
    final String code = url.substring(url.indexOf("?code=") + 6,
        url.length());
       
    AsyncTask.execute(new Runnable() {
     @Override
     public void run() {
      try {
       requestToken("https://www.arcgis.com/sharing/rest/oauth2/token?client_id="
           + CLIENT_ID
           + "&redirect_uri="
           + REDIRECT_URI
           + "&grant_type=authorization_code&code="
           + code);
      } catch (Exception e) {
       Log.e(getClass().getSimpleName(), "", e);
      }
      dismiss();
     }
    });
    return true;
   }

   @Override
   public void onPageFinished(WebView view, String url) {
    webView.setVisibility(View.VISIBLE);
    root.findViewById(R.id.progressbar).setVisibility(View.GONE);
   }
  });
  webView.loadUrl("https://www.arcgis.com/sharing/oauth2/authorize?client_id="
       + CLIENT_ID
       + "&response_type=code&redirect_uri="
       + REDIRECT_URI);
  return root;
 }
 
 @Override
 public void onDismiss(DialogInterface dialog) {
  if (latch != null)
  latch.countDown();
  super.onDismiss(dialog);
 }

 public void setLatch(CountDownLatch latch) {
  this.latch = latch;
 }

 private void requestToken(String url) throws JsonParseException,
   MalformedURLException, IOException {
  JsonFactory f = new JsonFactory();
  JsonParser json = f.createJsonParser(new URL(url));
  json.nextToken();
  while (json.nextToken() != JsonToken.END_OBJECT) {
   String name = json.getCurrentName();
   json.nextToken();
   if ("username".equals(name))
    username = json.getText();
   else if ("access_token".equals(name))
    access_token = json.getText();
   else if ("refresh_token".equals(name))
    refresh_token = json.getText();
   Log.i(getClass().getSimpleName(), name + " = " + json.getText());
  }
 }
}


Then you can launch the dialog from your Map Class with the following:
 // Create and show the dialog.
 WebViewDialogFragment dialog = new WebViewDialogFragment();
 CountDownLatch latch = new CountDownLatch(1);
 dialog.setLatch(latch);
 dialog.show(getFragmentManager(), "dialog");
 try {
  latch.await();
  if (!TextUtils.isEmpty(dialog.access_token)) {
   credentials = new UserCredentials();
   credentials.setUserAccount(dialog.username, "-");
   credentials.setUserToken(dialog.access_token, "-");
   credentials.setAuthenticationType(AuthenticationType.TOKEN);
   return new MapLoadAction<UserCredentials>(
     Action.CONTINUE_OPEN_WITH_THE_PARAMETER,
     credentials);
  }
 } catch (InterruptedException e) {
  Log.e(getClass().getSimpleName(), "", e);
 }


The 10.2 Android SDK release will have support for authenticating in the API.  It will include a class to authenticate and set listeners to.  In the listener callback you can load the map or save the credentials to disk or both.  We will release an OAuth2 sample with the next release of the SDK, v10.2.
AndrzejBieniek
New Contributor III

Hi Dan, thanks for the code...

I have created sample app using your code (slightly modified):

I have created sample app showing how to get the ArcGIS Online token without the Android SDK - http://github.com/osedok/AGOLAuth

Please remember to set valid CLIENT_ID in ArcGISOAuth activity before running the sample.

0 Kudos