Reputation: 771
I'm using Angular 2 and trying to send a header parameters on get method. I have following code:
let tokenUrl2 = "http://localhost:8080/users";
let headers = new Headers();
headers.append('abc', token);
let options = new RequestOptions({ headers: headers });
return this.http.get(tokenUrl2, options);
I get this error:
Response for preflight is invalid (redirect)
I also added these parameters but I get the same error:
headers.append('Content-Type', 'application/json');
headers.append('Authorization':'Bearer ' + token);
Could anyone tell me what is the right way to send header parameters. Thank you very much :)
EDIT 1
The URL "http://localhost:8080/users" is from spring boot web app (It's a REST service). I'm trying to communicate angular app with spring boot app. My idea is send it a token previousy obtained from another REST service. In a first REST service I got a token. This's a REST service with POST and It works. Then, I send this token to second REST Service (http://localhost:8080/users) through GET method. This second part doesn't work. I tried changed GET method to POST because on the firs part with a POST method do work but this new change neither work. I still getting the same message: Response for preflight is invalid (redirect).
I have these questions:
If my first REST service (implemented with POST) works, why the second doesn't? This is because my request (my angular app) doesn't implement CORS?
I hope wiht this details, you could help me to solve my problem.
Thanks!
EDIT 2
Initially, I thought that I only had an error when send headers parameters to REST service from Angular app. But, I've investigated and I see that my problem envolves more components. I tell about my components:
I have an angular app that need consuming a REST service from Spring boot app. Every REST service need authentication and for that I use JWT.
First. My angular app consumes a authenticate REST service. If this done. REST service return a token.
Second. With this token, angular app can consume another REST services secured with Spring Security.
My error happens on second step. I can't consume others services. I have a custom filter that extends from OncePerRequestFilter and even is not invoked. In angular app I get a message that I reported before:
Response for preflight is invalid (redirect)
As I said in my previous edit. I don't uderstand because the first REST service is invoked but second doesn't. Neither I understand why my custom filter is not invoked. I think that I'm invoking wrong from angular app.
My code:
Custom Filter:
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
private final Log logger = LogFactory.getLog(this.getClass());
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Value("${jwt.header}")
private String tokenHeader;
static final String ORIGIN = "Origin";
@Override
//@CrossOrigin(origins = "*")
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// TODO Auto-generated method stub
logger.info("checking authentication für user ");
String authToken = request.getHeader(this.tokenHeader);
// authToken.startsWith("Bearer ")
// String authToken = header.substring(7);
String username = jwtTokenUtil.getUsernameFromToken(authToken);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
// It is not compelling necessary to load the use details from the database. You could also store the information
// in the token and read it from it. It's up to you ;)
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
// For simple validation it is completely sufficient to just check the token integrity. You don't have to call
// the database compellingly. Again it's up to you ;)
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
logger.info("authenticated user " + username + ", setting security context");
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
filterChain.doFilter(request, response);
}
}
Angular Controller and Service:
import { Component, OnInit } from '@angular/core';
import { LoginService } from './login.service';
interface TokenJson {
token: string;
}
@Component({
selector: 'login',
templateUrl: 'login.component.html',
styleUrls: ['login.scss'],
providers: [LoginService]
})
export class LoginComponent implements OnInit {
private model = {'username':'****', 'password':'****'};
private currentToken:string ;
private tokenJson: TokenJson;
// constructor
constructor(private _loginService: LoginService) {
}
// on-init
ngOnInit() {
debugger;
this._loginService.sendCredential(this.model).subscribe(
data => {
debugger;
//localStorage.setItem("token", JSON.parse(JSON.stringify(data)).token);
// this.currentToken = JSON.parse(JSON.stringify(data))._body;
this.tokenJson = JSON.parse(JSON.stringify(data))._body;
this.currentToken = JSON.parse(JSON.parse(JSON.stringify(data))._body).token;
localStorage.setItem("token", this.currentToken);
this._loginService.sendToken(localStorage.getItem("token")).subscribe(
data => {
//this.currentUserName=this.model.username;
//localStorage.setItem("currentUserName", this.model.username);
debugger;
this.model.username='';
this.model.password='';
},
error => {
debugger;
console.log(error)
}
);
},
error => {
debugger;
console.log(error)
}
);
}
}
import {Injectable} from "@angular/core";
import {Http, Headers, Response, RequestOptions} from '@angular/http';
import {Observable} from 'rxjs/Observable';
@Injectable()
export class LoginService {
token: string;
constructor (private http: Http) {}
sendCredential(model) {
debugger;
let tokenUrl1 = "http://localhost:8080/auth";
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post(tokenUrl1, JSON.stringify(model), {headers: headers});
}
sendToken(token) {
debugger;
let tokenUrl2 = "http://localhost:8080/users";
console.log('Bearer '+token);
let getHeaders2 = new Headers();
getHeaders2.append('Authorization', token);
let headers = new Headers();
headers.append('authorization', token);
return this.http.post(tokenUrl2, {}, options);
}
}
SOLUTION
I've found the problem. The error message got for request of type OPTIONS. I had only avoid that type of requests. I added following configuration to security configuration class:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
}
//
}
PD: I guided from here
Upvotes: 0
Views: 1201
Reputation: 14564
Response for preflight is invalid (redirect)
That sounds more like your server isn't handling the pre-flight request properly.
Are you using CORS? (i.e. are you using ng serve
to run your Angular app, but trying to access a server on a different port/machine?).
Because, based on the error you're getting, I think your backend server isn't set up to handle CORS properly.
Upvotes: 1
Reputation: 1038
let requestOptions = new RequestOptions({
headers: new Headers({
'Content-Type': 'application/json'
}),
method: RequestMethod.Post,
body: {}
});
this.http.request("http://localhost:8080/users", requestOptions)
.map((response: Response) => response.json())
Upvotes: 0