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>
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,
}
]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With