JWT with Angular and SpringBoot - spring

I want to integrate a JWT authentication in my current Angular application which is connected to a spring boot backend.
I looked through quiet a lot of tutorials, but most of them did not fit, since they were connected to Auth0. I want to handle the usermanagement by myself.
I found this example:
Angular: https://medium.com/#juliapassynkova/angular-springboot-jwt-integration-p-1-800a337a4e0
Spring Boot: https://medium.com/#nydiarra/secure-a-spring-boot-rest-api-with-json-web-token-reference-to-angular-integration-e57a25806c50
Unfortunately, this Angular Frontend is Angular 4 and I'm using Angular 6 already. They use the 'angular2-jwt' which is not compatible with Angular 6. I have to use 'auth0/angular-jwt'.
My problem is, that after I use my login form, the browser opens again a login popup to login the backend. But even with the right credentials, it doesn't work. I'm guessing, that some credentials are missing in the request. In the app.module.ts are 2 old angular2-jwt code, which i don't know how to upgrade it to auth0/angular-jwt
export function authHttpServiceFactory(http: Http) {
return new AuthHttp(new AuthConfig({
headerPrefix: 'Bearer',
tokenName: TOKEN_NAME,
globalHeaders: [{'Content-Type': 'application/json'}],
noJwtError: false,
noTokenScheme: true,
tokenGetter: (() => localStorage.getItem(TOKEN_NAME))
}), http);
}
and
providers: [
{provide: AuthHttp, useFactory: authHttpServiceFactory, deps: [Http]},
]
Can someone help me with this issue. May be I'm wrong with my guessing and it could be something else?
A side note; I just changed my frontend but trying to connect to the backend from the example. If I'm using both front- and backend from the example, its working fine.

I have passed successful migration from angular2-jwt to auth0/angular-jwt several months ago. What you have to keep in mind while doing so is:
auth0/angular-jwt uses new angular HttpClient library, so if you want to use so, you have to migrate all your application to it (I suggest doing so anyway, new library is quite amazing)
new angular-jwt uses HttpInterceptors - this allows you to attach JWT directly to HttpClient filters chain. So you don't have to migrate your code above. You have to remove it completely and replace with interceptor initialization: (copy-paste from auth0/angular-jwt documentation):
import { JwtModule } from '#auth0/angular-jwt';
import { HttpClientModule } from '#angular/common/http';
export function tokenGetter() {
return localStorage.getItem('access_token');
}
#NgModule({
bootstrap: [AppComponent],
imports: [
// ...
HttpClientModule,
JwtModule.forRoot({
config: {
tokenGetter: tokenGetter,
whitelistedDomains: ['localhost:3001'],
blacklistedRoutes: ['localhost:3001/auth/']
}
})
]
})
export class AppModule {}
Remember to apply this code in your root module - then use your HttpClient without any changes and interceptors will apply JWT automatically. In case of problems - blame whitelistedDomains/blacklistedRoutes. These fields are very poorly implemented at the moment and are causing problems with regular expressions etc.
As migration is not straightforward, and took me a lot of time, feel free to ask about it. There's high probability, that I'll know the answers.

Related

Django drf-spectacular with FirebaseBackend auth

