Cannot includ/send jwt token using auth0/angular-jwt - spring

I use "https://github.com/auth0/angular2-jwt" to send JWT token to my server, I can see the token when I debug http request (angular) but at the server (java) the token is not found
this is my config jwt
JwtModule.forRoot({
config: {
headerName: 'API_TOKEN',
tokenGetter: function tokenGetter() {
return localStorage.getItem('API_TOKEN');
},
whitelistedDomains: ['localhost:8092'],
// blacklistedRoutes: ['https://localhost:8092/login'],
authScheme: ''
}
}),
I added a JwtHttpInterceptor for debug my request :
#Injectable()
export class JwtHttpInterceptor implements HttpInterceptor {
constructor() {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req);
}
}
and this is a screenshot : JWT token in header request
but server could not find this token.
When I try to add token with a chrome pluging, It work and server can find my token : token added with chrome pluging
Can you help me please?

I found the solution if it will help another person, in fact it comes from the backend, I reversed the spring security filters and my request "OPTIONS" should go through the filter CORS first
httpSecurity
.addFilter(jwtAuthenticationFilter)
.addFilterBefore(corsInputFilter, UsernamePasswordAuthenticationFilter.class) // OPTIONS REQUEST SHOULD COME HERE IN THE FIRST AND RETURN THE RESPONSE WITHOUT CONTINUE OTHERS FILTERS
.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

Related

Axios JWT doesn't send

I have a project divided in two layers. The back-end is developed in spring boot, secured by Sprint security and JWT, and the front-end is developed in Vue.js, using Axios library for communication between layers.
I receive the "Bearer token" authentication properly, and all the authentication process is done correctly. The issue appears when I try to send a request with a token header to access content but the token doesn't send, and the Spring boot returns null without the content.
Here is the code
getOffers: function () {
if (localStorage.getItem("userSession")) {
this.aux = JSON.parse(localStorage.getItem("userSession"));
this.token = this.aux.token;
this.tokenHeader = "Bearer "+this.token;
alert(this.tokenHeader)
};
console.log(`Bearer ${this.token}`)
axios.
get('http://localhost:8080/api/v1/offer', {'Authorization' : `Bearer ${this.token}`})
.then(response => {
console.log(response);
this.offers = response.data
}).catch(e => console.log(e))
}
P.S: When I make a request in Postman, it works fine and returns the desired object. Here is a postman example:
postman
Correct way to pass header is :
axios.get(uri, { headers: { "header1": "value1", "header2": "value2" } })
In your case try this:
axios.get('http://localhost:8080/api/v1/offer', { headers:{Authorization : `Bearer ${this.token}`} })
Also, check in console if this gives correct Bearer token:
console.log(`Bearer ${this.token}`)
Register the Bearer Token as a common header with Axios so that all outgoing HTTP requests automatically have it attached.
window.axios = require('axios')
let bearer = window.localStorage['auth_token']
if (bearer) {`enter code here`
window.axios.defaults.headers.common['Authorization'] = 'Bearer ' + bearer
}
And no need to send bearer token on every request.

How to set authorization header in vue.js

