Android Open Source - Android-Activity-Tracker-for-Dynamics-CRM Challange Response Builder






From Project

Back to project page Android-Activity-Tracker-for-Dynamics-CRM.

License

The source code is released under:

MIT License

If you think the Android project Android-Activity-Tracker-for-Dynamics-CRM listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

// Copyright  Microsoft Open Technologies, Inc.
////w w  w.  ja  v  a2 s  . c om
// 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;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.interfaces.RSAPrivateKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

class ChallangeResponseBuilder {

    private static final String TAG = "ChallangeResponseBuilder";

    private IJWSBuilder mJWSBuilder;

    ChallangeResponseBuilder(IJWSBuilder jwsBuilder) {
        mJWSBuilder = jwsBuilder;
    }

    class ChallangeResponse {
        String mSubmitUrl;

        String mAuthorizationHeaderValue;

        public String getSubmitUrl() {
            return mSubmitUrl;
        }

        public String getAuthorizationHeaderValue() {
            return mAuthorizationHeaderValue;
        }
    }

    enum RequestField {
        Nonce, CertAuthorities, Version, SubmitUrl, Context, CertThumbprint
    }

    class ChallangeRequest {
        String mNonce = "";

        String mContext = "";

        /**
         * Authorization endpoint will return accepted authorities.
         */
        List<String> mCertAuthorities;

        /**
         * Token endpoint will return thumbprint.
         */
        String mThumbprint = "";

        String mVersion = null;

        String mSubmitUrl = "";
    }

    /**
     * This parses the redirectURI for challenge components and produces
     * response object.
     * 
     * @param redirectUri Location: urn:http-auth:CertAuth?Nonce=<noncevalue>
     *            &CertAuthorities=<distinguished names of CAs>&Version=1.0
     *            &SubmitUrl=<URL to submit response>&Context=<server state that
     *            client must convey back>
     * @return Return Device challange response
     */
    public ChallangeResponse getChallangeResponseFromUri(final String redirectUri) {
        ChallangeRequest request = getChallangeRequest(redirectUri);
        return getDeviceCertResponse(request);
    }

    public ChallangeResponse getChallangeResponseFromHeader(final String challangeHeaderValue,
            final String endpoint) throws UnsupportedEncodingException {
        ChallangeRequest request = getChallangeRequestFromHeader(challangeHeaderValue);
        request.mSubmitUrl = endpoint;
        return getDeviceCertResponse(request);
    }

    private ChallangeResponse getDeviceCertResponse(ChallangeRequest request) {
        ChallangeResponse response = getNoDeviceCertResponse(request);
        response.mSubmitUrl = request.mSubmitUrl;

        // If not device cert exists, alias or privatekey will not exist on the
        // device
        @SuppressWarnings("unchecked")
        Class<IDeviceCertificate> certClazz = (Class<IDeviceCertificate>)AuthenticationSettings.INSTANCE
                .getDeviceCertificateProxy();
        if (certClazz == null) {
            throw new AuthenticationException(ADALError.DEVICE_CERTIFICATE_API_EXCEPTION,
                    "WPJ Api related class is not set");
        }

        IDeviceCertificate deviceCertProxy = getWPJAPIInstance(certClazz);
        if (deviceCertProxy.isValidIssuer(request.mCertAuthorities)
                || (deviceCertProxy.getThumbPrint() != null && deviceCertProxy.getThumbPrint()
                        .equalsIgnoreCase(request.mThumbprint))) {
            RSAPrivateKey privateKey = deviceCertProxy.getRSAPrivateKey();
            if (privateKey != null) {
                String jwt = mJWSBuilder.generateSignedJWT(request.mNonce, request.mSubmitUrl,
                        privateKey, deviceCertProxy.getRSAPublicKey(),
                        deviceCertProxy.getCertificate());
                response.mAuthorizationHeaderValue = String.format(
                        "%s AuthToken=\"%s\",Context=\"%s\",Version=\"%s\"",
                        AuthenticationConstants.Broker.CHALLANGE_RESPONSE_TYPE, jwt,
                        request.mContext, request.mVersion);
                Logger.v(TAG, "Challange response:" + response.mAuthorizationHeaderValue);
            } else {
                throw new AuthenticationException(ADALError.KEY_CHAIN_PRIVATE_KEY_EXCEPTION);
            }
        }

        return response;
    }

