I have some asp.net core application.
It uses Bearer authentication.
My auth and SignalR seattings. Also I use OpenIddict.
ConfigureServices
services.AddMvc();
...
services.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
{
builder
.AllowAnyMethod()
.AllowAnyHeader()
.AllowAnyOrigin()
.AllowCredentials();
}));
//services.AddSignalR();
services.AddSignalR(hubOptions =>
{
hubOptions.EnableDetailedErrors = true;
});
...
services.AddDefaultIdentity<Account>(opt =>
{
opt.Password.RequiredUniqueChars = 1;
opt.Password.RequireNonAlphanumeric = false;
opt.Password.RequireLowercase = false;
opt.Password.RequireDigit = false;
opt.Password.RequireUppercase = false;
opt.Password.RequiredLength = Account.MinPasswordLength;
opt.Lockout.AllowedForNewUsers = false;
opt.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name;
opt.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject;
opt.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role;
})
.AddUserManager<AccountManager>()
.AddRoles<AccountRole>()
.AddEntityFrameworkStores<ApplicationContext>()
.AddDefaultTokenProviders();
services.AddOpenIddict()
.AddCore(opt =>
{
opt.UseEntityFrameworkCore()
.UseDbContext<ApplicationContext>();
})
.AddServer(opt =>
{
opt.SetAccessTokenLifetime(TimeSpan.FromMinutes(5));
opt.UseMvc();
opt.AllowCustomFlow(WebConstants.AdminGrantType)
.EnableTokenEndpoint("/api/common/auth/Token")
.AllowRefreshTokenFlow()
.DisableHttpsRequirement()
.AcceptAnonymousClients();
});
services.AddAuthentication()
.AddOAuthValidation(options =>
{
options.Events.OnRetrieveToken = context =>
{
context.Token = context.Request.Query["access_token"];
return Task.CompletedTask;
};
});
Configure
app.UseCors("CorsPolicy");
app.UseAuthentication();
app.UseSignalR(routes =>
{
routes.MapHub<SomeHub >("/someHub");
});
AuthAccountTypeAttribute
public class AuthAccountTypeAttribute : AuthorizeAttribute
{
public AuthAccountTypeAttribute(params AccountType[] accountType)
{
if (accountType.Any())
{
Roles = string.Join(',', accountType.Select(x => x.ToString()));
}
AuthenticationSchemes = OAuthValidationDefaults.AuthenticationScheme;
}
}
And directly Hub
[AuthAccountType(AccountType.Admin)]
public class SomeHub : Hub
{
private readonly AccountManager _accountManager;
private readonly IUnitOfWork _unitOfWork;
public SomeHub (AccountManager accountManager, IUnitOfWork unitOfWork)
{
_accountManager = accountManager;
_unitOfWork = unitOfWork;
}
public override Task OnConnectedAsync()
{
return base.OnConnectedAsync();
}
public async Task OnConnectSmth()
{
}
}
If you use authorize attribute like this all works fine, but if SomeHub used without AuthAccountType and OnConnectSmth with
[AuthAccountType(AccountType.Admin)]
public async Task OnConnectSmth()
{
}
It returns 401.
What can I do?
SignalR 1.0.4
.Net Core 2.1
The same issue if I use basic Authorize
[Authorize(AuthenticationSchemes = OAuthValidationDefaults.AuthenticationScheme)]
Or how can I made Anonymous connection in Authorize Hub?
DefaultScheme was not set in ConfigureServices(). And strange rules in Hub.
Fix:
services.AddAuthentication(options => { options.DefaultScheme = OAuthValidationDefaults.AuthenticationScheme; } );
Related
I'm using Identity with framework entity.
I'm trying to seed my database with some data - 1 user, and 1 role.
The role is getting seeded properly and everything is good.
The user is not getting seeded - the issue.
Program.cs file
public class Program
{
public static async Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using var scope = host.Services.CreateScope();
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<DataContext>();
var userManager = services.GetRequiredService<UserManager<AppUser>>();
var roleManager = services.GetRequiredService<RoleManager<AppRole>>();
await context.Database.MigrateAsync();
await Roles.RoleInitalizer(roleManager);
await Seed.SeedUsers(userManager);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred during migration");
}
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Roles.cs file - works as intended
public class Roles
{
public static async Task RoleInitalizer(RoleManager<AppRole> roleManager)
{
var roles = new List<AppRole>
{
new AppRole{Name="User"}
};
foreach (var role in roles)
{
await roleManager.CreateAsync(role);
}
}
}
The seed.cs file - user seeding - the issue is here
public class Seed
{
public static async Task SeedUsers(UserManager<AppUser> userManager)
{
if (await userManager.Users.AnyAsync()) return;
var userData = await System.IO.File.ReadAllTextAsync("Data/Seed/UserSeedData.json");
var users = JsonSerializer.Deserialize<List<AppUser>>(userData);
if (users == null) return;
foreach (var user in users)
{
user.UserName = user.UserName.ToLower();
await userManager.CreateAsync(user, "#Test123456789");
await userManager.AddToRoleAsync(user, "User");
}
}
}
AppUser.cs File
public class AppUser : IdentityUser
{
public ICollection<Hero> Heroes { get; set; }
public ICollection<AppUserRole> UserRoles { get; set; }
}
ConfigureService from startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddAplicationServices(_config);
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "API", Version = "v1" });
});
services.AddCors();
services.AddIdentityServices(_config);
}
AddAplicationServices Function from startup
public static IServiceCollection AddAplicationServices(this IServiceCollection services, IConfiguration config)
{
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<IHeroRepository, HeroRepository>();
services.AddScoped<ITokenService, TokenService>();
services.AddAutoMapper(typeof(AutoMapperProfiles).Assembly);
services.AddControllersWithViews()
.AddNewtonsoftJson(options =>
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
services.AddDbContext<DataContext>(options =>
{
options.UseSqlServer(config.GetConnectionString("DefaultConnection"));
});
return services;
}
AddIdentityServices function from startup.cs
public static IServiceCollection AddIdentityServices(this IServiceCollection services, IConfiguration config)
{
services.AddIdentityCore<AppUser>(opt =>
{
opt.Password.RequireNonAlphanumeric = false;
})
.AddRoles<AppRole>()
.AddRoleManager<RoleManager<AppRole>>()
.AddSignInManager<SignInManager<AppUser>>()
.AddRoleValidator<RoleValidator<AppRole>>()
.AddEntityFrameworkStores<DataContext>();
// services.TryAddSingleton<ISystemClock, SystemClock>();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = "yad2",
ValidIssuer = "yad",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["TokenKey"])),
};
});
services.AddAuthorization(opt =>
{
opt.AddPolicy("RequireUserRole", policy => policy.RequireRole("User"));
});
return services;
}
The UserSeedData.json file
[
{
"UserName": "Test",
"Email": "test#test.com"
}
]
Here is the project stracture
This is the project from GitHub just in case
https://github.com/davidax0204/proj
I'm not able to figure out why the roles getting seeded properly and the user is not.
I double-checked that the seeding file has the correct structure as the table of the app user.
I'm getting dropping the old database and starting the project again and only the role is getting seeded every time.
I have tried to manipulate the Seed file but nothing seems to work for me.
Can someone please explain to me why that issue happens so I can learn from my mistakes?
And how can I solve that issue?
I have created an attribute for action names. I want to get the attribute names in my service. I tried so many solutions but it doesn't return anything.
This is my attribute class:
public class CustomeAttribute : ActionFilterAttribute
{
public string Name { get; set; }
}
This is the action that I used the attribute for:
[Custome(Name ="ُShow courses")]
public IActionResult Index()
{
var course = _courseService.GetAllCourses();
return View(course);
}
This is the method that I want to return the attribute name:
public IList<ActionAndControllerName> AreaAndActionAndControllerNamesList(Assembly asm)
{
var contradistinction = asm.GetTypes()
.Where(type => typeof(Controller).IsAssignableFrom(type))
.SelectMany(type =>
type.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly |
BindingFlags.Public))
.Select(x => new
{
Controller = x.DeclaringType?.Name,
//Action = x.Name,
//Action=x.DeclaringType?.GetCustomAttributes(typeof(CustomeAttribute), false),
//
Action=x.DeclaringType?.CustomAttributes.Where(c=>c.AttributeType==typeof(CustomeAttribute)),
// Action=x.DeclaringType?.GetCustomAttributes(typeof(CustomeAttribute), false),
// Action=x.DeclaringType?.CustomAttributes(typeof(CustomeAttribute), false),
//Action=x.DeclaringType?.GetCustomAttribute(typeof(CustomeAttribute), false),
Action=x.DeclaringType?.GetCustomAttributes<CustomeAttribute>(),
//Action = x.DeclaringType?.GetCustomAttributes().Where(a => a.GetType() ==
typeof(CustomeAttribute))
Area = x.DeclaringType?.CustomAttributes.Where(c => c.AttributeType ==
typeof(AreaAttribute)),
});
}
As I said I tried the solutions above that are commented but none of them worked. What should I do?
You can try to save Name to some place in ActionfilterAttribute.Here is a demo to save data to session in OnActionExecuting method:
TestController:
SomeOtherClass _someOtherClass;
public TestController(SomeOtherClass someOtherClass)
{
_someOtherClass = someOtherClass;
}
[Custome(Name = "Show courses")]
public IActionResult TestActionFilterAttribute()
{
var Name = _someOtherClass.TestGet();
return Ok();
}
SomeOtherClass:
public class SomeOtherClass
{
private readonly IHttpContextAccessor _httpContextAccessor;
private ISession _session => _httpContextAccessor.HttpContext.Session;
public SomeOtherClass(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public string TestGet()
{
return _session.GetString("Custome_Name");
}
}
Startup.cs(IHttpContextAccessor can help get seesion outside controller):
public void ConfigureServices(IServiceCollection services)
{
...
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromDays(1);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<SomeOtherClass, SomeOtherClass>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
...
}
CustomeAttribute:
public class CustomeAttribute: ActionFilterAttribute
{
public string Name { get; set; }
public override void OnActionExecuting(ActionExecutingContext
context)
{
if (Name != null)
{
context.HttpContext.Session.SetString("Custome_Name", Name);
}
}
public override void OnActionExecuted(ActionExecutedContext
context)
{
}
}
result:
I found the solution.I shouldn't have used "DeclaringType" in service.
This is the solution:
var contradistinction = asm.GetTypes()
.Where(type => typeof(Controller).IsAssignableFrom(type))
.SelectMany(type =>
type.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly |
BindingFlags.Public))
.Select(x => new
{
Controller = x.DeclaringType?.Name,
Action = x.GetCustomAttribute<CustomeAttribute>()?.Name,
Area = x.DeclaringType?.CustomAttributes.Where(c => c.AttributeType ==
typeof(AreaAttribute)),
});
I am using MVVM Prism for the Xamarin mobile app.
I created a NetCore 3.1 rest api that serves as the backend to my Xamarin mobile app. I want to be able to debug it locally.
I would like to:
A. Connect to localhost to debug the rest api from the Simulators
B. Also would like to connect to the localhost kestrel from the mobile app itself in debug mode if possible
I am using NetCore Kestrel instead of IIS to host the rest api in the localhost.
I can connect with Postman locally and DEBUG ok in VS using this URL:
https://localhost:44349/api/Accounts/Register
even though I do get a first certificate validation error, but I turned off Certificate validation in POSTMAN to make it work, but when I try to connect to that same URL from the mobile, with the code below I get this error below.
The error is triggered in LoginPageViewModel.cs in the SignInWithFacebookTapped function after calling ApiServices register function:
I have been struggling with this for 2 full days, this is my code:
REST API PROJECT
Program.cs class:
namespace MyAppNamespace
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.Configure<KestrelServerOptions>(
context.Configuration.GetSection("Kestrel"));
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(serverOptions =>
{
// Set properties and call methods on options
serverOptions.Limits.MaxConcurrentConnections = 100;
serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
serverOptions.Limits.MinRequestBodyDataRate =
new MinDataRate(bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10));
serverOptions.Limits.MinResponseDataRate =
new MinDataRate(bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10));
serverOptions.Listen(IPAddress.Loopback, 5000);
serverOptions.Listen(IPAddress.Loopback, 5001,
listenOptions =>
{
listenOptions.UseHttps(",myapphosting.pfx",
"mypassword"); // I did not specify where these files are in the code, it seems to just know?
});
serverOptions.Limits.KeepAliveTimeout =
TimeSpan.FromMinutes(2);
serverOptions.Limits.RequestHeadersTimeout =
TimeSpan.FromMinutes(1);
})
.UseStartup<Startup>();
});
}
}
Startup class:
namespace MyAppNamespace
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddMvc(option => option.EnableEndpointRouting = false)
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
.AddNewtonsoftJson(opt => opt.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Tokens:Issuer"],
ValidAudience = Configuration["Tokens:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"])),
ClockSkew = TimeSpan.Zero,
};
});
services.AddDbContext<MyAppDbContext>(option => option.UseSqlServer("MyConnectionString"));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, MyDbContext myDbContext)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
//else
//{
// app.UseHsts();
//}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
myDbContext.Database.EnsureCreated();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
launchSettings.Json :
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iis": {
"applicationUrl": "http://localhost/MyWebApiName",
"sslPort": 0
},
"iisExpress": {
"applicationUrl": "http://localhost:52080",
"sslPort": 44349
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "api/accounts/register",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"YWAW.WebApi": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api/accounts/register",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
}
}
I followed this tutorial to set up the to bypass the Bypass the certificate security check and grab an insecurehandler on both Android and iOS platforms.
https://learn.microsoft.com/en-us/xamarin/cross-platform/deploy-test/connect-to-local-web-services
XAMARIN FORMS PROJECT
in Constants class(shared project):
public static string BaseAddress =
Device.RuntimePlatform == Device.Android ? "https://10.0.2.2:5001" : "https://localhost:5001"; // here I tried writing the iOS url as in Postman above too, same result
public static string RestUrl = $"{BaseAddress}/api/Accounts/Register";
App.Xaml.cs
public partial class App
{
/*
* The Xamarin Forms XAML Previewer in Visual Studio uses System.Activator.CreateInstance.
* This imposes a limitation in which the App class must have a default constructor.
* App(IPlatformInitializer initializer = null) cannot be handled by the Activator.
*/
public App() : this(null) { }
public App(IPlatformInitializer initializer) : base(initializer) { }
protected override async void OnInitialized()
{
InitializeComponent();
await NavigationService.NavigateAsync("NavigationPage/HomePage");
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterSingleton<IAppInfo, AppInfoImplementation>();
containerRegistry.RegisterForNavigation<NavigationPage>();
containerRegistry.RegisterForNavigation<MainPage, MainPageViewModel>();
containerRegistry.RegisterForNavigation<HomePage, HomePageViewModel>();
containerRegistry.RegisterForNavigation<LoginPage, LoginPageViewModel>();
containerRegistry.RegisterForNavigation<SignUpPage, SignUpPageViewModel>();
containerRegistry.RegisterForNavigation<DefaultCustomActivityIndicatorPage, DefaultCustomActivityIndicatorPageViewModel>();
containerRegistry.RegisterForNavigation<DiscoverDealsTabbedPage, DiscoverDealsTabbedPageViewModel>();
containerRegistry.Register<ApiServices>(); //not sure if I actually should register this too
}
// add for app center analytics and crashes
protected override void OnStart()
{
base.OnStart();
AppCenter.Start("ios=secretkey" +
"uwp={Your UWP App secret here};" +
"android={Your Android App secret here}",
typeof(Analytics), typeof(Crashes));
}
}
LoginPageViewModel.cs
public class LoginPageViewModel : BindableBase
{
private IPageDialogService _dialogService { get; }
private ApiServices _apiService { get; }
public DelegateCommand SignInWithEmailTappedCmd { get; set; }
public DelegateCommand SignInWithFacebookTappedCmd { get; set; }
public DelegateCommand SignInWithGoogleTappedCmd { get; set; }
private IFacebookClient _facebookService = CrossFacebookClient.Current;
private IGoogleClientManager _googleService = CrossGoogleClient.Current;
public INavigationService NavigationService { get; set; }
private readonly ICustomActivityIndicatorPage _customActivityIndicator;
private string _emailAddress;
public string EmailAddress
{
get => _emailAddress;
set => SetProperty(ref _emailAddress, value);
}
private string _password;
public string Password
{
get => _password;
set => SetProperty(ref _password, value);
}
public LoginPageViewModel(ICustomActivityIndicatorPage customActivityIndicator,
IHttpClientHandlerService httpClientHandlerService,
INavigationService navigationService,
IPageDialogService dialogService)
{
_customActivityIndicator = customActivityIndicator;
SignInWithEmailTappedCmd = new DelegateCommand(SignInWithEmailTapped);
SignInWithFacebookTappedCmd = new DelegateCommand(async() => await SignInWithFacebookTapped());
SignInWithGoogleTappedCmd = new DelegateCommand(async() => await SingInWithGoogleTapped());
NavigationService = navigationService;
_dialogService = dialogService;
_apiService = new ApiServices(httpClientHandlerService);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
private async Task SignInWithFacebookTapped()
{
try
{
if (_facebookService.IsLoggedIn)
_facebookService.Logout();
EventHandler<FBEventArgs<string>> userDataDelegate = null;
_customActivityIndicator.InitActivityPage(new DefaultCustomActivityIndicatorPage());
_customActivityIndicator.ShowActivityPage();
userDataDelegate = async (object sender, FBEventArgs<string> e) =>
{
switch (e.Status)
{
case FacebookActionStatus.Completed:
var facebookProfile = await Task.Run(() => JsonConvert.DeserializeObject<FacebookProfile>(e.Data));
// save the user to the db if doesn't exist
UserToRegister user = new UserToRegister
{
Email = facebookProfile.Email,
FirstName = facebookProfile.FirstName,
LastName = facebookProfile.LastName
};
// THIS IS WHERE I TRY TO ACCESS THE LOCALHOST REST API
**var registerOutcome = await _apiService.Register(user);**
await NavigationService.NavigateAsync("DiscoverDealsTabbedPage");
_customActivityIndicator.HideActivityPage();
break;
case FacebookActionStatus.Canceled:
_customActivityIndicator.HideActivityPage();
await _dialogService.DisplayAlertAsync("Facebook Auth", "Canceled", "Ok");
break;
case FacebookActionStatus.Error:
_customActivityIndicator.HideActivityPage();
await _dialogService.DisplayAlertAsync("Facebook Auth", "Error", "Ok");
break;
case FacebookActionStatus.Unauthorized:
_customActivityIndicator.HideActivityPage();
await _dialogService.DisplayAlertAsync("Facebook Auth", "Unauthorized", "Ok");
break;
}
_facebookService.OnUserData -= userDataDelegate;
};
_facebookService.OnUserData += userDataDelegate;
string[] fbRequestFields = { "email", "first_name", "picture", "gender", "last_name" };
string[] fbPermisions = { "email" };
await _facebookService.RequestUserDataAsync(fbRequestFields, fbPermisions);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
finally
{
_customActivityIndicator.HideActivityPage();
}
}
}
ApiServices class:
public class ApiServices
{
private HttpClient httpClient;
private string apiRegisterURL;
private readonly IHttpClientHandlerService _httpClientHandler;
public ApiServices(IHttpClientHandlerService httpClientHandler)
{
#if DEBUG
_httpClientHandler = httpClientHandler;
httpClient = new HttpClient(_httpClientHandler.GetInsecureHandler());
apiRegisterURL = Constants.RestUrl;
#else
httpClient = new HttpClient();
apiRegisterURL = Constants.REGISTER_URL;
#endif
}
/// <summary>
///
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public async Task<RegisterOutcome> Register(UserToRegister user)
{
RegisterOutcome outcome = new RegisterOutcome();
//var httpClient = new HttpClient();
try
{
var json = JsonConvert.SerializeObject(user);
var content = new StringContent(json, Encoding.UTF8, "application/json");
outcome.ResponseMessage = await httpClient.PostAsync(apiRegisterURL, content);
}
catch (Exception ex) // ERROR IS HERE CONNECTION REFUSED
{
outcome.ErrorMessage = ex.Message;
}
return outcome;
}
}
IOS PROJECT:
iOSHttpClientHandlerService.cs:
[assembly: Dependency(typeof(iOSHttpClientHandlerService))]
namespace YWAWMobileApp.iOS.Services
{
public class iOSHttpClientHandlerService : IHttpClientHandlerService
{
public HttpClientHandler GetInsecureHandler()
{
HttpClientHandler handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
{
if (cert.Issuer.Equals("CN=localhost"))
return true;
return errors == System.Net.Security.SslPolicyErrors.None;
};
return handler;
}
}
}
AppDelegate.cs:
public class iOSInitializer : IPlatformInitializer
{
public void RegisterTypes(IContainerRegistry containerRegistry)
{
// Register any platform specific implementations
containerRegistry.Register<ICustomActivityIndicatorPage, iOSCustomActivityIndicatorPage>();
containerRegistry.Register<IHttpClientHandlerService, iOSHttpClientHandlerService>();
}
}
ANDROID project same as IOS.
In your web api project go to Program.cs file and in the CreateWebHostBuilder method add this.
.UseUrls("https://*:5001") // Add your port number or url scheme (http or https) on which your apis running instead of 5001.
Then change you base url like this.
public static string BaseAddress = "https://{here write your local ip address}:5001";
It seems like there is not a lot of information about how to do authorization with the new MVC version. Since ASP 5 now is in RC 1 one could guess that you now can start trying to understand how its going to work...
What I want to do is just a simple example of an auth token that contains the user's name and roles.
A link like http://bitoftech.net/2015/03/11/asp-net-identity-2-1-roles-based-authorization-authentication-asp-net-web-api/ would help greatly but seems hard to find
You can try OpenIddict for that. You need RC2 to use it, but it's quite easy to set up:
public void ConfigureServices(IServiceCollection services) {
services.AddMvc();
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders()
.AddOpenIddict(); // Add the OpenIddict services after registering the Identity services.
}
public void Configure(IApplicationBuilder app) {
app.UseOpenIddict();
}
Sean Walsh posted a detailed walkthrough on his blog: http://capesean.co.za/blog/asp-net-5-jwt-tokens/.
You can use OpenIdConnect.Server. You can set it up like this
Startup.cs
public class Startup {
public IConfigurationRoot configuration { get; set; }
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv) {
IConfigurationBuilder builder = new ConfigurationBuilder();
configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services) {
services.AddIdentity<ApplicationUser, IdentityRole>(options => {
options.User.RequireUniqueEmail = true;
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireUppercase = false;
options.Password.RequireNonLetterOrDigit = false;
options.Password.RequiredLength = 6;
}).AddEntityFrameworkStores<DataModelContext>();
}
public void Configure(IApplicationBuilder app) {
app.UseJwtBearerAuthentication(new JwtBearerOptions {
AutomaticAuthenticate = true,
AutomaticChallenge = true,
Audience = "OAuth:Audience",
Authority = "OAuth:Authority",
RequireHttpsMetadata = false
});
app.UseOpenIdConnectServer(options => {
options.Issuer = new Uri("OpenId:Issuer");
options.AllowInsecureHttp = true;
options.AuthorizationEndpointPath = PathString.Empty;
options.Provider = new AuthorizationProvider();
});
}
}
AuthorizationProvider.cs
public class AuthorizationProvider : OpenIdConnectServerProvider {
public override Task ValidateTokenRequest(ValidateTokenRequestContext context) {
context.Skip();
return Task.FromResult(0);
}
public override Task GrantResourceOwnerCredentials(GrantResourceOwnerCredentialsContext context) {
string username = context.UserName;
string password = context.Password;
UserManager<ApplicationUser> userManager = context.HttpContext.RequestServices.GetRequiredService<UserManager<ApplicationUser>>();
ApplicationUser user = userManager.FindByNameAsync(username).Result;
if (userManager.CheckPasswordAsync(user, password).Result) {
ClaimsIdentity identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme);
identity.AddClaim(ClaimTypes.Name, username,
OpenIdConnectConstants.Destinations.AccessToken,
OpenIdConnectConstants.Destinations.IdentityToken);
List<string> roles = userManager.GetRolesAsync(user).Result.ToList();
foreach (string role in roles) {
identity.AddClaim(ClaimTypes.Role, role,
OpenIdConnectConstants.Destinations.AccessToken,
OpenIdConnectConstants.Destinations.IdentityToken);
}
AuthenticationTicket ticket = new AuthenticationTicket(
new ClaimsPrincipal(identity),
new AuthenticationProperties(),
context.Options.AuthenticationScheme);
ticket.SetResources("OAuth:Audience");
List<string> scopes = new List<string>();
if (context.Request.HasScope("offline_access")) {
scopes.Add("offline_access");
}
ticket.SetScopes(scopes);
context.Validate(ticket);
} else {
context.Reject("invalid credentials");
}
return Task.FromResult(0);
}
}
Then on the Controller or Action you want to use Authorization, you can use the Authorize Attribute like this
[Authorize(Roles = "Administrator")]
public void MyAction() { }
My problem is mocked object doesn't return the value it return null instead
My MSpec UnitTest as follows
public class With_Fake_Data_Service
{
protected static Mock<IMProposalWCFService> _fakeDataService;
protected static FaultContract fault;
private Establish context = () =>
{
_fakeDataService = new Mock<IMProposalWCFService>();
_fakeDataService.Setup(
service =>
service.ReplyToProposal(new ReplyToProposalRequest(Moq.It.IsAny<Proposal>(), Moq.It.IsAny<bool>())))
.Returns(new ReplyToProposalResponse( Moq.It.IsAny<bool>(), fault));
_fakeDataService.Setup(
service => service.ReplyToProposalEmail(new ReplyToProposalEmailRequest(Moq.It.IsAny<string>(), Moq.It.IsAny<bool>())))
.Returns(new ReplyToProposalEmailResponse(Moq.It.IsAny<string>(), fault));
_fakeDataService.Setup(service => service.GetAllProposals(Moq.It.IsAny<GetAllProposalsRequest>()))
.Returns(() => new GetAllProposalsResponse(new List<Proposal>(){new Proposal()}, fault));
_fakeDataService.Setup(service => service.GetAllProposals(Moq.It.IsAny<GetAllProposalsRequest>())).Verifiable();
};
}
public class When_Testing_HomeController_Index : With_Fake_Data_Service
{
protected static HomeController _homeController;
protected static IList<Proposal> _proposals;
private Establish context = () =>
{
_homeController = new HomeController(_fakeDataService.Object);
};
private Because of = () =>
{
var result = _homeController.Index() as ViewResult;
_proposals = result.Model as IList<Proposal>;
};
private It Should_Have_Called_GetAllProposals_At_Least_Once =
() => _fakeDataService.Verify(service => service.GetAllProposals(Moq.It.IsAny<GetAllProposalsRequest>()), Times.Exactly(1));
}
Inside the Actual Code HomeController Index Method I get response as null when running above unit test
public HomeController(IMProposalWCFService service)
{
_service = service;
}
public ActionResult Index()
{
var response = _service.GetAllProposals(new GetAllProposalsRequest());
if (response.fault == null) /*Right Here reponse is null when running unit test*/
{
var proposals = response.GetAllProposalsResult;
}
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
Why am i Not getting not null response in other words why i'm not getting
new GetAllProposalsResponse(new List(){new Proposal()}, fault)
please help
Found the problem its
public class With_Fake_Data_Service
{
protected static Mock<IMProposalWCFService> _fakeDataService;
protected static FaultContract fault;
private Establish context = () =>
{
_fakeDataService = new Mock<IMProposalWCFService>();
_fakeDataService.Setup(
service =>
service.ReplyToProposal(new ReplyToProposalRequest(Moq.It.IsAny<Proposal>(), Moq.It.IsAny<bool>())))
.Returns(new ReplyToProposalResponse( Moq.It.IsAny<bool>(), fault));
_fakeDataService.Setup(
service => service.ReplyToProposalEmail(new ReplyToProposalEmailRequest(Moq.It.IsAny<string>(), Moq.It.IsAny<bool>())))
.Returns(new ReplyToProposalEmailResponse(Moq.It.IsAny<string>(), fault));
_fakeDataService.Setup(service => service.GetAllProposals(Moq.It.IsAny<GetAllProposalsRequest>()))
.Returns(() => new GetAllProposalsResponse(new List<Proposal>(){new Proposal()}, fault)).Verifiable();
};
}