hi I have created a blazor webassembly project, which uses an API to fetch data and authorize. The authentication works fine, the problem is the app is very slow. For example to login procedure can take up to 5 seconds through the bazor app, while procedure is verry fast if I call the login action through the API. What am I doing wrong? Here is the blazor code for the authentication. I have not included the API code since the authentication is fast thorugh postman
Login.razor
#page "/login"
#inject IAuthService AuthService
#inject NavigationManager NavigationManager
#using System.Net.Http
#inject HttpClient Http
<h1>Register</h1>
<div class="card">
<div class="card-body">
<h5 class="card-title">Please enter your details</h5>
<EditForm Model="UserLoginViewModel" OnValidSubmit="HandleRegistration">
<DataAnnotationsValidator />
<ValidationSummary />
<div class="form-group">
<label for="email">Email address</label>
<InputText Id="email" class="form-control" #bind-Value="UserLoginViewModel.Email" />
<ValidationMessage For="#(() => UserLoginViewModel.Email)" />
</div>
<div class="form-group">
<label for="password">Password</label>
<InputText Id="password" type="password" class="form-control" #bind-Value="UserLoginViewModel.Password" />
<ValidationMessage For="#(() => UserLoginViewModel.Password)" />
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</EditForm>
</div>
</div>
<h2 value="#test" innderHtml="#test" text="#test"></h2>
#code {
string test = "wow";
private UserLoginViewModel UserLoginViewModel = new UserLoginViewModel();
private async Task HandleRegistration()
{
var result = await AuthService.Login(UserLoginViewModel);
if (result.Successful)
{
NavigationManager.NavigateTo("/");
}
}
}
Authservice -> Login-function
public async Task<LoginResult> Login(UserLoginViewModel model)
{
var loginAsJson = JsonSerializer.Serialize(model);
var response = await _httpClient.PostAsync("Account/Login", new StringContent(loginAsJson, Encoding.UTF8, "application/json"));
LoginResult loginResult = JsonSerializer.Deserialize<LoginResult>(await response.Content.ReadAsStringAsync(), new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
if (!response.IsSuccessStatusCode)
return loginResult;
await _localStorage.SetItemAsync("authToken", loginResult.Token);
((ApiAuthenticationStateProvider)_authenticationStateProvider).MarkUserAsAuthenticated(model.Email);
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", loginResult.Token);
return loginResult;
}
Thank you!
This probably is not your issue, but I ran into the same thing recently. My authentication time in Blazor WebAssembly jumped from less a second to several seconds. I tracked it down to denying x-frames.
I think this is only going to affect a hosted Blazor WebAssembly application that is using ASP.NET Identity for Authentication. In other words, anyone that checked Individual Accounts when setting up a hosted project.
As soon as I setup NWebSpec and added this line it became very slow:
app.UseXfo(xfo => xfo.Deny());
I resolved the issue by switching to same origin:
app.UseXfo(xfo => xfo.SameOrigin());
Leaving this here in case anyone else stumbles on this issue.
Related
I have an API that I've created for user registration / authentication, and similar operations. Example post method:
[AllowAnonymous]
[HttpPost("authenticate")]
public IActionResult Authenticate([FromBody]AuthenticateModel model)
{
var user = _userService.Authenticate(model.Username, model.Password);
if (user == null)
return BadRequest(new { message = "Username or password is incorrect" });
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, user.Id.ToString()),
new Claim(ClaimTypes.Role, user.Role)
}),
Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);
// return basic user info and authentication token
return Ok(new
{
user.Id,
user.Username,
Token = tokenString,
});
I now need my front-end to implement my API. So I'd like to call this API from a View. For example, say I want to create a simple login page:
<div class="row">
<div class="col-md-12">
<form method="post" action="">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Username"></label>
<input asp-for="Username" class="form-control" />
<span asp-validation-for="Username" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
</div>
How would I now call the authenticate post method for this login form? As I have a controller which is the API controller, and I have a controller which is the action controller, for the users.
File structure if needed:
File structure
Calling your own web action can be done in mainly two ways:
Native HTML form submission.
AJAX
Native submit reloads your entire page. And address will be changed to the URL or your web action. Typically used as a search function, like:
<form asp-controller="Search" asp-action="Blogs" method="get">
<input type="text" name="question" />
<input type="submit" />
</form>
When the user submit the form with clicking the submit button, the browser will be redirect to /search/blogs?question=textHeInput.
To prevent page refreshing, you can submit a request with pure JavaScript. Which called AJAX.
https://en.wikipedia.org/wiki/Ajax_(programming)
For example:
// Require jQuery:
$.post('/authenticate', { "yourPropertyName" : "yourPropertyValue" }, function(response) {
// Do something after the request. Access response like this:
alert(response.Username);
});
And server responded username will shown.
You can use ASP.NET MVC Core Tag Helpers:
<form asp-controller="MyControllerName" asp-action="Authenticate" method="post">
<!-- Input and Submit elements -->
</form>
Since you're using JwtBearer with WebAPI's, an assumption is that you're probably going to call your authentication method using Ajax. Unfortunately you did not provide your class declaration showing your route convention for your ApiClass but normally it goes as "api/[Controller]"... If this is the case, you can do the following:
$("submitButton").click(
function authenticateUser()
{
$.post(
'/api/[COntrollerName]/authentication', // URL
$('#form").serialize(), // this is your form data as an object
function(payload) //Response
{
// do something with payload here
}
});
}
);
<button type="submit" class="btn btn-primary" id="submitButton">Login</button>
You might want to set your <button type="button"> so that the form doesn't submit. Attach a click event to that function, so that it processes the api call.
I'm trying follow the guide from angularfire2 docs on github, but when I try to open the popup window for google login it just closes instantly.
I've tried with different browsers, but I can't figure out what's going on.
Here's the HTML of my form component:
<div class="container " >
<h2 class="date">Wallet manager</h2>
<h1>SUBBO</h1>
<form>
<div class="form-group">
<label class="date" for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter email">
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div class="form-group">
<label class="date" for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
</div>
<button type="submit" (click)="login()" style="margin-top:20px" class="btn btn-outline-warning">Login</button>
<button type="submit" (click)="logout()" style="margin-top:20px" class="btn btn-outline-warning">Logout</button>
</form>
</div>
and here is the code:
import { Component, OnInit } from '#angular/core';
import { AngularFireAuth } from 'angularfire2/auth';
import * as firebase from 'firebase/app';
#Component({
selector: 'app-login-form',
templateUrl: './login-form.component.html',
styleUrls: ['./login-form.component.css']
})
export class LoginFormComponent implements OnInit {
constructor(public afAuth: AngularFireAuth) {
}
login() {
this.afAuth.auth.signInWithPopup(new firebase.auth.GoogleProvider());
}
logout() {
this.afAuth.auth.signOut();
}
ngOnInit() {
}
}
With the login button I call Login() and I was expecting the window to popup and stay there, but it close immediately.
I've uploaded the project to Firebase and it give's me the same problem:
https://subbo-wallet-manager.firebaseapp.com/
I had this same problem using Firebase Authentication. The solution for me was to go into the Firebase Control Panel, select my project, select authentication and under "Sign-in method" I had to add my domain to the authorized domain list. Once I did that, and reloaded the page, it worked.
The fire base documentation gives me this example:
firebase.auth().signInWithPopup(provider).then(function(result) {
// This gives you a Google Access Token. You can use it to access the Google API.
var token = result.credential.accessToken;
// The signed-in user info.
var user = result.user;
// ...
}).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
});
Your problem might be the missing then() (it might make it async, not sure). If my guess is wrong, you may still use the catch part to see if any errors occured. Maybe the provider is not valid.
I had the same issue but in my case the login just was failing for Google Chrome, so I tried to update Google Chrome version to the latest one and the login started to work fine again.
the name of God
and Hi to you
I created some login pages in asp.net
i want use SHA-1 algoritm for my passwords, it's mean, controller get password then send to SHA-1 function and then save it to db.
first: I have these cods in cshtml
<input type="text" name="Username" required="required" />
<label for="Username">Username</label>
<div>
<input type="password" name="Password" required="required"/>
<label for="Password">Password</label>
</div>
<div type="submit" class="button-container">
<button><span>Go</span></button>
</div>
after submit username and pass will be checked and if those be true an new page will be open and user login happen successfully but I don't have any idea about to show my login happened, let explain it whit a sample
I submit my login page and then this page will be open :http://localhost:19926/Home/Home because I used these codes(%1)
in html:
#using (Html.BeginForm("webAdminAccess", "Authentication")){
...myhtml codes...}
in controller:
public ActionResult webAdminAccess(string Username, string Password)
{
if (mLO.webAdminAccess(Username, Password))
{
return RedirectToAction("Home", "Home");
}
else
{
return View("webAdminAccessWrong");
}
}
and there is no difference if I run my project in visual and I put this link http://localhost:19926/Home/Home in my brower(%2)
now let me ask my question:
how make a difference between these two?(%1,%2)
what is Characteristic or Proprietary of a page that was open whit a login?
how make a difference between login as admin or login as client?
(I have admin class, authenticationController and use my sql)
tnx for you help
I hope someone can help me with this...
I'm working on osx on a new small project and "getting to know" the new vNext with MV6 and Entity Framework 7, with mono, kestrel, and using sublime text for the coding...
I have a very simple form:
<div class="login-form-outer">
#using (Html.BeginForm("Login2", "Account", null, FormMethod.Post, new { #class = "form-horizontal", role = "form", #autocomplete="off" }))
{
#Html.AntiForgeryToken()
<h4>Use a Local Account to log in.</h4>
<hr>
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(m => m.Name, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Name, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Name)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Log in" class="btn btn-default" />
</div>
</div>
} </div>
</div>
The form submits, the action "Login2" gets called, but the parameter never reaches the action...
This is the action BTW.
[HttpPost]
[AllowAnonymous]
public IActionResult Login2([FromBody] string Name)
{
Console.WriteLine(Name);
Console.WriteLine("Login2");
return RedirectToAction("Index", "Home");
}
The only thing the console shows is "Login2", and the redirection also works.
The thing is...
I have a virtual machine running a SQL Server database... I installed visual studio 2015 there, and executed the exact same project (shared folder) using WEB, KESTREL, and IIS, and they all worked! The parameter gets printed in the console...
So I don't really know where the problem is... is it mono? is it kestrel on OSX?... please help!
I usually work with Rails and Laravel, I'm a noob here...
Thanks in advance.
I don't really know with mvc6 but with mvc5 a simple string parameter was sent in the query string.
Did you tried to remove the
[FromBody]
EDIT:
In MVC5 a simple string parameter can be sent through a form post, a query string or a route value.
I try to validate a simple form. The validation is well executed but the result page doesn't display the errors.
I use velocity to render the page.
I've used as example the PetClinic project from spring website.
Here is my controller when I hit the "post form" button:
#Controller
#RequestMapping("/subscription")
public class SubscriptionController {
#RequestMapping(value = "/newCustomer", method = RequestMethod.POST)
public String processSubmit(#ModelAttribute Customer customer, BindingResult result, SessionStatus status) {
new CustomerValidator().validate(customer, result);
if (result.hasErrors()) {
return "subscription";
}
else {
status.setComplete();
return "redirect:/admin";
}
}
}
When I go in debug, I see the errors. I'm successfully redirected on the subscription page but the errors are not displayed.
My webpage (simplified):
...
#springBind("customer")
#springShowErrors("<br/>" "")
<form class="form-horizontal" method="post" action="#springUrl("/subscription/newCustomer/")">
....
<!-- Button -->
<div class="controls">
<button class="btn btn-primary">#springMessage("website.subscription.signup")</button>
</div>
</form>
...
if you need anything else, don't hesitate to tell me. Thanks for your help! I'm stuck on this since several days.
EDIT :
I finally found the error. It was with the springBind tag. I didn't well understand that you need to bind the field to show the associated error. Here is the fixed code for one field for twitter bootstrap framework.
#springBind("customer.name")
<div class="control-group #if(${status.error})error#end">
<!-- Prepended text-->
<label class="control-label">#springMessage("website.subscription.name")</label>
<div class="controls">
<div class="input-prepend">
<span class="add-on"><i class="icon-user"></i></span>
<input class="input-xlarge"
placeholder="John Doe" id="name" name="name" type="text">
</div>
<p class="help-block">
#springShowErrors("<br/>" "")
</p>
</div>
</div>
springShowErrors(...) will show all the errors associated with the field name of the POJO customer.