Search code examples
asp.netangularauthenticationhttpclientaccess-token

Angular 5 authenticate with web api


i try to post my login credentials to my asp.net core web api. but every time i do this i get this message.

OPTIONS XHR http://localhost:64989/api/auth/login [HTTP/1.1 415 Unsupported Media Type 16ms]

ERROR Object { headers: Object, status: 0, statusText: "Unknown Error", url: null, ok: false, name: "HttpErrorResponse", message: "Http failure response for (unknown …", error: error }

my code looks like this on Angular side:

login( email:string, password:string ) :Observable<boolean>{

  return this.http.post('http://localhost:64989/api/auth/login', {email, password}, {headers: new HttpHeaders().set('Content-Type', 'application/json')})
   .map(data => {
     let userAuth = data;
     if(userAuth){
       localStorage.setItem('currentUser', JSON.stringify(userAuth));
       return true;
     }else{
       return false;
     } 
   });
}

On server side i've got a web api which should check the login credentials. this works with postman but not with angular. The Web Api is made with Asp.net core 2.

 [AllowAnonymous]
    [HttpPost("CreateToken")]
    [Route("login")]
    public async Task<IActionResult> Login([FromBody] LoginDTO model)
    {
        try
        {
            var user = await _userManager.FindByNameAsync(model.Email);
            if (user == null)
            {
                return Unauthorized();
            }

            var signInResult = await _signInManager.CheckPasswordSignInAsync(user, model.Password, false);

            if (signInResult.Succeeded)
            {
                var userClaims = await _userManager.GetClaimsAsync(user);

                var claims = new[]
                {
                    new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
                    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                    new Claim(JwtRegisteredClaimNames.Email, user.Email)
                }.Union(userClaims);

                var symmetricSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JwtToken:Key"]));
                var signingCredentials = new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256);

                var jwtSecurityToken = new JwtSecurityToken(
                    issuer: _configuration["JwtToken:Issuer"],
                    audience: _configuration["JwtToken:Audience"],
                    claims: claims,
                    expires: DateTime.UtcNow.AddMinutes(60),
                    signingCredentials: signingCredentials
                    );
                return Ok(new
                {
                    token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken),
                    expiration = jwtSecurityToken.ValidTo
                });
            }
            return Unauthorized();
        }
        catch (Exception ex)
        {
            _logger.LogError($"error while creating token: {ex}");
            return StatusCode((int)HttpStatusCode.InternalServerError, "error while creating token");
        }
    }

Solution

  • I think i found a way how it works for me in development. not production.

    The problem was on the Web API. if you come from a different source to your web api it won't awnser. in my case if i try to call my web api from client side app on http://localhost:4200/ and my web api is running on http://localhost:64989 i will come to this issue i had. if your client side app and server side app is under the same domain you won't have any problem. I will have it in the same domain in production. So i still need a workaround for dev.

    in my ASP.NET core app i can add CORS(Cross Origin resource sharing) to Startup.

      public void ConfigureServices(IServiceCollection services)
      {
            services.AddCors();
            //add cors bevor mvc
            services.AddMvc();
      }
    
     public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
    
            loggerFactory.AddConsole();
    
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
    
                app.UseCors(builder =>
                    builder.AllowAnyOrigin()
                           .AllowAnyMethod()
                           .AllowAnyHeader());
            }
    
    
            app.UseAuthentication();
    
    
            app.UseMvc();
        }
    

    define use cors in IsDevelopment. here you can define which origin is allow and which isn't. i allow any for dev because i won't have this issue in production.