I'm making an axios post call with the JWT token generated after successful login. For all the requests I need to attach JWT token in header and in the back-end which is developed on spring -boot I have logic to get the token from header and validate it.
From the browser, first the OPTIONS request goes to back-end where it gives me 403 error and in the back-end If I sysout headers, I can't find the header name X-XSRF-TOKEN
axios.post("http://localhost:8004/api/v1/auth", { "username": "test", "password" : "test"})
.then((response) => {
let token = response.data.token;
axios.defaults.headers.common["X-XSRF-TOKEN"] = token;
axios.post("http://localhost:8004/api/v1/getdata", {"action" : "dashboard"})
.then((response) => {
console.log(response.data);
}, (error) => {
console.log(error);
})
}, (error) => {
console.log(error);
})
Spring boot part
#Controller
#CrossOrigin(origins = "*", allowedHeaders = "*")
#RequestMapping(path = "/api/v1")
public class ApplicationController {
#PostMapping(path = "/getdata")
#ResponseBody
public SessionData getData(#RequestBody ProfileRequest profileRequest) {
try {
return profileService.getData(profileRequest);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
Setting Authorization Header is not something to do with vue, but it
is something to do with axios.
axios.post("http://localhost:8004/api/v1/getdata", {"action" : "dashboard"}, {
headers: {
Authorization: 'Bearer ' + token,
}
})
When you get the auth token you can configure the axios instance with:
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`
common means applying the header to every subsequent request, while you can also use other HTTP verb names if you want to apply a header to only one request type:
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
You will find more info in https://github.com/axios/axios#config-defaults
...
axios.post('http://localhost:8004/api/v1/auth',
{ "username": "test", "password" : "test"}, {headers: { X-XSRF-TOKEN: `${token}`}})
...
the issue might not be axios but the cors policy set by spring security.
If you are using spring security check out this answer
I had the same issue, that answer helped solve my problem.

Adding the application autehntication to Swagger UI

I have Spring boot app where I integrate JWT authentication.
In order to authenticate, user need to send a POST request to /login with username and password, then he gets a JSON response with {"token": "BEARER SOME_TOKEN" }.
In my swagger UI, when I click "Try it out" and execute a request, the request is being sent without any token.
Question - Is there any way to query a login request and add authorization token to the Swagger UI requests?
In this case we can intercept the tokens and add them to all the requests by using these two interceptors in the index.html when defining SwaggerUIBundle:
const ui = SwaggerUIBundle({
...
responseInterceptor:
function (response) {
if (response.obj.access_token) {
console.log(response.obj.access_token)
const token = response.obj.access_token;
localStorage.setItem("token", token)
}
return response;
},
requestInterceptor:
function (request) {
request.headers.Authorization = "Bearer " + localStorage.getItem("token");
return request;
}
}
The responseInterceptor captures the response and if it contains the field "token" it saves it in local storage.
The requestInterceptor adds the Authorization header on each call you make from swagger-ui using the value from local storage.
This fix is for using v3 of swagger-ui:
<script src="https://unpkg.com/swagger-ui-dist#3.12.1/swagger-ui-standalone-preset.js"></script>
<script src="https://unpkg.com/swagger-ui-dist#3.12.1/swagger-ui-bundle.js"></script>

Angular 2 JWT doesnot sends Authorization Bearer Token during page reload

I am using Tymon JWT to setup the JWT Token from my Laravel application.
I have setup similar to the quick start guide and when i test using the postman, the backend successfully returns the access token.
On frontend i am using Angular2-jwt to send the request from frontend also replacing the Http module with AuthHttp from this package which is a wrapper for the Http module.
Configured the AuthModule similar to the guide:
import { NgModule } from '#angular/core';
import { Http, RequestOptions } from '#angular/http';
import { AuthHttp, AuthConfig } from 'angular2-jwt';
export function authHttpServiceFactory(http: Http, options: RequestOptions) {
return new AuthHttp(new AuthConfig({
tokenName: 'token',
noJwtError : true, //<== Using this explicitely because i am using AuthHttp on every routes.
tokenGetter: (() => sessionStorage.getItem('token')),
globalHeaders: [{'Content-Type':'application/json'}],
}), http, options);
}
#NgModule({
providers: [
{
provide: AuthHttp,
useFactory: authHttpServiceFactory,
deps: [Http, RequestOptions]
}
]
})
export class AuthModule {}
During the first load of the login page also if i have valid auth token there is no any Authorization: Bearer <token> added in the Get request. Sometimes it gets added in the Header and on some request there is no Authorization in the header.
Image1:
No Authorization added in the header even though there is valid token
Image2:
Authorization Header Added before requesting the token to the backend.
I am not sure about the addition of the header when does it adds and when does it removes from the header.
Have anyone else received this kind of issue?
If further details is required will add them.

Enable authenticator manually

Currently my client authenticates request only on case of 401 response:
this.client.authenticator(new okhttp3.Authenticator() {
public Request authenticate(Route route, Response response) throws IOException {
String credentials = authenticator.getCredentials();
if (credentials.equals(response.request().header("Authorization"))) {
throw new TraversonException(401, "Unauthorized", response.request().url().toString());
} else {
defaultHeader("Authorization", credentials);
Request.Builder newRequest = response.request().newBuilder()
.headers(Headers.of(defaultHeaders));
return newRequest.build();
}
});
But I'd like to change this behavior and be able to call it either manually or auto per first call? Is it possible somehow?
If the authentication is predictably required and not related to a proxy, then the solution is to implement an Interceptor instead of Authenticator.
OkHttpClient.Builder clientBuilder = ...;
clientBuilder.networkInterceptors().add(0, myInterceptor);
client = clientBuilder.build();
Example Interceptor https://github.com/yschimke/oksocial/blob/48e0ca53b85e608443eab614829cb0361c79aa47/src/main/java/com/baulsupp/oksocial/uber/UberAuthInterceptor.java
n.b. There is discussion around possible support for this usecase in https://github.com/square/okhttp/pull/2458. One issue with current Authenticator API is that it assumes a Response from the failed (401) request.

Resources