Home > Software engineering >  Every call to controller redirects to /Identity/Account/Login even login is success
Every call to controller redirects to /Identity/Account/Login even login is success

Time:07-12

I have two projects one is web api and second is Angular app. I made simple "To do" app, and added Authorize attribute over ToDoController so I can restrict each user can see only their to dos.

Problem which I encountered is when I want to get all to dos per user and inspect call in browser console I see every my request is redirected to Identity/Account/Login even after I successful logged in. I got this message:

Http failure response for https://localhost:7141/Identity/Account/Login?ReturnUrl=/api/to-do

But when I send request via postman everything works fine, but first I need to login via postman and after that if I send get request to localhost:7141/api/to-do I can fetch all to dos for logged user. Why this doesn't work if I go via web app through web browser?

ToDoController.cs

[ApiController]
[Route("api/to-do")]
[Authorize]
public class ToDoController : ControllerBase
{
    private readonly ToDoService _toDoService;
    private readonly UserManager<ApplicationUser> _userManager;
    public ToDoController(ToDoService toDoService, UserManager<ApplicationUser> userManager)
    {
        _toDoService = toDoService;
        _userManager = userManager;
        
    }

    [HttpGet()]
    public async Task<IActionResult> GetAll()
    {
        int.TryParse(_userManager.GetUserId(HttpContext.User), out int _userId);
        return Ok(await _toDoService.GetToDos(_userId));
    }
}

Login method in AccountController

    [HttpPost("login")]
    public async Task<IActionResult> Login([FromBody] LoginModel loginModel)
    {
        var appUser = await _userManager.FindByEmailAsync(loginModel.Email);

        if (appUser == null) return BadRequest("User not registered!");

        var result = await _signInManager.PasswordSignInAsync(appUser.UserName, loginModel.Password, false, false);

        if (result.Succeeded)
        {
            return Ok(new UserModel { Id = appUser.Id, Email = appUser.Email });
        }

        return BadRequest("Invalid login details!");
    }

Program.cs (WebApi)

...
builder.Services.AddDefaultIdentity<ApplicationUser>()
            .AddEntityFrameworkStores<ToDoAngularDbContext>();

builder.Services.AddAuthentication();

builder.Services.AddScoped<ToDoRepository>();
builder.Services.AddScoped<ToDoService>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
   app.UseSwagger();
   app.UseSwaggerUI();
}

app.UseCors(options => options.WithOrigins("https://localhost:44426")
                          .AllowAnyMethod()
                          .AllowAnyHeader()
                          .AllowCredentials());

app.UseHttpsRedirection();

app.UseAuthentication();

app.UseAuthorization();
...

HomeComponent where on ngonInit I go to user to dos.

export class HomeComponent implements OnInit {
 public toDos: ToDoModel[] | null = [];

 private apiUrl: string = this.constants.WEB_API_BASE_URL   
 this.constants.API_TO_DO_ENDPOINT;

 constructor(private http: HttpClient, public authService: AuthenticationService, 
 private snackBar: MatSnackBar, private constants: Constants) {}

 ngOnInit(): void {
    const headers: HttpHeaders = new HttpHeaders();
    headers.set('Content-Type', 'application/json');

 this.http.get<ToDoModel[]>(this.apiUrl, { headers: headers, observe: 'response' 
 }).subscribe(result => {
    if (result) {
      if (result.status == HttpStatusCode.Ok) {
        this.toDos = result.body;
      }
    }
  },
    error => console.error(error));
}
}

CodePudding user response:

After struggling almost whole day with this, with HTTP toolkit application I manage to watch request which I send with my app and postman. Postman request was sent with cookies while my Angular app didn't send cookies.

So I figured I need to set one of angular request properties to true in this case "withCredentials: true".

After I add this in my request everything works fine.

ngOnInit(): void {
const headers: HttpHeaders = new HttpHeaders();
headers.set('Content-Type', 'application/json');

this.http.get<ToDoModel[]>(this.apiUrl, { headers: headers, observe: 'response', withCredentials: true }).subscribe(result => {
    if (result) {
      if (result.status == HttpStatusCode.Ok) {
        this.toDos = result.body;
      }
    }
  },
    error => console.error(error));
}

Also if you use SignInManager to login on your site, you need set withCredential to true in this case too, so you can get cookies from web api.

this.http.post<UserModel>(this.apiUrl   '/login', loginModel, { headers: headers, observe: 'response', withCredentials: true })
  • Related