To give as much context as possible; I have two problems while using drf-spectacular to build my API documentation;
With my default configuration, I cannot even load the documentation's page because I have a custom auth backend (using firebase_admin 5.2.0), the swagger (or ReDoc) are part of my REST API, therefore, would have to pass a valid token to load the page allocated in the documentation's endpoint (which is not possible from a browser).
Second, and most importantly, I am not able to configure my custom firebase auth with drf-spectacular to implement a Swagger authentication method to execute against my API endpoints. I would be just fine having the possibility to add a token in the Swagger doc, do not need to have all Firebase auth credentials, URLs, and flow.
api/urls.py
router = routers.DefaultRouter()
urlpatterns = [
path('api/schema/', SpectacularAPIView.as_view(), name='schema'),
path('api/schema/swagger/', SpectacularSwaggerView.as_view(), name='swagger'),
path('api/schema/redoc/', SpectacularRedocView.as_view(), name='redoc'),
# _____________________FIREBASE AUTH ______________________
path('api-auth/', include('rest_framework.urls')),
path('', include(router.urls)),
settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'auth.backends.FirebaseBackend',
],
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
}
I have unsuccessfully tried adding many different configurations to my SPECTACULAR_SETTINGS.
Thanks in advance!!
By default spectacular uses 'SERVE_PERMISSIONS': ['rest_framework.permissions.AllowAny'], which should allow opening the swagger page even if not authenticated. Maybe FirebaseBackend bails hard which prevents you ever getting to AllowAny. Try this to take Firebase out of the equation for the schema views:
SPECTACULAR_SETTINGS = {
...
'SERVE_PERMISSIONS': ['rest_framework.permissions.AllowAny']
'SERVE_AUTHENTICATION': [],
}
You need to write an OpenApiAuthenticationExtension for Firebase as it is not part of the spectacular at the moment.

Caching the axios httpService in NestJS

Within our application we use the Axios HttpService to do some request to a third-party api.
Because the amount of data returned bij de api is so huge, we would like to cache the responses.
In the docs is wasn't able to find some examples of how to do this.
I'm currently doing this as follows:
#Module({
imports: [
HttpModule,
CacheModule.register({
ttl: 15,
store: redisStore,
host: 'localhost',
port: 6379,
})
]
})
export class AppModule {}
I register the CacheModule globally.
Then import it in the module where i need it.
In the service where i use the third-party api, i create an interceptor where i go and cache the reponses. Very crude and just for testing.
constructor(private readonly httpService: HttpService,
private readonly cache: CacheStore) {
httpService.axiosRef.interceptors.response.use((response) => {
cache.set(response.request.url, response.data);
return response;
}, error => Promise.reject(error));
}
First of all this doesn't run, because the CACHE_MANAGER can't be imported into the CacheModule, for some reason.
Second this is a more a Node.js way of creating such interceptors and not the NestJS way.
But is this a way to move forward or is there a more effecient way and if yes, what way is that?
The CacheModule is not the right tool here, as it means to cache ingoing requests (the requests your service receive, so it doesn't proceed them again and send back a cache result).
What you're trying to do is caching the outgoing requests (the one your service makes to 3rd-party services). For mysterious reasons, I couldn't find it documented in NestJS documentation either, but here's how you can go:
As you're using Axios, you can implement caching using the axios-cache-adapter npm package.
npm install --save axios-cache-adapter
Then you need to create an adapter (preferably in the constructor of your service, see notes below):
const cache = setupCache({
maxAge: 3600 * 1000, // 60 minutes
});
and provide this adapter as part of the AxiosRequestConfig alongside your request:
const config = {
adapter: this.cache.adapter,
};
this.httpService.get( url, config );
You should be good with some caching now!
IMPORTANT NOTES:
caching should be used, and will likely work, only on GET requests
use the setupCache function only once (in the constructor of your service for instance); if you create one cache object for every request, this cache will be empty everytime, defeating the purpose of it

How to properly connect Nuxt.js with a laravel backend?

I am starting a new project, Nuxt.js for the frontend and Laravel for the backend.
How can I connect the two?
I have installed a new Nuxt project using create-nuxt-app, and a new laravel project.
As far as I have searched, I figured I need some kind of environment variables.
In my nuxt project, I have added the dotenv package and placed a new .env file in the root of the nuxt project.
And added CORS to my laravel project, as I have been getting an error.
The variables inside are indeed accessible from the project, and im using them
like this:
APP_NAME=TestProjectName
API_URL=http://127.0.0.1:8000
And accessing it like this:
process.env.APP_NAME etc'
To make HTTP calls, I am using the official Axios module of nuxt.js, and to test it i used it in one of the components that came by default.
The backend:
Route::get('/', function () {
return "Hello from Laravel API";
});
and from inside the component:
console.log(process.env.API_URL)//Gives 127.0.0.1:8000
//But this gives undefined
this.$axios.$get(process.env.API_URL).then((response) => {
console.log(response);
});
}
What am I doing wrong here?
I have tried to describe my setup and problem as best as I can. If I overlooked something, please tell me and I will update my question. Thanks.
Taking for granted that visiting https://127.0.0.1:8000/ in your browser you get the expected response, lets see what might be wrong in the front end:
First you should make sure that axios module is initialized correctly. Your nuxt.config.js file should include the following
//inclusion of module
modules: [
'#nuxtjs/axios',
<other modules>,
],
//configuration of module
axios: {
baseURL: process.env.API_URL,
},
Keep in mind that depending on the component's lifecycle, your axios request may be occurring in the client side (after server side rendering), where the address 127.0.0.1 might be invalid. I would suggest that you avoid using 127.0.0.1 or localhost when defining api_uris, and prefer using your local network ip for local testing.
After configuring the axios module as above, you can make requests in your components using just relative api uris:
this.$axios.$get('/').then(response => {
console.log(response)
}).catch(err => {
console.error(err)
})
While testing if this works it is very helpful to open your browser's dev tools > network tab and check the state of the request. If you still don't get the response, the odds are that you'll have more info either from the catch section, or the request status from the dev tools.
Keep us updated!
Nuxt has a routing file stucture to make it easy to set up server side rendering but also to help with maintainability too. This can cause Laravel and Nuxt to fight over the routing, you will need to configure this to get it working correctly.
I'd suggest you use Laravel-Nuxt as a lot of these small problems are solved for you.
https://github.com/cretueusebiu/laravel-nuxt

