예제 #1
0
        /// <summary>
        /// Obtains the claims supported by this Identity Server for this client as a JSON string.
        /// </summary>
        /// <param name="userCredentialsCallback">
        /// A callback used to obtain login credentials in the case that the current Access Token and
        /// Refresh Token (if any) are expired.
        /// </param>
        /// <returns>A JSON string representing the Claims for this API.</returns>
        ///
        public async Task <string> GetAccountsApiClaimsAsJson(UserCredentialsCallback userCredentialsCallback)
        {
            var response = await InvokeApiAsync(Get, "identity", userCredentialsCallback);

            var content = await TryGetResponseContent(response);

            return(content);
        }
예제 #2
0
        /// <summary>
        /// Used by Admin users to create a new account bound to the client specified by <c>clientId</c>.
        /// </summary>
        /// <param name="clientId">The account to be modified.</param>
        /// <param name="userCredentialsCallback">A delegate that, if invoked, returns the User's credentials.</param>
        /// <returns>The starting balance for the new account.</returns>
        ///
        public async Task <string> CreateAccount(string clientId, UserCredentialsCallback userCredentialsCallback)
        {
            string accountId;

            var accessToken = await GetCurrentAccessToken(userCredentialsCallback);

            using (var accountsApi = new AccountsApiClient(_accountsApiUrl, accessToken))
            {
                accountId = await accountsApi.CreateAccount(clientId);
            }

            return(accountId);
        }
예제 #3
0
        /// <summary>
        /// Get the history of an account from the Accounts API, on behalf of a User.
        /// </summary>
        /// <param name="accountNumber">The account to be queried.</param>
        /// <param name="userCredentialsCallback">A delegate that, if invoked, returns the User's credentials.</param>
        /// <returns>The account history as list of signed doubles.</returns>
        ///
        public async Task <AccountHistory> GetAccountHistory(string accountNumber, UserCredentialsCallback userCredentialsCallback)
        {
            AccountHistory history;

            var accessToken = await GetCurrentAccessToken(userCredentialsCallback);

            using (var accountsApi = new AccountsApiClient(_accountsApiUrl, accessToken))
            {
                history = await accountsApi.GetAccountHistory(accountNumber);
            }

            return(history);
        }
예제 #4
0
        /// <summary>
        /// Get the balance of an account from the Accounts API, on behalf of a User.
        /// </summary>
        /// <param name="accountNumber">The account to be queried.</param>
        /// <param name="userCredentialsCallback">A delegate that, if invoked, returns the User's credentials.</param>
        /// <returns>The account balance as a double.</returns>
        ///
        public async Task <double> GetAccountBalance(string accountNumber, UserCredentialsCallback userCredentialsCallback)
        {
            double balance;

            var accessToken = await GetCurrentAccessToken(userCredentialsCallback);

            using (var accountsApi = new AccountsApiClient(_accountsApiUrl, accessToken))
            {
                balance = await accountsApi.GetAccountBalance(accountNumber);
            }

            return(balance);
        }
예제 #5
0
        private async Task <string> GetCurrentAccessToken(UserCredentialsCallback userCredentialsCallback)
        {
            var tokens = TokenManager.GetAccessTokens();

            if (!String.IsNullOrEmpty(tokens?.AccessToken))
            {
                return(tokens.AccessToken);
            }

            var(username, password) = await userCredentialsCallback();

            return(await GetAndStoreApiAccessTokens(username, password));
        }
예제 #6
0
        /// <summary>
        /// Create a Client with and bind it to the specified username.  This request will fail if the User
        /// specified by <c>username</c> is already bound to a Client.
        /// </summary>
        /// <param name="username">The username of the User to bind to the new Client.</param>
        /// <param name="firstName">The client's first/given name.</param>
        /// <param name="lastName">The client's last/family name.</param>
        /// <param name="userCredentialsCallback"></param>
        /// <returns></returns>
        public async Task <string> CreateClient(string username,
                                                string firstName,
                                                string lastName,
                                                UserCredentialsCallback userCredentialsCallback)
        {
            var accessToken = await GetCurrentAccessToken(userCredentialsCallback);

            using (var accountsApi = new AccountsApiClient(_accountsApiUrl, accessToken))
            {
                var clientId = await accountsApi.CreateClient(username, firstName, lastName);

                return(clientId);
            }
        }
예제 #7
0
        /// <summary>
        /// Call the Accounts API, on behalf of a User, to debit an account by some amount.
        /// Note that <c>amount</c> should be unsigned, and that only it's absolute value
        /// will be taken in any event.
        /// </summary>
        /// <param name="accountNumber">The account to be modified.</param>
        /// <param name="amount">The (unsigned) amount to be debited from the account.</param>
        /// <param name="memo">A short note to be attached to this transaction.</param>
        /// <param name="userCredentialsCallback">A delegate that, if invoked, returns the User's credentials.</param>
        /// <returns>The new balance for the modified account.</returns>
        ///
        public async Task <double> DebitAccount(string accountNumber, double amount, string memo,
                                                UserCredentialsCallback userCredentialsCallback)
        {
            double balance;

            var accessToken = await GetCurrentAccessToken(userCredentialsCallback);

            using (var accountsApi = new AccountsApiClient(_accountsApiUrl, accessToken))
            {
                balance = await accountsApi.DebitAccount(accountNumber, amount, memo);
            }

            return(balance);
        }
