25

I am trying to implement basic authorization in Angular 4 using the newly released HttpClient.

I am trying to connect to a Spring application running on Tomcat with exposed REST APIs.

I have the following code in my LoginComponent:

onSubmit(user){
   console.log(user);
   const body = JSON.stringify({username: user.userName, password: user.password});

   let headers = new HttpHeaders();
   headers.append("Authorization", "Basic " + btoa("username:password"));
   headers.append("Content-Type", "application/x-www-form-urlencoded");

   this.http.post('my url here',body, {headers: headers}).subscribe(response => {
         console.log(response);
   }, err => {
      console.log("User authentication failed!");
   });
}

However, the request does not add Authorization header at all.

This is from the Chrome tools Network tab:

enter image description here

What am I doing wrong ? How can I make this work ?


Update 1: Its still not working:

I changed my two lines as below:

headers = headers.append("Authorization", "Basic " + btoa("username:password"));
headers = headers.append("Content-Type", "application/x-www-form-urlencoded");

I am getting header in the request as expected. This is from Chrome:

enter image description here

However, the post call is still failing.

At server side, my code is:

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    String authCredentials = request.getHeader("Authorization");

    if(authCredentials == null) {
        logger.info("Request with no basic auth credentials {}", request.getRequestURL());
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        return;
    }

    // do my stuff
}

Call is never reaching do my stuff. authCredentials is null.

This is from chrome:

enter image description here

How to proceed ?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Vicky
  • 16,679
  • 54
  • 139
  • 232

4 Answers4

31

HttpHeaders is immutable, so you need to assign the result of the function to override the headers object each call.

let headers = new HttpHeaders();
headers = headers.append("Authorization", "Basic " + btoa("username:password"));
headers = headers.append("Content-Type", "application/x-www-form-urlencoded");

Source: Angular Docs

Ben Kolya Mansley
  • 1,768
  • 16
  • 24
  • "assign the result of the function to override the headers object each call". Can you please elaborate on this ? – Vicky Aug 26 '17 at 11:26
  • Look at the code, instead of simply `headers.append()`, you have to do `headers = headers.append()`, as `headers.append()` creates a new headers object, which you were previously not using – Ben Kolya Mansley Aug 26 '17 at 11:28
  • 1
    Oh! sorry! noticed now.. I thought you just pasted my two lines!! will try it.. thanks! – Vicky Aug 26 '17 at 11:33
2

Hi can your backend cors configuration

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class RestConfig {
    @Bean
    public CorsFilter corsFilter() {
         UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("DELETE");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
     }
 }

Your angular request should be like that,

import { Http , Headers, Response } from '@angular/http';
let headers = new Headers();
headers.append("Authorization", "Basic " + btoa("username:password"));
headers.append("Content-Type", "application/x-www-form-urlencoded");

You can also check githup repo sample demo spring mvc with angular2/4

Robert
  • 3,373
  • 1
  • 18
  • 34
1

I was having the same problem and authorization header was not going with post request. This was my authenticate function

authenticate(username, password) {
const headers = new HttpHeaders({ Authorization: 'Basic ' + btoa(username + ':' + password) });

return this.httpClient.post<any>('<your-login-url>',{headers}).pipe(
 map(
   userData => {
    sessionStorage.setItem('username',username);
    return userData;
   }
 )
);

I did not know that post requires second argument as body and third as headers. After coming this question I found it from question itself that I need to send a second argument as blank json because I dont have anything in body.

And here is the correct code for above authenticate function

authenticate(username, password) {
const headers = new HttpHeaders({ Authorization: 'Basic ' + btoa(username + ':' + password) });

return this.httpClient.post<any>('<your-login-url>',{},{headers}).pipe(
 map(
   userData => {
    sessionStorage.setItem('username',username);
    return userData;
   }
 )
);

Which is working fine now.

Mohammad Anas
  • 320
  • 3
  • 6
0

Use RequestOptions to set headers to your post request.

    import { Http,Headers,RequestOptions } from '@angular/http';
    ..
    ..
    let headers = new Headers();
    headers.append("Authorization", "Basic " + btoa("username:password"));
    headers.append("Content-Type", "application/x-www-form-urlencoded");

    let options = new RequestOptions({ headers: headers });
    this.http.post('my url here',body, options).subscribe(response => {
             console.log(response);
       }, err => {
          console.log("User authentication failed!");
       });
Ajit Soman
  • 3,926
  • 3
  • 22
  • 41