SpringBoot - Angular 5 - CSRF

Iam lost now and need some help.
I have a
SpringBoot Server with SpringSecurtiy 4.3.
Angular 5 App
And want to enable CSRF protection since it should be enabled on both by default (says the docs)
:Its NOT!
On SpringBoot I need to add these security configs:
http
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
On Angular I need to add these Modules:
imports: [
...,
HttpClientModule,
HttpClientXsrfModule, //(!)
...
Bottom line the server send the XRSF-TOKEN in each response.
-But a diffrent on each one. Is that correct? I expected to be the same on a client session.
-Main problem here is that Angular5 still didnt use the XRSF-TOKEN in its post calls (e.g.). It dont set a X-XSRF-TOKEN in its requests.
What am I doing wrong or missing?
I had this same problem and I think it is a regression due to version 5 of angular.
Until this is fixed you can add your own 'X-XSRF-TOKEN' header as I did.
constructor(private http: HttpClient, private tokenExtractor: HttpXsrfTokenExtractor) {
}
then extract manually a token
const token = this.tokenExtractor.getToken() as string;
and add it to the header
this.http.post<any>(url, body, {headers: new HttpHeaders().set('X-XSRF-TOKEN', token)})
Houssem

Sails.js 0.10 and passport

I was fiddling with sails.js and passport. Seems they are mend to be used together.
I have made the user models available in de db. And I am able to use the authentication by bcryptjs. This works, but dearly want to like to automatically authenticate every call, and mostly socket.io blueprint calls.
Still, I am searching for an elegant method to enable the sails.js way of integrating passport.
There are many examples, but seem a bit out-dated, not sure.
Important is the sockets. They need to be authenticated.
For e.g. every io.socket CRUD method, would be nice.
Kind regards
I found a link (http://www.bearfruit.org/2014/07/21/tutorial-easy-authentication-for-sails-js-apps/) that's pointing me in the right direction, but still not clear how this is reflected in for instance controllers
What I am trying to manage, is to have the custom api calls authenticated before they are called (configured in routes.js or by means of blueprints).
e.g:
OrderController:
module.exports = {
placeOrder: function (req, res) {
if (true === req.isSocket) {
// Pseudo code:
if (passport.authenticated(['user','admin'])) {
Order.save();
}
// end pseudo code
}
}
}
How should/is the above method secured, and I am I able to use for instance user-roles here?
I know two good solution for you question:
sails-auth
sails-generate-auth
Both implements passport, I recommend the first one, because it creates a layer to handle all authentication difficulties in model and services

Resources