/// <summary>
        /// Read the identity provider configuration for an app
        /// </summary>
        /// <param name="args">command line args</param>
        /// <returns>a task</returns>
        private async Task GetIdentityProvider(string[] args)
        {
            this.ParseIdentityLookupArgs(args);

            this.ValidateGetIdentityProvider();

            IAppProfileEntity appProfileEntity = await this.appsManager.ReadAppProfile(this.appHandle);

            if (appProfileEntity == null)
            {
                Console.WriteLine("Cannot find app with appHandle = {0}", this.appHandle);
                Environment.Exit(0);
            }

            IIdentityProviderCredentialsEntity credentialsEntity = await this.appsManager.ReadIdentityProviderCredentials(this.appHandle, (IdentityProviderType)this.identityProvider);

            if (credentialsEntity != null)
            {
                Console.WriteLine("Identity provider config for appHandle {0}, identity provider type {1}", this.appHandle, (IdentityProviderType)this.identityProvider);
                Console.WriteLine("  Client Id = {0}", credentialsEntity.ClientId);
                Console.WriteLine("  Client secret = {0}", credentialsEntity.ClientSecret);
                Console.WriteLine("  Redirect Uri = {0}", credentialsEntity.ClientRedirectUri);
            }
            else
            {
                Console.WriteLine(
                    "Cannot find identity provider config for appHandle {0}, identity provider type {1}",
                    this.appHandle,
                    (IdentityProviderType)this.identityProvider);
            }
        }
        /// <summary>
        /// Validate third-party identity and return the user information
        /// Throws InvalidIdentityException if identity is invalid
        /// Throws IdentityValidationFailureException if validation fails for other reasons
        /// </summary>
        /// <param name="identityProviderType">Identity provider type</param>
        /// <param name="accessToken">Third party access token (for implicit flow) or user code/verifier (for authorization grant flow) or accountID (for AADS2S)</param>
        /// <param name="requestToken">Third party request token</param>
        /// <param name="identityProviderCredentials">Application's credentials for the third party identity provider.</param>
        /// <returns>User information from identity provider</returns>
        public async Task <IdentityProviderUser> GetIdentityProviderUser(
            IdentityProviderType identityProviderType,
            string accessToken,
            string requestToken,
            IIdentityProviderCredentialsEntity identityProviderCredentials)
        {
            UserProfile userProfile = null;

            try
            {
                switch (identityProviderType)
                {
                case IdentityProviderType.Microsoft:
                    userProfile = await OAuth.Instance.ImplicitFlow(IdentityProviders.Microsoft, accessToken);

                    break;

                case IdentityProviderType.Facebook:
                    userProfile = await OAuth.Instance.ImplicitFlow(IdentityProviders.Facebook, accessToken);

                    break;

                case IdentityProviderType.Google:
                    userProfile = await OAuth.Instance.ImplicitFlow(IdentityProviders.Google, accessToken);

                    break;

                case IdentityProviderType.Twitter:
                    userProfile = await OAuth.Instance.AuthorizationCodeFlow(IdentityProviders.Twitter, accessToken, identityProviderCredentials.ClientId, identityProviderCredentials.ClientSecret, null, requestToken);

                    break;

                case IdentityProviderType.AADS2S:
                    return(new IdentityProviderUser
                    {
                        AccountId = accessToken
                    });

                default:
                    throw new IdentityProviderException("Third party not supported.", null);
                }
            }
            catch (OAuthException ex)
            {
                throw new InvalidIdentityException("OAuth error.", ex);
            }

            return(new IdentityProviderUser()
            {
                AccountId = userProfile.GenericUserProfile.AccountId,
                FirstName = userProfile.GenericUserProfile.FirstName,
                LastName = userProfile.GenericUserProfile.LastName
            });
        }
        /// <summary>
        /// Update identity provider credentials
        /// </summary>
        /// <param name="storageConsistencyMode">Storage consistency mode</param>
        /// <param name="appHandle">App handle</param>
        /// <param name="identityProviderType">Identity provider type</param>
        /// <param name="identityProviderCredentialsEntity">Identity provider credentials entity</param>
        /// <returns>Update identity provider credentials task</returns>
        public async Task UpdateIdentityProviderCredentials(
            StorageConsistencyMode storageConsistencyMode,
            string appHandle,
            IdentityProviderType identityProviderType,
            IIdentityProviderCredentialsEntity identityProviderCredentialsEntity)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.Apps);

            ObjectTable table     = this.tableStoreManager.GetTable(ContainerIdentifier.Apps, TableIdentifier.AppIdentityProviderCredentialsObject) as ObjectTable;
            Operation   operation = Operation.Replace(table, appHandle, identityProviderType.ToString(), identityProviderCredentialsEntity as IdentityProviderCredentialsEntity);
            await store.ExecuteOperationAsync(operation, storageConsistencyMode.ToConsistencyMode());
        }
        /// <summary>
        /// Get fake identity provider user
        /// </summary>
        /// <param name="identityProviderType">Identity provider type</param>
        /// <param name="accessToken">Third party access token</param>
        /// <param name="requestToken">Third party request token</param>
        /// <param name="identityProviderCredentials">Application's credentials for the third party identity provider.</param>
        /// <returns>User information from identity provider</returns>
        public async Task <IdentityProviderUser> GetIdentityProviderUser(
            IdentityProviderType identityProviderType,
            string accessToken,
            string requestToken,
            IIdentityProviderCredentialsEntity identityProviderCredentials)
        {
            await Task.Delay(0);

            return(new IdentityProviderUser()
            {
                AccountId = accessToken,
                FirstName = "TestFirstName",
                LastName = "TestLastName"
            });
        }
        /// <summary>
        /// Update identity provider credentials
        /// </summary>
        /// <param name="processType">Process type</param>
        /// <param name="appHandle">App handle</param>
        /// <param name="identityProviderType">Identity provider type</param>
        /// <param name="clientId">Client id</param>
        /// <param name="clientSecret">Client secret</param>
        /// <param name="clientRedirectUri"><c>OAuth</c> callback</param>
        /// <param name="identityProviderCredentialsEntity">Identity provider credentials entity</param>
        /// <returns>Update identity provider credentials task</returns>
        public async Task UpdateIdentityProviderCredentials(
            ProcessType processType,
            string appHandle,
            IdentityProviderType identityProviderType,
            string clientId,
            string clientSecret,
            string clientRedirectUri,
            IIdentityProviderCredentialsEntity identityProviderCredentialsEntity)
        {
            identityProviderCredentialsEntity.ClientId          = clientId;
            identityProviderCredentialsEntity.ClientSecret      = clientSecret;
            identityProviderCredentialsEntity.ClientRedirectUri = clientRedirectUri;

            await this.appsStore.UpdateIdentityProviderCredentials(StorageConsistencyMode.Strong, appHandle, identityProviderType, identityProviderCredentialsEntity);
        }
        /// <summary>
        /// Update the identity provider configuration for an app
        /// </summary>
        /// <param name="args">command line args</param>
        /// <returns>a task</returns>
        private async Task UpdateIdentityProvider(string[] args)
        {
            this.ParseIdentityArgs(args);

            this.ValidateUpdateIdentityProvider();

            IAppProfileEntity appProfileEntity = await this.appsManager.ReadAppProfile(this.appHandle);

            if (appProfileEntity == null)
            {
                Console.WriteLine("Cannot find app with appHandle = {0}", this.appHandle);
                Environment.Exit(0);
            }

            IIdentityProviderCredentialsEntity credentialsEntity = await this.appsManager.ReadIdentityProviderCredentials(this.appHandle, (IdentityProviderType)this.identityProvider);

            if (credentialsEntity != null)
            {
                if (appProfileEntity.DeveloperId == this.appDeveloperId)
                {
                    await this.appsManager.UpdateIdentityProviderCredentials(
                        ProcessType.Frontend,
                        this.appHandle,
                        (IdentityProviderType)this.identityProvider,
                        this.clientId,
                        this.clientSecret,
                        this.redirectUri,
                        credentialsEntity);

                    Console.WriteLine("Updated identity provider config for appHandle {0}, identity provider type {1}", this.appHandle, (IdentityProviderType)this.identityProvider);
                }
                else
                {
                    Console.WriteLine(
                        "Incorrect developerId: developerId is {0} for appHandle {1}",
                        appProfileEntity.DeveloperId,
                        this.appHandle);
                }
            }
            else
            {
                Console.WriteLine(
                    "Cannot find identity provider config for appHandle {0}, identity provider type {1}",
                    this.appHandle,
                    (IdentityProviderType)this.identityProvider);
            }
        }