I have implemented the OIDC in the backend express app using express-openid-connect
with the provider as ADFS and on successful authentication the express app saves the info into session and the backend APIs are protected.
What mechanism/library I can use to protect my react app using OIDC and can also hit the protected APIs at the same time?
React and Node are on different domain basically they are independent and deployed on different server.
WEBSITE MODEL
The express library is for scenarios where you are using a Node.js website that serves your React app's static content. Requests for your index.html file will trigger a redirect if there is no secure cookie yet.
After user sign in, an HTTP only encrypted cookie is written, and you can then call APIs via other routes in the website, as explained in this section of the docs. The web back end decrypts the cookie, then makes an access token available that can be forwarded from the website to APIs.
SPA STATIC CONTENT HOST
If you want to serve the SPA as just static content, similar to development web servers like webpack, the express solution is not the right architectural choice and you need a different option. You can't just throw these things together.
However, current security best practices mean you should only use secure cookies in the browser, so you need to solve this problem, and it is far from easy. The simplest option in the short term may be to serve static content via express.
FURTHER INFO
We have plenty of info on SPA architectures at Curity, starting with SPA Best Practices and a React Code Example, but it is very architectural, and SPA security is a tough topic. So you need to discuss requirements with your stakeholders, based on costs and benefits.
Related
Currently I have a backend express server that is used by our mobile apps (iOS and Android). I want to use Next.js for our web app version of the same application for the benefits that its been praised for (SSR, SEO, etc). I don't want to rewrite our current backend api onto the Next.js server. I just want to use Next.js as the frontend while it sends request to our current server (ideally I want to keep the backend code in a single server). I've done a bit of digging and it's entirely possible, however will this render the benefits of Next.js useless so I might as well just use CRA?
I want to have an application that is the most SEO friendly and efficient for users. Wondering which option is the best in this case.
I started a Django app and i created the whole authentication layer using Django-Allauth, it already has quite some features such as email confirmation, password reset and two factor authentication. Now i realized that, since my app will be heavily interactive and with a lot of real time features, i'm going to need a Vue SPA to use with Django, so i'm thinking of creating the Vue SPA on the same server and domain and have Django as a Rest API.
Here is my problem: since i already made the whole authentication part using Django templates and Django urls, if i separate the rest of the frontend from the backend, will i have to rewrite everything? Is it possible to have a Vue app and a Django backend app separated on the same domain where authentication is handled by Django templates and all the rest is a Vue app with vue routes and all the other interactions are handled by Django Rest Framework endpoints?
So maybe something like this:
urlpatterns = [
path('accounts/signup/', SignUpView.as_view(), name='signup'), #Django template
path('accounts/login/', LoginView.as_view(), name='login'), #Django template
...
]
And these are the only Django-handled urls where the page is rendered by Django views. Once the user is logged in, they will be redirected to the VueJS app.
My personal opinion, it's not worth it to keep a bunch of server side pages just for sign-up, login, ... Managing both server-side pages and front-end pages in long run is a headache. But if you like that way, here are my suggestions.
For authentication, use Django auth. No matter if it's a server side HTML page or it's an API end-point. Django auth is simple and secure. Don't roll your own auth, don't store tokens in localstorage or so.
Fully separate these 3:
Front-end URLs (i.e. routes stored in Vue)
Back-end page URLs (i.e. HTML pages severd by Django)
Back-end API end-points URLs (i.e. the ones user never see, only Vue uses them under the hood)
They can be on separated domains but it can be just by a path prefix as well. As you yourself suggested in a comment.
Now when user visits some page in BE, it will use server side rendering and every user click is a browser refresh. Until you hit a FE URLs, then your front proxy should redirect user to FE or you'll serve JS files directly from Django. After that every user click is handled inside Vue without a refresh. If user hits a URL prefix that's for BE, then FE needs to do something like document.location = "/server-side/some-page.
BTW few days ago I answered another question that was similar to this, maybe you find the answer or comments there useful.
So in order to log in from the SPA i need to send a csrf token, and in order to get the token i can create a Django view that returns a CSRF token to the user so that it can be used to login. Wouldn't it provide attackers a way to attack my server (stackoverflow.com/questions/43567052/…)
My suggestion is to turn CSRF protection off and instead make session cookie samesite=Lax (I think that's default in newer versions of Django). All major browsers support this and it prevents CSRF.
Otherwise you can read token from another API or from cookie like here
So on production i will use Nginx to have the Vue app and the Django backend app on the same server and domain, but on development how can i do that? If i run the two apps on different terminals, won't django consider the Vue app to be in a different server?
It can't understand what server it is. The only thing you should care is the domain of the cookie. It should be set on your BE domain. When running on local both FE and BE are running on domain "localhost" so there should be no issue.
I'm trying to setup a protected route (homepage in my case) with React. It works fine on the client. If not authenticated by server, it reroutes to login page. But technically, unauthenticated users can still check out the static content on the protected route (though of course the api calls to server are safe), just by either sifting through code, or by setting state in dev tools. I don't like this.
TLDR question: How can I make sure even the static content in protected routes are not seen by unauthenticated users?
I understand that authentication has to move from client to the server. But what is the proper way to do this with React/React Router?
My ideas:
-Serve an unauthenticated react app/index.html for just Login. When authenticated, serve another app for user content/pages.
-Maybe it's possible to do some component lazy loading from the server that also checks authentication on the request?
My context: create-react-app, express/node backend, using okta auth.
Thank you.
There are a couple of ways around this using a variety of methods.
First is to server-side render everything with a framework like Next.js. This framework is used by a ton of large enterprise companies because of the search engine friendliness of SSR pages. In your scenario though, it would solve your problem of showing content only when someone is authorized.
However, in most React.js apps, your data is coming from a data source such as MongoDB that is hidden behind your backend. The only code/information an unauthorized user would be able to see in your JS is the general layout of pages.
You can make hoc which will wrap your protected component and check if he is authenticated by a server. If not redirect him to homepage or somewhere else.
I am creating a desktop application that using Spotify's oauth api. I am using the implicit grant flow described here: https://developer.spotify.com/web-api/authorization-guide/#implicit_grant_flow
My idea is to have an "Authenticate" button, that you click and it opens your browser. You login/approve the connection with Spotify. Then it sends you to a redirect url.
I want to set this redirect url to 127.0.0.1:58212 or some port on the loopback device.
My question is, should I use https for this?
I am leaning towards yes. One because the access token needs to be secure, and I believe other users on the system could potentially read the message when it is sent, and two because in the time it took the user to log in, someone could have taken over the port.
So I want SSL for encryption of the message, and I want to ensure I am actually talking to my app.
How do I generate certificates in this situation? I think each instance of the application needs to have its own certificate, and I need to somehow inform the computer to trust that certificate during the lifetime of the application.
I could also generate the certificate during installation, and do some step during installation that makes the system trust that certificate.
Am I thinking about this the correct way, or am I going about this all wrong?
I am using electron and express in JavaScript to write my application.
Thanks for any advice.
The best way to securely use Oauth with installed applications such as desktop applications is to use the Oauth 2 flow for installed applications. But this option would have to be implemented by the service provider. Google provides for this option.
https://developers.google.com/api-client-library/python/auth/installed-app
Unfortunately, many services do not implement OAuth2.
To use Oauth 1.0 with installed applications, instead of returning to a callback_url, the service provider displays the auth code to the user which the user can then copy and paste to the desktop application. Check out Trello Ouath integration which allows for this.
The Web Api flow that you are trying to achieve will not work in the case of desktop apps. The redirect uri 127.0.0.1:port is your local uri. The service provider will need, at the very least, your public ip to redirect the flow back to your system.
AFAIK, for a Desktop or a native app it is much better to implement the Oauth authorization code flow. The implicit grant is intended to be used on a device browser and not on a Web View.
If your app uses a Web Service to connect, your Web Service needs a redirect URL that uses https. Luckily most hosting platforms like Heroku provide this to you for free (otherwise you need to buy an SSL certificate which might be a lot of work).
On the authorization code flow, a token doesn't need to see the client, it is all stored in the backend.
Most services allow you to test on localhost with http.
I wrote a tutorial that could give you some guidance on the flow.
I've created a Node.js WebApp and placed it on Azure. This hosts a Socket.io WebSocket and Website that I want to protect behind a form of authentication. My initial plan was to use ActiveDirectory, but I can't find any information on connecting a WebSocket using that kind of authentication.
Is there a way to use Active Directory or another similar and easy to setup authentication to protect both the website and the WebSocket?
I am planning on connecting to this server-side web app from a local machine using a socket.io-client.
I would look for an HTTP-based solution which allows you to interact with the active directory environment. You can then wire together this integration with your existing WebSocket solution.
This library looks promising: https://github.com/gheeres/node-activedirectory
It also looks like Azure provides a REST API for Active Directory: https://msdn.microsoft.com/en-us/library/azure/hh974476.aspx
I work at Stormpath, we also have an Active Directory feature that allows you to connect your Node.JS application to a data store that is synced with Active Directory. See Integrating Stormpath with Active Directory and LDAP
Hope this helps!
After much consideration on simplicity, I decided to drop the traditional Azure provided ActiveDirectory Authentication all together. (It blocks WebSocket traffic so that I could not do any manual authentication over the sockets)
I instead handle the website authentication myself using Passport and whichever authentication I choose Active Directory, Facebook, Google, Twitter, Github.
For the Socket.io authentication, I used socketio-auth to protect the connections with a custom layer of security and authentication.