    private IDeviceCertificate getWPJAPIInstance(Class<IDeviceCertificate> certClazz) {
        IDeviceCertificate deviceCertProxy = null;
        Constructor<?> constructor;
        try {
            constructor = certClazz.getDeclaredConstructor();
            deviceCertProxy = (IDeviceCertificate)constructor.newInstance((Object[])null);
        } catch (NoSuchMethodException e) {
            throw new AuthenticationException(ADALError.DEVICE_CERTIFICATE_API_EXCEPTION,
                    "WPJ Api constructor is not defined", e);
        } catch (InstantiationException e) {
            throw new AuthenticationException(ADALError.DEVICE_CERTIFICATE_API_EXCEPTION,
                    "WPJ Api constructor is not defined", e);
        } catch (IllegalAccessException e) {
            throw new AuthenticationException(ADALError.DEVICE_CERTIFICATE_API_EXCEPTION,
                    "WPJ Api constructor is not defined", e);
        } catch (IllegalArgumentException e) {
            throw new AuthenticationException(ADALError.DEVICE_CERTIFICATE_API_EXCEPTION,
                    "WPJ Api constructor is not defined", e);
        } catch (InvocationTargetException e) {
            throw new AuthenticationException(ADALError.DEVICE_CERTIFICATE_API_EXCEPTION,
                    "WPJ Api constructor is not defined", e);
        }
        return deviceCertProxy;
    }

    private ChallangeResponse getNoDeviceCertResponse(final ChallangeRequest request) {
        ChallangeResponse response = new ChallangeResponse();
        response.mSubmitUrl = request.mSubmitUrl;
        response.mAuthorizationHeaderValue = String.format("CertAuth Context=\"%s\"",
                request.mContext);
        return response;
    }

    private ChallangeRequest getChallangeRequestFromHeader(final String headerValue)
            throws UnsupportedEncodingException {
        if (StringExtensions.IsNullOrBlank(headerValue)) {
            throw new IllegalArgumentException("headerValue");
        }

        // Header value should start with correct challenge type
        if (!StringExtensions.hasPrefixInHeader(headerValue,
                AuthenticationConstants.Broker.CHALLANGE_RESPONSE_TYPE)) {
            throw new AuthenticationException(ADALError.DEVICE_CERTIFICATE_REQUEST_INVALID,
                    headerValue);
        }

        ChallangeRequest challange = new ChallangeRequest();
        String authenticateHeader = headerValue
                .substring(AuthenticationConstants.Broker.CHALLANGE_RESPONSE_TYPE.length());
        ArrayList<String> queryPairs = StringExtensions.splitWithQuotes(authenticateHeader, ',');
        HashMap<String, String> headerItems = new HashMap<String, String>();

        for (String queryPair : queryPairs) {
            ArrayList<String> pair = StringExtensions.splitWithQuotes(queryPair, '=');
            if (pair.size() == 2 && !StringExtensions.IsNullOrBlank(pair.get(0))
                    && !StringExtensions.IsNullOrBlank(pair.get(1))) {
                String key = pair.get(0);
                String value = pair.get(1);
                key = StringExtensions.URLFormDecode(key);
                value = StringExtensions.URLFormDecode(value);
                key = key.trim();
                value = StringExtensions.removeQuoteInHeaderValue(value.trim());
                headerItems.put(key, value);
            } else {

                // invalid format
                throw new AuthenticationException(ADALError.DEVICE_CERTIFICATE_REQUEST_INVALID,
                        authenticateHeader);
            }
        }

        validateChallangeRequest(headerItems, false);
        challange.mNonce = headerItems.get(RequestField.Nonce.name());
        if (StringExtensions.IsNullOrBlank(challange.mNonce)) {
            challange.mNonce = headerItems.get(RequestField.Nonce.name().toLowerCase(Locale.US));
        }
        challange.mThumbprint = headerItems.get(RequestField.CertThumbprint.name());
        if (StringExtensions.IsNullOrBlank(challange.mThumbprint)) {
            throw new AuthenticationException(ADALError.DEVICE_CERTIFICATE_REQUEST_INVALID,
                    "CertThumbprint is not present in the header");
        }
        challange.mVersion = headerItems.get(RequestField.Version.name());
        challange.mContext = headerItems.get(RequestField.Context.name());
        return challange;
    }

    private void validateChallangeRequest(HashMap<String, String> headerItems,
            boolean redirectFormat) {
        if (!(headerItems.containsKey(RequestField.Nonce.name()) || headerItems
                .containsKey(RequestField.Nonce.name().toLowerCase(Locale.US)))) {
            throw new AuthenticationException(ADALError.DEVICE_CERTIFICATE_REQUEST_INVALID, "Nonce");
        }
        if (!headerItems.containsKey(RequestField.Version.name())) {
            throw new AuthenticationException(ADALError.DEVICE_CERTIFICATE_REQUEST_INVALID,
                    "Version");
        }
        if (redirectFormat && !headerItems.containsKey(RequestField.SubmitUrl.name())) {
            throw new AuthenticationException(ADALError.DEVICE_CERTIFICATE_REQUEST_INVALID,
                    "SubmitUrl");
        }
        if (!headerItems.containsKey(RequestField.Context.name())) {
            throw new AuthenticationException(ADALError.DEVICE_CERTIFICATE_REQUEST_INVALID,
                    "Context");
        }
        if (redirectFormat && !headerItems.containsKey(RequestField.CertAuthorities.name())) {
            throw new AuthenticationException(ADALError.DEVICE_CERTIFICATE_REQUEST_INVALID,
                    "CertAuthorities");
        }
    }

