Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular5 - Set cookies returned from spring form login

I am trying to add spring security to an app which is build using angular5 and spring boot 1.5.8. The authentication mechanism I am trying to add is spring boot's formLogin.

I am authenticating the user through rest call, and not through default form action. The login works fine but the subsequent rest calls fails. I am making this rest calls with cookies 'ON' so that it will send cookies to spring app, but still the request fails. The reason is angular doesn't set response cookies returned from authentication.

Set cookies in auth.service.ts's login method once rest is successfull.

How to make angular set the cookies returned from spring security please help....

Here is the code:

login.component.html

<form name="form-signin" (ngSubmit)="login()" #f="ngForm" novalidate>
  <div class="form-group" >
    <label for="username">Username</label>
    <input type="text" class="form-control" id="username" name="username" [(ngModel)]="user.username" />
  </div>
  <div class="form-group">
    <label for="password">Password</label>
    <input type="password" class="form-control" id="password" name="password" [(ngModel)]="user.password" />        
  </div>
  </div>
  <button class="btn btn-lg btn-primary btn-block btn-signin" type="submit">Sign in</button>
</form>

login.component.ts

export class LoginComponent implements OnInit {
  user: User=new User();
  constructor(private authService :AuthService, private router: Router) { }

  ngOnInit() {
  }

  login(){
    this.authService.logIn(this.user).subscribe(data=>{
            this.authService.testRest().subscribe(data=>{
            this.router.navigate(['/dashboard']);
            });
        },err=>{
            this.errorMessage="error :  Username or password is incorrect";
        }
      )
  }
}

auth.service.ts

export class AuthService {
  constructor(public http: HttpClient) { }

  public logIn(user: User){
    const httpOptions = {
    headers: new HttpHeaders({
      'Content-Type':  'application/x-www-form-urlencoded'
    })
    };
    let body = new URLSearchParams();
    body.set('username', user.username);
    body.set('password', user.password);

    return this.http.post(AppComponent.API_URL+"/login" , body.toString() ,  httpOptions)
      .map((response: Response) => {
     //How to make angular set cookies here
      console.log(JSON.stringify(response));
    });
  }

  testRest() {
    return this.http.get(AppComponent.API_URL+"/testRest", { withCredentials: true }) .map((response: Response) => {
      console.log(JSON.stringify(response));
    });
  }
}

WebConfig.java

@Configurable
@EnableWebSecurity
public class WebConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private AppUserDetailsService appUserDetailsService;
    @Autowired
    private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
    @Autowired
    private CustomAuthenticationFailureHandler customAuthenticationFailureHandler;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user")
                .password("password")
                .roles("USER");
    }

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedOrigins("http://localhost:4200");

            }
        };
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.cors()
        .and()
        .authorizeRequests()
        .antMatchers("/login")
        .permitAll()
        .anyRequest()
        .fullyAuthenticated()
        .and()
        .logout()
        .permitAll()
        .logoutRequestMatcher(new AntPathRequestMatcher("/logout", "POST"))
        .and()
       .formLogin().successHandler(customAuthenticationSuccessHandler).failureHandler(customAuthenticationFailureHandler)
        .and()
        .sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
        .and()
        .csrf()
        .disable();
    }
}

TestController.java

public class TestController {

    @CrossOrigin
    @RequestMapping("/testRest")
    public String testRest() {
        Map<String, String> test= new HashMap<>();
        test.put("key", "Test Value");
        return test;
    }
}

pom.xml

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.8.RELEASE</version>
        <relativePath/> 
    </parent>
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.196</version>
        </dependency>
</dependencies>
like image 491
JavaCodeNet Avatar asked Nov 08 '22 05:11

JavaCodeNet


1 Answers

Need to set {withCredentials: true} while making login rest call also.

Instead write an HttpInterceptor.

auth.interceptor.ts

import { Observable } from 'rxjs/Observable';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor() {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    request = request.clone({
      withCredentials: true
  });
  return next.handle(request);
  }
}

And add to providers array of app.module

app.module.ts

import { AuthInterceptor } from './services/auth.interceptor';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpClientModule } from '@angular/common/http';
imports: [
    BrowserModule,HttpClientModule,FormsModule
  ],

providers: [
    {
    provide: HTTP_INTERCEPTORS,
    useClass: AuthInterceptor,
    multi: true,
    }
]
like image 174
JavaCodeNet Avatar answered Nov 11 '22 13:11

JavaCodeNet