예제 #8
0
        /// <summary>
        /// Creates a new Identity with the specified username, password, and name.  Also creates a corresponding
        /// User on the Accounts system and links it to the new Identity via the <see cref="ApplicationClaimTypes.ACCOUNTS_USERNAME"/>
        /// claim.
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <param name="firstName"></param>
        /// <param name="lastName"></param>
        /// <param name="isAdmin"></param>
        /// <param name="userCredentialsCallback"></param>
        /// <returns></returns>
        public async Task CreateUser(string username,
                                     string password,
                                     string firstName,
                                     string lastName,
                                     bool isAdmin,
                                     UserCredentialsCallback userCredentialsCallback)
        {
            var accessToken = await GetCurrentAccessToken(userCredentialsCallback);

            var newUser     = new AltSourceNewUserDto(username, password, firstName, lastName, isAdmin);
            var jsonNewUser = JsonConvert.SerializeObject(newUser);
            var content     = new StringContent(jsonNewUser, Encoding.UTF8, "application/json");

            using (var identityApi = new HttpClient {
                BaseAddress = _identityServerUrl
            })
            {
                identityApi.SetBearerToken(accessToken);

                var requestUrl = (isAdmin ? "api/manage/admin/create" : "api/manage/user/create");
                var result     = await identityApi.PutAsync(requestUrl, content);

                if (!result.IsSuccessStatusCode)
                {
                    var msg = result.Content.ReadAsStringAsync();

                    throw new HttpRequestException($"{result.ReasonPhrase} - {msg.Result}");
                }
            }

            using (var accountsApi = new AccountsApiClient(_accountsApiUrl, accessToken))
            {
                if (!await accountsApi.CreateUser(username))
                {
                    throw new HttpRequestException($"Failed to create user '{username}' on the Accounts system.");
                }
            }
        }
예제 #9
0
        /// <summary>
        /// Submits a request URL to the Accounts API. Contains the retry logic required in order to
        /// deal with expired Access/Refresh Tokens.
        /// </summary>
        /// <param name="invocation">The calling method (Get, Put, or Post).</param>
        /// <param name="requestUrn">The request to be submitted to the Accounts API.
        /// See: <see cref="InvokeApiAsync(HttpClientHelpers.EndPointInvocation,string)"/>
        /// </param>
        /// <param name="userCredentialsCallback">
        /// A delegate that can be invoked to obtain username/password credentials from the user.
        /// </param>
        /// <returns>The response from the Accounts API.</returns>
        ///
        private async Task <HttpResponseMessage> InvokeApiAsync(HttpClientHelpers.EndPointInvocation invocation,
                                                                string requestUrn,
                                                                UserCredentialsCallback userCredentialsCallback)
        {
            // ReSharper disable once NotAccessedVariable
            AccessTokenPair accessTokens;

            //--------------------------------------------------------------------------------------------
            // Have we been authenticated?  Check the Token Manager for an Access Token. If we don't have
            // one, go get one.
            //--------------------------------------------------------------------------------------------

            // ReSharper disable once RedundantAssignment
            if ((accessTokens = TokenManager.GetAccessTokens()).IsNull())
            {
                var(username, password) = await userCredentialsCallback();

                await GetAndStoreApiAccessTokens(username, password);
            }

            // TODO handle failure

            //--------------------------------------------------------------------------------------------
            // We have an Access Token; issue the request to the Accounts API.
            //--------------------------------------------------------------------------------------------

            var response = await InvokeApiAsync(invocation, requestUrn);

            //--------------------------------------------------------------------------------------------
            // Did the request fail?
            //--------------------------------------------------------------------------------------------

            if (!response.IsSuccessStatusCode)
            {
                Console.WriteLine(response.StatusCode);

                //------------------------------------------------------------------------------------------
                // Failed. Was it because our access token timed out?
                //------------------------------------------------------------------------------------------

                if (response.IsAccessTokenExpired())
                {
                    //----------------------------------------------------------------------------------------
                    // Yes. Use our refresh token to get a new access token.
                    //----------------------------------------------------------------------------------------

                    // ReSharper disable once NotAccessedVariable
                    var accessToken = await GetAndStoreApiAccessTokens();

                    //----------------------------------------------------------------------------------------
                    // Re-submit the original request with the new access token.
                    //----------------------------------------------------------------------------------------

                    response = await InvokeApiAsync(invocation, requestUrn);

                    //----------------------------------------------------------------------------------------
                    // Is the Accounts API still reporting an expired token?
                    //----------------------------------------------------------------------------------------

                    if (response.IsAccessTokenExpired())
                    {
                        //--------------------------------------------------------------------------------------
                        // Yes. Apparently, our refresh token has expired too. At this point we must ask the
                        // user to re-authenticate with their username/password. Use the caller-provided
                        // callback to obtain them.
                        //--------------------------------------------------------------------------------------

                        var(username, password) = await userCredentialsCallback();

                        //--------------------------------------------------------------------------------------
                        // Try to get a new access token one more time, using the user's credentials.
                        //--------------------------------------------------------------------------------------

                        // ReSharper disable once RedundantAssignment
                        accessToken = await GetAndStoreApiAccessTokens(username, password);

                        //--------------------------------------------------------------------------------------
                        // Either that worked, or it didn't. Either way, we're done here.  Return the final
                        // response to the caller.
                        //--------------------------------------------------------------------------------------

                        response = await InvokeApiAsync(invocation, requestUrn);
                    }
                }
            }

            return(response);
        }