where to handle authorization for a seperate backend and frontend? - authentication

I have a sveltekit client and a seperated backend (spring-boot) and I am unsure how to manage the session and where authorization should happen.
When you route to any protected page the backend authorize the client by looking for a cookie but this means that there is a split second, during the request, where the user is on a loading page before getting a response from the server.
I would like that this happens serverside so you don't get that flash of the page loading, which is possible if I do the authorization serverside in svelte but then I am making two trips to two different servers each time im rendering a protected page? Is that approach reasonable?

Related

Authorization between nuxtjs and the backend API

I have a Vuejs application created using Nuxtjs. I am also using Django as the backend server, and I made an API to interact with the backend server (Django) and front-end app (Vuejs/Nuxtjs). And any API related fetch are done in the AsyncData function of the page to render the data on the server-side using axios. Also, I am using json web token authentication, and the API generates a jwt token after successful login which is stored in the cookie. So on the backend, it will always check for the request's authorization header for the token. If the request is from a logged in user (authorized token) then return authenticated json data, or else return non authenticated data.
The problem:
When the user navigates to the app, I would like to check if the user is authenticated. If the user is authenticated, render the authenticated page. If not then display non authenticated page.
My thoughts:
When the fetch is done from the App on the AsyncData function, I would check whether there is any value for the cookie. If there is then send the token with the request's authorization header. But, since the page will be rendered on the server first, and not on the client side (where the cookie actually is) it will never find the token for the authorization.
How can I check if the user is already logged in or not so that I can get authenticated and non authenticated data respectively from the API?
Update
When I successfully log in (post authorized email and password), I get a json response back with the token, which I set in the cookie like this:
this.$cookie.set('my_auth_token', this.token, {expires: 15})
How can I retrieve client side cookie and into the nuxt server for server side rendering?
Cookies are exposed in the (Express) Nuxt server through middleware.
Specifically, they can be read from the req.headers.cookie property. You can see an example implementation of this in the Nuxt documentation.
Regarding your implementation: fetching the privileged data from your API using Node would seem to be the ideal way to delegate session handling to that single service (rather than both) and provide SSR for your users.
If you've chosen to instead implement your session handling on the Django service then you'll need to "forward" your cookies by passing them into your axios request headers.
I did something similar using Firebase authentication. There is an example project on Github as well as a blog entry outlining the important files and configuration used in the application.

Handle authentication in a Service Worker for a React App

I have a React app rendering client-side, in which I handle authentication the following way:
Upon loading, the app fires an AJAX request to the backend, basically asking whether the user's session is valid ;
It updates the app's state with the server's response ;
It renders the "/" route accordingly (the homepage if the session is invalid, a dashboard if it is valid).
(Maybe there are better solutions for handling this in front-end applications, I'm all ears if you have ideas)
This works pretty well, but introducing Service Workers into the mix and trying to turn the app into an offline-first progressive web app seems... complicated.
On the one hand, if I don't cache the "Am I logged in ?" request and the app is offline, the app will always render the homepage.
On the other hand, if I do cache the AJAX request, the users will eventually be shown an empty dashboard because their sessions will have expired and the server will be throwing 403s.
Is there a way to handle this effectively?
I solved my problem by taking a different approach: I now persist the state in localStorage.
This way, when the user arrives on the app, he is presented with stale data from his last visit. Meanwhile, a "Am I logged in?" request is fired in the background.
If it is succesful and returns true, the other AJAX requests get fired and fill the app with fresh data ;
If it is successful and returns false, the state is updated accordingly and the user redirected to the homepage ;
If the request is unsuccessful (i.e. the app is offline) the app keeps showing stale data from last session in the dashboard. We don't know if the user's session is still valid, but we can't retreive any data so it does not matter.
One way of doing it is adding a /verifyToken (assuming you are using some kind of token to validate the session) in your back-end api to check if the token is valid.
So you cache your session token. If the app is offline it shows the dashboard.
If the app is online, you fire a request to /verifyToken to check is the session is still valid. If it is then you continue to dashboard. If it isn't you redirect them back to homepage (or the sign in page).
Edit:
When your app is online, you can technically fire a request to any authorized route and check if the response was 403 (in case you can't modify the backend). If it is then you can send them back to sign in page.

Passport basic authentication only for API requests

I'm writing an express/node/angular application. When the client-side angular controllers need some data, they request it from the server using an endpoint that returns JSON.
This endpoint is behind some passport.authenticate('local') middleware, however this endpoint is exactly what we need for a public API.
Our API uses a passport.authenticate('basic') (basic http auth).
I'm trying to find a way to use the same URL for both, but I don't want users to my site who aren't logged in to see an http authentication window. I somehow need to tell "is this an API request, or an xhr request from the site"
For example, I want the following URL to work for a locally-authenticated user (would have been authenticated via a /login route) or for an API user:
app.get('/api/v1/tasks', passport.authenticate('basic'), tasks.list);
The only alternative I know of that works is splitting these into two different URLs, one for the site to use internally, and one for the public API. Maybe that's a better strategy for security/organization anyway?

How can I use HandleErrorAttribute to execute action retry logic?

I want to extend HandleErrorAttribute to globally handle a custom error type in my project. This what I was envisioning
Page user makes a request to pull a report from the site
The site (mvc project) needs to talk to a web api using an auth token
The api returns 401 with a body that contains an app code indicated it was because the token has expired
The site sees this and throws a TokenRefreshException
The site handles this globally by retrieving the refresh token from the session and using it to update the user's tokens, save it back to the session and then reattempt the action.
If it isn't able to refresh the token, it kills the session and redirects the user to the login page.
Is this possible and how do I implement this logic without creating an infinite loop (I'm not sure how to keep count)?

AngularJS: how to implement server-side or client-side authentication?

I want to authenticate an AngularJS app, it is running on top of Node.js and Express.js backend with Jade templates.
I thought of the following strategies:
1) server side authentication - store credentials in session variables and redirect the user to the AngularJS app, the problem: how to pass the credentials to AngularJS? (I can render those as Jade variables, but how can I read them with AngularJS?), also, how to handle session expiry ?
2) client side authentication - do the authentication with AJAX calls and get the credentials,
the problems: how to handle 'session' expiry and how to remember users so they won't have to login every time the app starts ?
any insights may help.
Setting up authentication for a Angular.js application isn't any different then setting it up for any other website. You post your username and password to the server and it will set a session/cookie if your credentials are correct. To get data (in your case crdentials) from the server you use the same techniques you always use with Javascript. Xhr, websockets, render values in a text field, ...