com.microsoft.aad.adal.testapp.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.aad.adal.testapp.MainActivity.java

Source

// Copyright  Microsoft Open Technologies, Inc.
//
// All Rights Reserved
//
// 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
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
// ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A
// PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT.
//
// See the Apache License, Version 2.0 for the specific language
// governing permissions and limitations under the License.

package com.microsoft.aad.adal.testapp;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.UUID;

import javax.crypto.NoSuchPaddingException;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;

import com.microsoft.aad.adal.ADALError;
import com.microsoft.aad.adal.AuthenticationCallback;
import com.microsoft.aad.adal.AuthenticationContext;
import com.microsoft.aad.adal.AuthenticationException;
import com.microsoft.aad.adal.AuthenticationResult;
import com.microsoft.aad.adal.AuthenticationSettings;
import com.microsoft.aad.adal.CacheKey;
import com.microsoft.aad.adal.DefaultTokenCacheStore;
import com.microsoft.aad.adal.ITokenCacheStore;
import com.microsoft.aad.adal.Logger;
import com.microsoft.aad.adal.Logger.ILogger;
import com.microsoft.aad.adal.PromptBehavior;
import com.microsoft.aad.adal.TokenCacheItem;

public class MainActivity extends Activity {

    public static final String GETTING_TOKEN = "Getting token...";

    Button btnGetToken, btnResetToken, btnRefresh, btnSetExpired, buttonVerify, buttonRemoveCookies;

    TextView textViewStatus;

    EditText mAuthority, mResource, mClientId, mUserid, mPrompt, mRedirect;

    CheckBox mValidate;

    private final static String TAG = "MainActivity";

    public final static String FAILED = "TEST_FAILED";

    public final static String PASSED = "TEST_PASSED";

    public final static String TOKEN_USED = "TOKEN_USED";

    public static final String TEST_CERT_ALIAS = "My Key Chain";

    public static final String PKCS12_PASS = "changeit";

    public final String PKCS12_FILENAME = "keychain.p12";

    public final String JWS_ALGORITHM = "SHA256withRSA";

    /**
     * result from recent request
     */
    private AuthenticationResult mResult;

    private Exception mLastException;

    private String mActiveUser, mExtraQueryParam;

    final static String AUTHORITY_URL = "https://login.windows.net/omercantest.onmicrosoft.com";

    final static String CLIENT_ID = "650a6609-5463-4bc4-b7c6-19df7990a8bc";

    final static String RESOURCE_ID = "https://omercantest.onmicrosoft.com/AllHandsTry";

    final static String AUTHORIZATION_HEADER = "Authorization";

    final static String AUTHORIZATION_HEADER_BEARER = "Bearer ";

    final static String REDIRECT_URL = "http://taskapp";

    // Endpoint we are targeting for the deployed WebAPI service
    final static String SERVICE_URL = "https://android.azurewebsites.net/api/values";

    final static String LOG_STATUS_FORMAT = "Status:%s Expires:%s";

    private AuthenticationContext mContext = null;

    private UUID mRequestCorrelationId;

    private Handler handler = new Handler();

    public Handler getTestAppHandler() {
        return handler;
    }

    public AuthenticationContext getAuthenticationContext() {
        return mContext;
    }

    class AdalCallback implements AuthenticationCallback<AuthenticationResult> {

        UUID mId;

        public AdalCallback() {
            mId = UUID.randomUUID();
        }

        @Override
        public void onError(Exception exc) {
            Log.e(TAG, "Callback returned error", exc);
            mLastException = exc;
            if (exc instanceof AuthenticationException) {
                AuthenticationException authException = (AuthenticationException) exc;
                textViewStatus.setText("Authentication error:" + authException.getCode().name());
                if (authException.getCode() == ADALError.AUTH_FAILED_CANCELLED) {
                    textViewStatus.setText("Cancelled");
                    Log.d(TAG, "Cancelled");
                }
            }
            Log.d(TAG, "Authentication error:" + exc.getMessage());
        }