    private ChallangeRequest getChallangeRequest(final String redirectUri) {
        if (StringExtensions.IsNullOrBlank(redirectUri)) {
            throw new IllegalArgumentException("redirectUri");
        }

        ChallangeRequest challange = new ChallangeRequest();
        HashMap<String, String> parameters = StringExtensions.getUrlParameters(redirectUri);
        validateChallangeRequest(parameters, true);
        challange.mNonce = parameters.get(RequestField.Nonce.name());
        if (StringExtensions.IsNullOrBlank(challange.mNonce)) {
            challange.mNonce = parameters.get(RequestField.Nonce.name().toLowerCase(Locale.US));
        }
        String authorities = parameters.get(RequestField.CertAuthorities.name());
        Logger.v(TAG, "Cert authorities:" + authorities);
        challange.mCertAuthorities = StringExtensions.getStringTokens(authorities,
                AuthenticationConstants.Broker.CHALLANGE_REQUEST_CERT_AUTH_DELIMETER);
        challange.mVersion = parameters.get(RequestField.Version.name());
        challange.mSubmitUrl = parameters.get(RequestField.SubmitUrl.name());
        challange.mContext = parameters.get(RequestField.Context.name());
        return challange;
    }
}




Java Source Code List

com.microsoft.aad.adal.ADALError.java
com.microsoft.aad.adal.AuthenticationActivity.java
com.microsoft.aad.adal.AuthenticationCallback.java
com.microsoft.aad.adal.AuthenticationCancelError.java
com.microsoft.aad.adal.AuthenticationConstants.java
com.microsoft.aad.adal.AuthenticationContext.java
com.microsoft.aad.adal.AuthenticationException.java
com.microsoft.aad.adal.AuthenticationParameters.java
com.microsoft.aad.adal.AuthenticationRequestState.java
com.microsoft.aad.adal.AuthenticationRequest.java
com.microsoft.aad.adal.AuthenticationResult.java
com.microsoft.aad.adal.AuthenticationSettings.java
com.microsoft.aad.adal.BrokerProxy.java
com.microsoft.aad.adal.CacheKey.java
com.microsoft.aad.adal.ChallangeResponseBuilder.java
com.microsoft.aad.adal.DefaultTokenCacheStore.java
com.microsoft.aad.adal.Discovery.java
com.microsoft.aad.adal.ExceptionExtensions.java
com.microsoft.aad.adal.FileTokenCacheStore.java
com.microsoft.aad.adal.HashMapExtensions.java
com.microsoft.aad.adal.HttpWebRequest.java
com.microsoft.aad.adal.HttpWebResponse.java
com.microsoft.aad.adal.IBrokerProxy.java
com.microsoft.aad.adal.IConnectionService.java
com.microsoft.aad.adal.IDeviceCertificate.java
com.microsoft.aad.adal.IDiscovery.java
com.microsoft.aad.adal.IJWSBuilder.java
com.microsoft.aad.adal.ITokenCacheStore.java
com.microsoft.aad.adal.ITokenStoreQuery.java
com.microsoft.aad.adal.IWebRequestHandler.java
com.microsoft.aad.adal.IdToken.java
com.microsoft.aad.adal.JWSBuilder.java
com.microsoft.aad.adal.Logger.java
com.microsoft.aad.adal.MemoryTokenCacheStore.java
com.microsoft.aad.adal.Oauth2.java
com.microsoft.aad.adal.PRNGFixes.java
com.microsoft.aad.adal.PackageHelper.java
com.microsoft.aad.adal.PromptBehavior.java
com.microsoft.aad.adal.StorageHelper.java
com.microsoft.aad.adal.StringExtensions.java
com.microsoft.aad.adal.TokenCacheItem.java
com.microsoft.aad.adal.UserInfo.java
com.microsoft.aad.adal.WebRequestHandler.java
com.microsoft.aad.adal.package-info.java
com.microsoft.activitytracker.Activities.CheckInActivity.java
com.microsoft.activitytracker.Activities.ItemActivity.java
com.microsoft.activitytracker.Activities.MainActivity.java
com.microsoft.activitytracker.Activities.SetupActivity.java
com.microsoft.activitytracker.Adapters.ActivitiesItemAdapter.java
com.microsoft.activitytracker.Adapters.MainItemAdapter.java
com.microsoft.activitytracker.Classes.ActivityTracker.java
com.microsoft.activitytracker.Classes.Constants.java
com.microsoft.activitytracker.Classes.Entity.java
com.microsoft.activitytracker.Classes.RecentHistorydbHandler.java
com.microsoft.activitytracker.Classes.Utils.java
com.microsoft.activitytracker.Core.NetworkCalls.java
com.microsoft.activitytracker.Core.SoapExecuteParser.java
com.microsoft.activitytracker.Core.SoapRetrieveMultipleParser.java