I try to get token but it not works. Request work in postman, but when I try reproduce this in angular I getting:
My request in postman:
My request in angular:
getToken() {
const headers = new HttpHeaders();
headers.set('Authorization', 'Basic ZGV2Z2xhbi1jbGllbnQ6ZGV2Z2xhbi1zZWNyZXQ=');
headers.set('Content-Type', 'application/x-www-form-urlencoded');
const body = new URLSearchParams();
body.append('username', 'Alex123');
body.append('password', 'password');
body.append('grant_type', 'password');
this.http.post<AuthToken>('http://localhost:8080/oauth/token', body, {headers: headers})
.subscribe(
success => {
debugger
this.token = success.access_token;
}
);
}
my CORS configure, i thing all is good with it.:
#Throws(Exception::class)
override fun configure(http: HttpSecurity) {
http
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/api-docs/**").permitAll()
http
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/auth/token").permitAll()
}
#Bean
fun corsFilter(): FilterRegistrationBean<*> {
val source = UrlBasedCorsConfigurationSource()
val config = CorsConfiguration()
config.allowCredentials = java.lang.Boolean.TRUE
config.addAllowedOrigin("*")
config.addAllowedHeader("*")
config.addAllowedMethod("*")
source.registerCorsConfiguration("/**", config)
val bean = FilterRegistrationBean(CorsFilter(source))
bean.order = 0
return bean
}
It seems you have issues with CORS, please read the following article about to learn more about CORS.
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
This answer should be an comment, but I'm unable to comment..
Related
I'm trying to get a value from my rest api but for some reason it not letting me get it from an authorize user but when i set it permitAll() it does. I'm receiving a 403 error code.
Backend
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests().antMatchers(HttpMethod.GET,"/token/refresh/**").hasAnyAuthority("ROLE_USER");
http.authorizeRequests().antMatchers(HttpMethod.GET,"/api/user/**").hasAnyAuthority("ROLE_USER");
http.authorizeRequests().antMatchers(HttpMethod.GET,"/api/user/{username}/**").hasAnyAuthority("[ROLE_ADMIN]");
http.authorizeRequests().antMatchers(HttpMethod.POST,"/api/user/save/**").hasAnyAuthority("ROLE_ADMIN");
http.authorizeRequests().antMatchers("/api/login/**","/api/user/save/**","/api/role/addtouser/**").permitAll();
http.authorizeRequests().anyRequest().authenticated();
http.addFilter(customAuthenticationFilter);
http.addFilterBefore(new CustomAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
http.httpBasic();
Front-End
here is the request is being send.
getUserId(username) {
this.http.get(`http://localhost:8080/api/user/${username}`).subscribe(
resp=>{
sessionStorage.setItem("id",resp.toString())
}
)
}
Interceptor
this is my interceptor i think it's adding it to the header
export class HttpInterceptorInterceptor implements HttpInterceptor {
constructor(private authrnticationService: AuthenticationServiceService, private router:Router) {}
intercept(req: HttpRequest<any>, next: HttpHandler){
let httpHeaders = new HttpHeaders();
let basicAuthHeaderString=this.authrnticationService.getAuthenticatedtoken();
let username= this.authrnticationService.getEmail();
if (!req.headers.has('Content-Type')) {
httpHeaders = httpHeaders.append('Content-Type', 'application/x-www-form-urlencoded')
}
if (basicAuthHeaderString) {
httpHeaders = httpHeaders.append('Authorization', basicAuthHeaderString)
}
const xhr=req.clone({
headers: httpHeaders
})
return next.handle(xhr).pipe(tap(() => {},
(err: any) => {
if (err instanceof HttpErrorResponse) {
if (err.status !== 401) {
return;
}
sessionStorage.clear()
this.router.navigate(['login']);
}
}));
}
}
I would like to post using Axios to my Spring Boot server. If I disable csrf using .csrf().disable() it works correctly however it fails when enabled.
I've tried adding X-CSRF-TOKEN to the header, or _csrf in the body but it is saying it is invalid. Checking the request the csrf is being passed in as expected.
CSRF Controller
#RequestMapping("/csrf")
public String csrf(final CsrfToken token) {
return token.getToken();
}
Spring Security
httpSecurity
.antMatcher("/api/**")
.cors().and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
Axios
axios
.post(
`/api/doSomething`,
{ id: id, _csrf: csrf},
{
withCredentials: true,
headers: {
'X-CSRF-TOKEN': csrf
}
}
)
.then(response => {
resolve(response.data);
})
.catch(error => {
reject(error);
});
MetaTags react-meta-tags store the CSRF
<MetaTags>
<meta name="csrf-token" content={csrfToken} />
</MetaTags>
Axios to get the CSRF token
axios
.get('/csrf', {
withCredentials: true
})
.then(response => {
resolve(response.data);
})
.catch(error => {
reject(error);
});
Function to get the CSRF token from the meta tags
function getCSRFFromPage(): string | null {
const element = document.querySelector("meta[name='csrf-token']");
if (element !== null) {
const csrf: string | null = element.getAttribute('content');
return csrf;
} else {
return null;
}
}
Error
Invalid CSRF token found for <url>
What could be causing this to fail?
There are two possible causes.
First of all, the CSRF token endpoint should match the Spring Security configuration. In your example, you're using antMatcher("/api/**"), but CSRF token endpoint is /csrf. This should likely become /api/csrf.
The second part is that the CSRF token changes after each request. You didn't show the code where you invoke getCSRFFromPage(), but this should happen before each call you make. If not, then only the first call with that CSRF token will succeed. All consecutive calls will fail.
If you don't like making an additional call with each request, then you can use the CookieCsrfTokenRepository:
httpSecurity
// ...
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
By doing so, each time you make a request, you'll get an XSRF-TOKEN cookie containing the next CSRF token. This should be passed within the X-CSRF-TOKEN or X-XSRF-TOKEN header. Many libraries, including Axios do this out of the box, so you don't have to do anything else.
You can customize this behavior by configuring the xsrfHeaderName or xsrfCookieName properties (see Request Config).
I am working on application to learn something more about jwt authentication and I have problem with registration.
I put signup url in antMatchers to permittAll but it does not work. Here is the code:
const val AUTH_LOGIN_URL = "/library/authenticate"
const val SIGN_UP_URL = "/library/signup"
Security Config :
override fun configure(http: HttpSecurity?) {
http?.cors()?.and()
?.csrf()?.disable()
?.authorizeRequests()
?.antMatchers(SIGN_UP_URL, AUTH_LOGIN_URL)?.permitAll()
?.anyRequest()?.authenticated()
?.and()
?.exceptionHandling()?.authenticationEntryPoint(authenticationEntryPoint)
?.and()
?.sessionManagement()
?.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
http?.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter::class.java)
}
Jwt filter:
#Component
class JwtRequestFilter(
#Autowired
val jwtTokenProvider: JwtTokenProvider,
#Autowired
val customUserDetailsService: CustomUserDetailsService
) : OncePerRequestFilter() {
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
var username: String
var jwtToken = getJwtFromRequrst(request)
try {
if (!StringUtils.isEmpty(jwtToken)) {
username = jwtTokenProvider.getUsernameFromToken(jwtToken)
val userDetails = customUserDetailsService.loadUserByUsername(username)
val authentication = UsernamePasswordAuthenticationToken(userDetails, null, emptyList())
authentication.details = WebAuthenticationDetailsSource().buildDetails(request)
SecurityContextHolder.getContext().authentication = authentication
}
} catch (e: Exception) {
logger.error("Could not set user authentication in security context", e)
}
filterChain.doFilter(request, response)
}
private fun getJwtFromRequrst(request: HttpServletRequest): String {
val bearerToken = request.getHeader(TOKEN_HEADER)
if (!StringUtils.isEmpty(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) {
return bearerToken.substring(7, bearerToken.length)
}
return ""
}
}
Entry point:
#Component
class WebSecurityEntryPoint: AuthenticationEntryPoint {
override fun commence(request: HttpServletRequest?, response: HttpServletResponse?, authException: AuthenticationException?) {
response?.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Access denied")
}
}
Using SIGN_UP_URL I always receive 401. Could you help me?
Ok I resolve issue:
I changed the Controller by adding request mapping:
#RestController
#RequestMapping("/auth")
class AuthenticationController
and then in security config:
?.antMatchers("/auth/**")?.permitAll()
It starts working.
I think this was the problem:
?.antMatchers(SIGN_UP_URL, AUTH_LOGIN_URL)?.permitAll()
Maybe if I will declare it one by one it would also work
Am using Auth0 for my authentication service. I have a web application communicating with a springboot API. Am trying to authenticate access to my API resource using Auth0 jwt token. Below is my implementation.
My Auth0 JS web application
var options = {
allowAutocomplete: true,
autoclose: true,
container: 'login-auth',
theme: {
logo: 'http://palermoinn.com/wp-content/uploads/2015/12/pullman_palermoinn.png',
primaryColor: '#009688',
foregroundColor: "#009688",
labeledSubmitButton: false,
},
auth: {
audience: 'https://xxx.auth0.com/userinfo',
responseType: 'token id_token',
params: {
state: 'into',
scope: 'openid email profile roles'
}
},
redirectUri: window.location.href,
languageDictionary: {
title: "Log In"
}
};
// console.log(constants.CLIENT_ID + " or " + constants.VERIFY_URL + " or " + constants.TYPE_GET);
var lock = new Auth0Lock(
'CLIENT_ID',
'xxx.auth0.com',
options
);
if (token == null && profile == null) {
lock.show();
} else {
var HEADER = {
token: token,
timeStamp: new Date().getTime(),
access: profile
}
console.log(JSON.stringify(HEADER));
/**
* This request would first request a token from the Auth0 Server
* The token is returned and that token is used to access API resource
*/
network.call(constants.STATS_URL + '1', constants.TYPE_GET, {}, token);
// window.location.href = "dashboard.html";
}
From my springboot Web security configuration I implemented the following
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST"));
configuration.setAllowCredentials(true);
configuration.addAllowedHeader("Authorization");
configuration.addAllowedHeader("cache-control");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors();
JwtWebSecurityConfigurer
.forRS256(AUTH_AUD, AUTH_ISSUER)
.configure(http)
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/v1/clients/stats/{userId}").authenticated();
}
My question now is Springboot web config I designed won't auth my request with the token I passed in the header. It keeps giving me an 401 unauthorized response. What am I doing wrong?
I can do a request uploading a file from Postman, but when I do the request from Angular, it is returned the WARN "Required MultipartFile parameter 'file' is not present"
It follows my resource in API.
#PostMapping
public ResponseEntity<Conteudo> publicaConteudo(#RequestParam("file") MultipartFile file) throws JsonParseException, JsonMappingException, IOException {
/* ANYTHING */
return ResponseEntity.ok(new Conteudo());
}
And my service in Angular. I'm using JWT, but I also trying to do the request using HttpClient.
upload(file: File, conteudo: Conteudo): Promise<any> {
let formData: FormData = new FormData();
formData.append('file', file, file.name);
/* USING JWT
return this.http.post(this.conteudoUrl, formData)
.toPromise()
.then(response => response.json());
*/
let h1 = new HttpHeaders().set('Authorization', 'Bearer ' + localStorage.getItem('token'));
const req = new HttpRequest('POST',this.conteudoUrl, formData, {
headers: h1
});
return this.httpClient.request(req).toPromise();
}
And how I can do in Postman
I tried many solutions that I found, as create a Bean MultipartResolver and others, but any solve my problem and what I think more interesting is that it works fine in Postman.
In your AbstractAnnotationConfigDispatcherServletInitializer class do you have this method?:
#Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter("UTF-8");
encodingFilter.setForceEncoding(true);
return new Filter[]{new DelegatingFilterProxy("springSecurityFilterChain"),
new OpenEntityManagerInViewFilter(),encodingFilter, new MultipartFilter()};
}
maybe you havenĀ“t registered the multipart filter. Hope this help.