        @Override
        public void onSuccess(AuthenticationResult result) {
            Log.d(TAG, "Callback has result");
            setResult(result);

            if (result == null || result.getAccessToken() == null || result.getAccessToken().isEmpty()) {
                textViewStatus.setText(FAILED);
                Log.d(TAG, "Token is empty");
                if (result != null) {
                    Log.d(TAG, "Error  code:" + result.getErrorCode() + " Description:"
                            + result.getErrorDescription());
                }
            } else {
                // request is successful
                Log.d(TAG, String.format(LOG_STATUS_FORMAT, result.getStatus(), result.getExpiresOn().toString()));
                textViewStatus.setText(PASSED);
            }
        }
    };

    public void setLoggerCallback(ILogger loggerCallback) {
        // callback hook to insert from test instrumentation to check loaded url
        // on webview
        // Test project adds callback to track the completion
        // loggerCallback
        if (loggerCallback != null) {
            Logger.getInstance().setExternalLogger(loggerCallback);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Get the current window
        Window window = getWindow();
        // Add the Flag from the window manager class
        window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);

        textViewStatus = (TextView) findViewById(R.id.textViewStatus);
        btnGetToken = (Button) findViewById(R.id.buttonGetToken);
        btnResetToken = (Button) findViewById(R.id.buttonReset);
        btnSetExpired = (Button) findViewById(R.id.buttonExpired);
        btnRefresh = (Button) findViewById(R.id.buttonRefresh);
        buttonVerify = (Button) findViewById(R.id.buttonVerify);
        buttonRemoveCookies = (Button) findViewById(R.id.buttonRemoveCookies);
        mAuthority = (EditText) findViewById(R.id.editAuthority);
        mResource = (EditText) findViewById(R.id.editResource);
        mClientId = (EditText) findViewById(R.id.editClientid);
        mUserid = (EditText) findViewById(R.id.editUserId);
        mPrompt = (EditText) findViewById(R.id.editPrompt);
        mRedirect = (EditText) findViewById(R.id.editRedirect);
        mValidate = (CheckBox) findViewById(R.id.checkBoxValidate);

        findViewById(R.id.buttonTestScriptRun).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                TestScriptRunner runner = new TestScriptRunner(MainActivity.this);
                runner.runRemoteScript();
            }
        });

        buttonRemoveCookies.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                removeCookies();
            }
        });

        buttonVerify.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                useToken();
            }
        });

        btnGetToken.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getToken();
            }
        });

        btnResetToken.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                resetToken();
            }
        });

        btnSetExpired.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setTokenExpired();
            }
        });

        btnRefresh.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getTokenByRefreshToken();
            }
        });
    }

    public void initDeviceCertificateMock() throws NoSuchAlgorithmException, UnrecoverableKeyException,
            CertificateException, KeyStoreException, IOException {
        KeyStore keystore = loadTestCertificate();
        Key key = keystore.getKey(TEST_CERT_ALIAS, PKCS12_PASS.toCharArray());
        RSAPrivateKey privateKey = (RSAPrivateKey) key;
        Certificate cert = keystore.getCertificate(TEST_CERT_ALIAS);
        RSAPublicKey publicKey = (RSAPublicKey) cert.getPublicKey();
        MockDeviceCertProxy.sValidIssuer = true;
        MockDeviceCertProxy.sPrivateKey = privateKey;
        MockDeviceCertProxy.sPublicKey = publicKey;
        MockDeviceCertProxy.sThumbPrint = "test";
        MockDeviceCertProxy.sCertificate = (X509Certificate) cert;
        AuthenticationSettings.INSTANCE.setDeviceCertificateProxyClass(MockDeviceCertProxy.class);
    }

    private KeyStore loadTestCertificate() throws IOException, CertificateException, UnrecoverableKeyException,
            KeyStoreException, NoSuchAlgorithmException {
        KeyStore caKs = KeyStore.getInstance("PKCS12");
        BufferedInputStream stream = new BufferedInputStream(MainActivity.this.getAssets().open(PKCS12_FILENAME));
        caKs.load(stream, PKCS12_PASS.toCharArray());
        return caKs;
    }

    @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;
    }

    private void initContext() {
        Log.d(TAG, "Init authentication context based on input");

        // UI automation tests will fill in these fields to test different
        // scenarios
        String authority = mAuthority.getText().toString();
        if (authority == null || authority.isEmpty()) {
            authority = AUTHORITY_URL;
        }

        try {
            mContext = new AuthenticationContext(MainActivity.this, authority, mValidate.isChecked());
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void acquireTokenByRefreshToken(String refreshToken) {
        textViewStatus.setText(GETTING_TOKEN);
        if (mContext == null) {
            initContext();
        }

        String clientId = mClientId.getText().toString();
        if (clientId == null || clientId.isEmpty()) {
            clientId = CLIENT_ID;
        }
        mContext.setRequestCorrelationId(mRequestCorrelationId);
        mContext.acquireTokenByRefreshToken(refreshToken, clientId, new AdalCallback());
    }

    private void getTokenByRefreshToken() {
        Logger.v(TAG, "get Token with refresh token");
        textViewStatus.setText(GETTING_TOKEN);
        if (mResult != null && mResult.getRefreshToken() != null && !mResult.getRefreshToken().isEmpty()) {
            String clientId = mClientId.getText().toString();

            if (clientId == null || clientId.isEmpty()) {
                clientId = CLIENT_ID;
            }
            mContext.setRequestCorrelationId(mRequestCorrelationId);
            mContext.acquireTokenByRefreshToken(mResult.getRefreshToken(), clientId, new AdalCallback());
        } else {
            textViewStatus.setText(FAILED);
        }
    }

    private void getToken() {
        Logger.v(TAG, "get Token");
        textViewStatus.setText(GETTING_TOKEN);
        if (mContext == null) {
            initContext();
        }

        String resource = mResource.getText().toString();
        if (resource == null || resource.isEmpty()) {
            resource = RESOURCE_ID;
        }

        String clientId = mClientId.getText().toString();
        if (clientId == null || clientId.isEmpty()) {
            clientId = CLIENT_ID;
        }

        // Optional field, so acquireToken accepts null fields
        String userid = mUserid.getText().toString();

        String promptInput = mPrompt.getText().toString();
        if (promptInput == null || promptInput.isEmpty()) {
            promptInput = PromptBehavior.Auto.name();
        }

        PromptBehavior prompt = PromptBehavior.valueOf(promptInput);

        // Optional field, so acquireToken accepts null fields
        String redirect = mRedirect.getText().toString();
        mResult = null;
        mContext.setRequestCorrelationId(mRequestCorrelationId);
        mContext.acquireToken(MainActivity.this, resource, clientId, redirect, userid, prompt, mExtraQueryParam,
                new AdalCallback());
    }

    public void getTokenSilent() {
        Logger.v(TAG, "get Token Silent");
        textViewStatus.setText(GETTING_TOKEN);
        if (mContext == null) {
            initContext();
        }

        String resource = mResource.getText().toString();
        if (resource == null || resource.isEmpty()) {
            resource = RESOURCE_ID;
        }

        String clientId = mClientId.getText().toString();
        if (clientId == null || clientId.isEmpty()) {
            clientId = CLIENT_ID;
        }

        // Optional field, so acquireToken accepts null fields
        String userid = mUserid.getText().toString();

        mResult = null;
        mContext.setRequestCorrelationId(mRequestCorrelationId);
        mContext.acquireTokenSilent(resource, clientId, userid, new AdalCallback());
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (mContext != null) {
            mContext.onActivityResult(requestCode, resultCode, data);
        }
    }

    public void setContextForScriptRun(final AuthenticationContext context) {
        this.mContext = context;
    }

    private void removeCookies() {
        // Clear browser cookies
        CookieSyncManager.createInstance(MainActivity.this);
        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.removeAllCookie();
        CookieSyncManager.getInstance().sync();
    }

    /**
     * only remove from cache but keep cookies
     */
    public void removeTokens() {
        if (mContext == null) {
            initContext();
        }

        mContext.getCache().removeAll();
        textViewStatus.setText("");
    }

    /**
     * reset all
     */
    private void resetToken() {
        Log.d(TAG, "reset Token");
        removeTokens();
        removeCookies();
    }

    /**
     * set all expired
     */
    private void setTokenExpired() {
        Log.d(TAG, "Setting item to expire...");

        Calendar calendar = new GregorianCalendar();
        calendar.add(Calendar.MINUTE, -30);
        Date date = calendar.getTime();
        ITokenCacheStore cache = mContext.getCache();
        String key = CacheKey.createCacheKey(mAuthority.getText().toString(), mResource.getText().toString(),
                mClientId.getText().toString(), false, mUserid.getText().toString());
        TokenCacheItem item = cache.getItem(key);
        setTime(cache, date, key, item);

        key = CacheKey.createCacheKey(mAuthority.getText().toString(), mResource.getText().toString(),
                mClientId.getText().toString(), true, mUserid.getText().toString());
        item = cache.getItem(key);
        setTime(cache, date, key, item);
    }

    private void setTime(ITokenCacheStore cache, Date date, String key, TokenCacheItem item) {
        if (item != null) {
            Calendar calendar = new GregorianCalendar();
            calendar.add(Calendar.MINUTE, -30);
            item.setExpiresOn(calendar.getTime());

            cache.setItem(key, item);
            Log.d(TAG, "Item is set to expire for key:" + key);
        } else {
            Log.d(TAG, "item is null: setTokenExpired");
        }
    }

    /**
     * set all expired
     */
    public ArrayList<TokenCacheItem> getTokens() {
        Log.d(TAG, "Setting item to expire...");
        ArrayList<TokenCacheItem> items = new ArrayList<TokenCacheItem>();
        DefaultTokenCacheStore cache = (DefaultTokenCacheStore) mContext.getCache();
        Iterator<TokenCacheItem> iterator = cache.getAll();
        while (iterator.hasNext()) {
            TokenCacheItem item = iterator.next();
            if (item != null) {
                items.add(item);
            }
        }

        return items;
    }

    /**
     * send token in the header with async task
     * 
     * @param result
     */
    private void useToken() {
        if (mResult != null && mResult.getRefreshToken() != null && !mResult.getRefreshToken().isEmpty()) {
            textViewStatus.setText("");
            new RequestTask(SERVICE_URL, mResult.getAccessToken()).execute();
        } else {
            textViewStatus.setText(FAILED);
        }
    }

    public AuthenticationResult getResult() {
        return mResult;
    }

    public String getActiveUser() {
        return mActiveUser;
    }

    public void setResult(AuthenticationResult result) {
        this.mResult = result;
        if (result != null && result.getUserInfo() != null) {
            Log.v(TAG, "Active UserId:" + mActiveUser);
            mActiveUser = result.getUserInfo().getUserId();
        }
    }

    public UUID getRequestCorrelationId() {
        return mRequestCorrelationId;
    }

    public void setRequestCorrelationId(UUID mRequestCorrelationId) {
        this.mRequestCorrelationId = mRequestCorrelationId;
    }

    public void setExtraQueryParam(String extraQueryParam) {
        mExtraQueryParam = extraQueryParam;
    }

    public Exception getLastException() {
        return mLastException;
    }

    /**
     * Simple get request for test
     */
    class RequestTask extends AsyncTask<Void, String, String> {

        private String mUrl;

        private String mToken;

        public RequestTask(String url, String token) {
            mUrl = url;
            mToken = token;
        }

        @Override
        protected String doInBackground(Void... empty) {

            HttpClient httpclient = new DefaultHttpClient();
            HttpResponse httpResponse;
            String responseString = "";

            try {
                HttpGet getRequest = new HttpGet(mUrl);
                getRequest.addHeader(AUTHORIZATION_HEADER, AUTHORIZATION_HEADER_BEARER + mToken);
                getRequest.addHeader("Accept", "application/json");

                httpResponse = httpclient.execute(getRequest);
                StatusLine statusLine = httpResponse.getStatusLine();

                if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
                    // negative for unknown
                    if (httpResponse.getEntity().getContentLength() != 0) {
                        ByteArrayOutputStream out = new ByteArrayOutputStream();
                        httpResponse.getEntity().writeTo(out);
                        out.close();
                        responseString = out.toString();
                    }
                } else {
                    // Closes the connection.
                    httpResponse.getEntity().getContent().close();
                    throw new IOException(statusLine.getReasonPhrase());
                }
            } catch (ClientProtocolException e) {
                responseString = e.getMessage();
            } catch (IOException e) {
                responseString = e.getMessage();
            }
            return responseString;
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);

            textViewStatus.setText("");
            if (result != null && !result.isEmpty()) {
                textViewStatus.setText(TOKEN_USED);
            }
        }
    }

}