2

I have the following @RestContoller for login:

  @RequestMapping("/account/login")
@ResponseBody
@CrossOrigin(origins = "*", maxAge = 3600)
public Principal login(Principal principal) {
    logger.info("user logged " + principal.getName());
    return principal;
}

I have the following request made by client which is an Angularjs application.

Accept: application/json
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,fa;q=0.8,it;q=0.7
Authorization: Basic bWVocmRhZGFsbGFoa2FyYW1pQGdtYWlsLmNvbTptZWhyZGFk
Connection: keep-alive
DNT: 1
Host: localhost:8080
Origin: http://localhost:4200
Referer: http://localhost:4200/login
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36

However I get 200 in response, the server prints null and the client get error in response:

HttpErrorResponse {headers: HttpHeaders, status: 400, statusText: "OK", url: "http://localhost:8080/account/login", ok: false, …}error: {timestamp: 1540136257516, status: 400, error: "Bad Request", exception: "org.springframework.web.bind.ServletRequestBindingException", message: "Missing request header 'header' for method parameter of type Header", …}headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}message: "Http failure response for http://localhost:8080/account/login: 400 OK"name: "HttpErrorResponse"ok: falsestatus: 400statusText: "OK"url: "http://localhost:8080/account/login"__proto__: HttpResponseBase

Can anyone help me know where do I wrong? It was working before, but I used interceptors in Angular and it is not working anymore.

My login controller is this:

@Injectable()
export class AuthService {
  constructor(public http: HttpClient, public auth: InterceptorAuthService) {
  }

  public logIn(user: User) {
    this.auth.setUser(user);
    return this.http.get(AppComponent.API_URL + "/account/login")
      .pipe(
        map(response => {
            // login successful if there's a jwt token in the response
            let user = response;// the returned user object is a principal object
            if (user) {
              // store user details  in local storage to keep user logged in between page refreshes
              localStorage.setItem('currentUser', JSON.stringify(user));
            }
          },
          catchError(error => {
            return Observable.throw(error);
          })
        ));
  }
}

WebConfig.java configuration:

// This method is used for override HttpSecurity of the web Application.
// We can specify our authorization criteria inside this method.
@Override
protected void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    // ignoring the guest's urls "
    http.antMatcher("/account/**").authorizeRequests().anyRequest().authenticated().and()
            .antMatcher("/token").authorizeRequests().anyRequest().authenticated()
            .antMatchers("/logout").permitAll()
            .and()
            .csrf()
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
            .httpBasic();
    // authenticate all remaining URLS

    // @formatter:on
}
Zibrash
  • 23
  • 1
  • 4
  • Did you read https://stackoverflow.com/questions/31159075/how-to-find-out-the-currently-logged-in-user-in-spring-boot? – dur Oct 21 '18 at 17:18
  • @ChirdeepTomar Yes I actually work with basic security principal, but is is null. Do you any other security methods I can use? I work on it for a day and no logical result I could get yet – Zibrash Oct 21 '18 at 19:09
  • @dur Yes, all the solution I get NullExeption – Zibrash Oct 21 '18 at 19:09
  • I would be curious to know what SecurityContextHolder.getContext().getAuthentication() gives you in login controller method where you are trying to fetch the Principle. Check if your securityContext is getting set correctly or not before you go any further – Hary Oct 21 '18 at 20:22
  • @dur The client URL is http://localhost:4200/login and server URL to accept this request is http://localhost:8080/account/login – Zibrash Oct 21 '18 at 22:22
  • @Hary `SecurityContextHolder.getContext().getAuthentication()` returns me `null` – Zibrash Oct 21 '18 at 22:24
  • Try opening it for all routes i.e. http.antMatcher("/**") – Hary Oct 22 '18 at 05:53
  • I assume you've got `@EnableWebSecurity` on your `WebConfig` class, right? If you breakpoint your `configure()` method do you see it getting hit? – Andy Brown Oct 22 '18 at 09:05

2 Answers2

0
@Component
public class MyBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
@Override
public void afterPropertiesSet() throws Exception {
    setRealmName("Baeldung");
    super.afterPropertiesSet();
}
@Override
public void commence(
  HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx) 
  throws IOException, ServletException {
    response.addHeader("WWW-Authenticate", "Basic realm="" + getRealmName() + """);
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    PrintWriter writer = response.getWriter();
    writer.println("HTTP Status 401 - " + authEx.getMessage());
}
}

// inside filter we can get the 
SecurityContextHolder.getContext().getAuthentication().getPrincipal()
venkey
  • 66
  • 6
0

Try adding sec:authorize="isAuthenticated() to "/account/login" template where you want to display the username

For Example:

<h3 sec:authorize="isAuthenticated()" th:text="${user.username}"></h3>  

It would get the the state of authentication if it has happened, else, it would not display the <h3> block of code.

Nirav Patel
  • 1,297
  • 1
  • 12
  • 23
  • OP mentioned using Angular and not Thymeleaf. Additionally, he's asking about spring security and its configurations – ButtahNBred Mar 19 '23 at 15:10