I have an angular project where I implemented a login function in the login.service.ts.My problem is that no matter what I do I can't get rid of the 405 error Method not Allowed for POST.When I check Postman for the API it gives me the same error and it displays only DELETE and PUT as allowed methods.This is the service class:
import { Injectable } from '@angular/core';
import {Register} from '../Models/register';
import { HttpClient, HttpHeaders, HttpErrorResponse} from '@angular/common/http';
import { BehaviorSubject, Observable, throwError } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { Router } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class LoginService {
headers = new HttpHeaders().set('Content-Type', 'application/json;charset=utf-8').append('Authorization', 'Bearer');
currentUser = {};
ApiUrl = 'https://localhost:5001';
constructor(private http: HttpClient, public router: Router) {
}
login(user: Register) {
return this.http.post(this.ApiUrl + '/register/login', user)
.subscribe((res: any) => {
localStorage.setItem('access_token', res.token);
this.getUserProfile(res.id).subscribe((res) => {
this.currentUser = res;
this.router.navigate(['/register/userdata/' + res.msg.id]);
});
});
}
getToken() {
return localStorage.getItem('access_token');
}
get isLoggedIn(): boolean {
const authToken = localStorage.getItem('access_token');
return (authToken !== null) ? true : false;
}
doLogout() {
const removeToken = localStorage.removeItem('access_token');
if (removeToken == null) {
this.router.navigate(['login']);
}
}
getUserProfile(id): Observable<any> {
const api = this.ApiUrl + 'register/userdata/' + id;
return this.http.get(api, { headers: this.headers }).pipe(
map((res: Response) => {
return res || { };
}),
catchError(this.handleError)
);
}
handleError(error: HttpErrorResponse) {
let msg = '';
if (error.error instanceof ErrorEvent) {
msg = error.error.message;
} else {
msg = `Error Code: ${error.status}\nMessage: ${error.message}`;
}
return throwError(msg);
}
}
This is the login.component.ts:
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { LoginService } from '../services/login.service';
import { first } from 'rxjs/operators';
import {ToastrManager} from 'ng6-toastr-notifications';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
loading = false;
submitted = false;
returnUrl: string;
constructor(private formBuilder: FormBuilder,
private route: ActivatedRoute,
private router: Router,
private loginService: LoginService,
public toast: ToastrManager, ) { }
ngOnInit() {
this.loginForm = this.formBuilder.group({
email: ['', Validators.required],
password: ['', Validators.required]
});
}
get loginFormControl() {return this.loginForm.controls; }
onSubmit() {
this.submitted = true;
if (this.loginForm.invalid) {
return;
}
this.loading = true;
this.loginService.login(this.loginForm.value);
this.toast.successToastr('Its working');
this.router.navigate(['register/userdata/id']);
}
}
I recreated a couple of versions from the internet with the client side authentication but gave me the same error over and over no matter what version I used.
I have no clue why it's not working,I'm struggling for some time with the error and I tried almost every possible combination to make it work.Does someone have any idea about this problem and how can be resolved? Any help would be appreciated!!!
UPDATE:
This is the server controller class:
[EnableCors]
[Authorize]
[ApiController]
[Produces("application/json")]
[Route("[controller]")]
public class LoginController : ControllerBase
{
private readonly IConfiguration _config;
public LoginController(IConfiguration config)
{
_config = config;
}
private List<Register> appUsers = new List<Register>();
[AllowAnonymous]
[HttpPost]
[Route("login")]
public IActionResult Login([FromBody] Register model)
{
IActionResult response = Unauthorized();
Register user = AuthenticateUser(model);
if (user != null)
{
var tokenString = GenerateJWT(user);
response = Ok(new
{
token = tokenString,
userDetails = user,
});
}
return response;
}
string GenerateJWT(Register user)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:SecretKey"]));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.Email),
new Claim("Name", user.Name.ToString()),
new Claim("role",user.Role),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Audience"],
claims: claims,
expires: DateTime.Now.AddMinutes(30),
signingCredentials: credentials
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
Register AuthenticateUser(Register login)
{
Register user = appUsers.SingleOrDefault(x => x.Email == login.Email && x.Password == login.Password);
return user;
}
}
This is the Register.cs class:
public class Register
{
public string Role { get; set; }
public string Name { get; set; }
[Key]
public int Id { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
What I have tried:
I tried to assign email and password to the function and get their values with JSON.stringify(),I tried to change the header to allow POST method but then I realised I already did that in my CORS middleware class to which method I pass it in Startup.cs.(server side).When I put breakpoints to debug it,I have no problem with it as it actually reads the info inputted but in login.service.ts when I hit the breakpoint at
localStorage.setItem('access_token', res.token);
on localStorage it gives me the length 0 and after isLoggedIn boolean is set to false as it won't login.I don't know how relevant is this but I also get this upon setting breakpoints(when i look at methods):
TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them.
I understood that this is usually caused by the syntax 'use strict' but I don't have any js I have to worry about.