locked
What is the best way to secure api requests RRS feed

  • Question

  • User389690 posted

    Hello there. Im a c# web developer, and I'm just starting to work with Xamarin. The app I would like to build will need to communicate with a web based application that I already have. I would like to have a login page that will authenticate the user credentials with my web app api.

    my concern is that other app might monitor the requests that coming out the device and get the login information.. is it a possibility?

    Saturday, October 12, 2019 10:52 PM

All replies

  • User383174 posted

    I used "ASP.NET Identity using OAuth" in my application. see this video

    Sunday, October 13, 2019 9:09 AM
  • User389690 posted

    Cant view the video..

    Sunday, October 13, 2019 10:04 AM
  • User383174 posted

    Inside web API

    using Microsoft.Owin;
    using Microsoft.Owin.Security.OAuth;
    using Owin;
    using YourAPI.Providers;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Http;
    
    [assembly: OwinStartup(typeof(YourAPI.Startup))]
    namespace YourAPI
    {
        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                HttpConfiguration config = new HttpConfiguration();
                ConfigureOAuth(app);
                WebApiConfig.Register(config);
                app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
                app.UseWebApi(config);
            }
    
            public void ConfigureOAuth(IAppBuilder app)
            {
                OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
                {
                    AllowInsecureHttp = true,
                    TokenEndpointPath = new PathString("/token"),
                    AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
                    Provider = new SimpleAuthorizationServerProvider()
                };
    
                // Token Generation
                app.UseOAuthAuthorizationServer(OAuthServerOptions);
                app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
    
            }
        }
    }
    

    Inside web API --->Providers folder----> yourprovider class:

    using Microsoft.AspNet.Identity;
    using Microsoft.Owin.Security;
    using Microsoft.Owin.Security.OAuth;
    using Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Claims;
    using System.Threading.Tasks;
    using System.Web;
    using System.Web.Security;
    
    namespace YourAPI.Providers
    {
        public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
        {
            public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
            {
                context.Validated();
            }
    
            public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
            {
                context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
                MembershipUser user = null;
                user = Membership.GetUser(context.UserName);
                if (user == null)
                {
                    context.SetError("invalid_grant", "user not found.");
                    return;
                }
                bool validUser = Membership.ValidateUser(context.UserName, context.Password);
                if (validUser)
                {
                    string[] rolesArr = Roles.GetRolesForUser(context.UserName);
                    string userId = user.ProviderUserKey.ToString();
    
                    ...
    
                    var identity = new ClaimsIdentity(context.Options.AuthenticationType);
                    identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
                    foreach (string role in rolesArr)
                    {
                        identity.AddClaim(new Claim(ClaimTypes.Role, role));
                    }
    
                    List<Claim> roles = identity.Claims.Where(c => c.Type == ClaimTypes.Role).ToList();
                    AuthenticationProperties properties = CreateProperties(user.UserName, JsonConvert.SerializeObject(roles.Select(x => x.Value)), userId, customerId);
    
                    AuthenticationTicket ticket = new AuthenticationTicket(identity, properties);
    
                    context.Validated(ticket);
                }
                else
                {
                    context.SetError("invalid_grant", "The user name or password is incorrect.");
                    return;
                }
    
            }
            public static AuthenticationProperties CreateProperties(string userName, string Roles, string UserID, string CustomerID)
            {
                IDictionary<string, string> data = new Dictionary<string, string>
                {
                    { "userName", userName },
                    { "roles", Roles},
                    { "User_ID", UserID },
                    { "Customer_ID" , CustomerID } //my 
                };
                return new AuthenticationProperties(data);
            }
    
            public override Task TokenEndpoint(OAuthTokenEndpointContext context)
            {
                foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
                {
                    context.AdditionalResponseParameters.Add(property.Key, property.Value);
                }
    
                return Task.FromResult<object>(null);
            }
        }
    
    }
    

    Inside AppStart folder in WebAPI

    using Newtonsoft.Json.Serialization;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Http.Formatting;
    using System.Web.Http;
    using System.Web.Http.Cors;
    
    namespace YourAPI
    {
        public static class WebApiConfig
        {
            public static void Register(HttpConfiguration config)
            {
                config.EnableCors();
                config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
                config.MapHttpAttributeRoutes();
                config.Routes.MapHttpRoute(
                   name: "ControllerAndAction",
                   routeTemplate: "api/{controller}/{action}/{id}",
                   defaults: new { id = RouteParameter.Optional, extension = RouteParameter.Optional }
                );
    
                var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
                jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    
            }
        }
    }
    

    Inside Your API Controller:

    [AcceptVerbs("Get", "Post")]
            [ActionName("YourMethod")]
            [Authorize]
            public HttpResponseMessage YourMethod(string userID)
            {
                int count = users.getUserCompanyCount(userID); //sample
                return new HttpResponseMessage()
                {
                    Content = new StringContent(count.ToString(), Encoding.UTF8)
                };
            }
    

    Inside Your App:

    method with Authentication send AccessToken

    public async Task<int> getYourMethodAsync(string userId, string accessToken)
            {
                var client = new HttpClient();
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
                var content = await client.GetStringAsync(Settings.API_URL + "/api/Account/YourMethod?userId=" + userId);
                var result = int.Parse(content);
                return result;
            }
    
    public class ApiUsers
        {
            public async Task<string> LoginAsync(string userName, string password)
            {
                string result = "";
                try
                {
                    var keyValues = new List<KeyValuePair<string, string>>
                    {
                        new KeyValuePair<string, string>("username", userName),
                        new KeyValuePair<string, string>("password", password),
                        new KeyValuePair<string, string>("grant_type", "password")
                    };
                    var request = new HttpRequestMessage(HttpMethod.Post, Settings.API_URL + "/Token");
                    request.Content = new FormUrlEncodedContent(keyValues);
                    var client = new HttpClient();
                    var response = await client.SendAsync(request);
                    var content = await response.Content.ReadAsStringAsync();
                    JObject jwtDynamic = JsonConvert.DeserializeObject<dynamic>(content);
                    result = content;
                    var accessToken = jwtDynamic.Value<string>("access_token");
                    var accessTokenExpiration = jwtDynamic.Value<DateTime>(".expires");
                    Settings.AccessTokenExpiration = accessTokenExpiration;
                }
                catch (Exception ex)
                {
                    result = ex.Message;
                }
                return result;
            }
    
            public async Task GetNewTokenAsync()
            {
                var keyValues = new List<KeyValuePair<string, string>>
                {
                    new KeyValuePair<string, string>("username", Settings.Username),
                    new KeyValuePair<string, string>("password", Settings.Password),
                    new KeyValuePair<string, string>("grant_type", "password")
                };
                var request = new HttpRequestMessage(HttpMethod.Post, Settings.API_URL + "/Token");
                request.Content = new FormUrlEncodedContent(keyValues);
                var client = new HttpClient();
                var response = await client.SendAsync(request);
                var content = await response.Content.ReadAsStringAsync();
                JObject jwtDynamic = JsonConvert.DeserializeObject<dynamic>(content);
                var accessToken = jwtDynamic.Value<string>("access_token");
                var accessTokenExpiration = jwtDynamic.Value<DateTime>(".expires");
                Settings.AccessToken = accessToken;
                Settings.AccessTokenExpiration = accessTokenExpiration;
            }
    

    In login Page:

    string response = await apiUsers.LoginAsync(username, pass);
                        if (!string.IsNullOrEmpty(response))
                        {
                            JObject jwtDynamic = JsonConvert.DeserializeObject<dynamic>(response);
                            var accessToken = jwtDynamic.Value<string>("access_token");
                            if (!string.IsNullOrEmpty(accessToken))
                            {
                                var user_id = jwtDynamic.Value<string>("User_ID");
                                var customer_id = jwtDynamic.Value<long>("Customer_ID");
                                var rolesJson = jwtDynamic.Value<string>("roles");
                                var roles = JsonConvert.DeserializeObject<List<string>>(rolesJson);
    
                                Settings.AccessToken = accessToken;
                                Settings.Username = username;
                                Settings.Password = pass;
                                Settings.Customer_ID = customer_id.ToString();
                                Settings.User_ID = user_id;
                                Settings.Roles = string.Join(",", roles.ToArray()); 
                            }
                            else
                            {
                                DependencyService.Get<ILodingPageService>().HideLoadingPage();
                                var messsge = "invalid user or password!";
                                DependencyService.Get<IMessage>().ShortTime(messsge);
                            }
    

    hope this helps you.

    Sunday, October 13, 2019 1:38 PM
  • User394988 posted

    @mjdeveloper, Is there any sample code on how to put together these classes you mentioned? Is this the best approach today to I implement signin using OAuth2?

    Tuesday, June 2, 2020 4:53 PM