I currently have a multi-tenant SPA application that uses wild-card URL to differentiate tenants and databases. For example https://tenant1.appname.com might tie to database tenant1_db and https://tenant2.appname.com would tie to database tenant2_db.
Currently, the front end SPA is hosted on the same server as the backend .Net API. I use cookie authentication with HTTP Only cookies and because everything is hosted on the same site -- I don't have to deal with CORS or anything like that.
I'm exploring the possibility of authentication from Azure AD using OIDC. My understanding is that RFC specs state that OIDC callbacks MUST be made to an absolute URI. So, I wouldn't be able to callback to things like https://tenant1.appname.com.
I've read a few places that talk about using state to keep track of the tenant and redirect after OIDC login. I'm just curious how this works in regards to the cookies and tracking the tokens. If the callback URL is https://appname.com/callback and then the SPA client forwards to https://tenant1.appname.com, it seems like my cookies/tokens would now be invalid or un-accessible due to the different domain.
Can someone explain how this would work?
Interesting question and I thought I'd post some details based on experience. It may not be a complete answer though.
DESIGN THOUGHTS
I would start with how the simplest option would work, based on systems I have provided for investment banks:
All users from all tenants share the same database, APIs and application URLs
A tenant ID claim is included in tokens
APIs ensure that users from Tenant A can never see data from Tenant B
Customers who are not happy with this can pay extra to get their own dedicated servers and URLs - as you describe. If cookies are used for Tenant A they must not be usable for a Tenant B domain.
A key benefit of this is that you keep your code simple - everything is standard including the callback URL issue you mention. For different tenants you deploy the same code with different configuration settings.
AZURE AD
This has an option to use different OAuth URLs per tenant, and also to include Tenant IDs as claims in tokens. It may not be what you want though, because not all tenants are the same:
90% of tenants may be happy to share the same system - this will be all of the small customers
10% of clients may be willing to.pay extra - this will be the big customers
TECHNICAL SOLUTIONS
Hopefully thets across that there is not usually a magic technical solution to this problem. Sharing cookies across tenants or doing non standard OAuth things can lead to exploits.
ROUTING SOLUTIONS
Another option to consider is around dynamic user routing. You could possibly identify all users in the same system, then route them to the correct URLs dynamically.
Most systems don't support this but in case it gives you some ideas, have a look at this recent article from Curity - in particular the possibilities that reverse proxies provide.
Related
I'm a quite new JavaScript developer, coming from the Embedded Systems area, i.e., algorithms and programming basic concepts are not an issue for me, but some concepts of web development (front/back end) are still new to me, and many doubts often come up.
Going directly to my question, I'm currently developing a basic HTML + JS application where the user must login to get access to a "private" area; once logged-in, it is possible to perform many service requests and see other users requests, being more or less an "intranet" system.
I'm using Firebase Firestore as the database, and adopting two approaches to comunicate with the database:
-For user authentication management (log-in and sign-up processes), I'm taking advantage of the "front-end" JS modules provided by Firebase, using the login/password method with the e-mail link confirmation feature activated. Once an auth request is sent, the firebase app returns a token, and based on this token a session cookie is generated, granting access to the private area. This way, I don't need to manage most of the auth / account validation steps in my back-end part.
-For any other database operations (firestore read & write), I'm using the 'firebase-admin' SDK in conjunction with my back-end implementation, in a way that all the requests are validated with the session cookie before being actually performed. The back-end has access to a service account JSON "key", which gives it total read & write access to the whole database.
Finally, the questions are:
-Is it acceptable or conventional to use both approaches, front-end and back-end, to manage the firebase application?
-Once all the firestore data is being managed in the back-end side, and all the read/write/privilege rules are managed there, is it correct the correct approach to set the security rules to block everything, as follows? (considering that firebase-admin bypasses everything from the back-end side, not being affected)
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
Best regards, and please let me know if I was clear in my doubts :)
Combining front-end and back-end code when using Firestore (or other Firebase modules) is quite normal. Performing all data access through the Admin SDK (while not necessary) is a completely acceptable approach too. Setting the rules to not allow any direct access from client-side SDKs (or with ID tokens through the REST APIs) is indeed a logical step in this scenario.
On thing to realize is that your code is now responsible for ensuring all data is authorized, while in cases where you use client-side Firebase SDKs it is the security rules that perform access control.
What is the difference between using Google OAuth and signing in users at the frontend of the application, and signing in users at the backend side of the application?
Example: Signing in users and getting the ID and a auth object in React or letting Node/Express handle everything, the prosess, redirecting and store it in a database.
Is there any advantages for one or the other methods, which are most common and are there any "rules"?
What is the difference between using Google OAuth and signing in users
at the frontend of the application, and signing in users at the
backend side of the application?
So to clarify to everyone reading this, signing in users at the backend side of the application is another way of saying OAuth for servers and signing in users at the frontend of the application is OAuth for JavaScript browser applications such as React.
Signing in users via OAuth for servers and browsers results in a 'token' that a server/browser can use to make requests on behalf of the user. We are asking the user to provide us access to their information via an outside service provider such as an email address, identification of some sort and it will be inside that token as well as some possible permissions that allow us to take actions on behalf of that user.
Is there any advantages for one or the other methods, which are most
common and are there any "rules"?
Server-side OAuth is usually used when we have an app that needs to access user data when they are not logged in. So if you are attempting to build an application that needs to access the users email every ten minutes and possibly delete emails on the users' behalf, you would want to be able to access their email account every 10 minutes regardless of whether they are logged into our application. So for this use case we want to make use of Oauth for server.
Otherwise, if we are not trying to do anything on behalf of the user except sign them into our app, then we can just go with OAuth for browser.
Those two things are very different. Without knowing the specifics of what you're trying to accomplish, you should know as a general rule that front-end-only authentication and authorization leaves you extremely vulnerable.
If someone knows JavaScript well, or is using editing plugins, or any of a million different things, they can bypass much front-end authorization. Or they could just watch to see what calls your app makes to the back end, then simulate those calls from something like Postman, bypassing your web front end entirely.
If you're not securing your backend, you're not secure. Typically systems do both.
It is just a different ways of registering users to our website.
Signing in users at the frontend using OAuth can be very handy as it enables our users to not go through our boring forms in our website. Using OAuth is just one click away from registering users in our website. Beneficial to both the clients and developer.We are provided with the general information about clients by the provider(google,facebook) just clicking on one button.
Signing in users at the backend side is the traditional way of registering our clients. Here we force our client to fill the forms in our website(which may be painfull if it is a long form) and all the filled data is stored in our database.
So they are both different ways to register clients to our websites. Both are used very often. It depends on usecase and needs. Oauth can be used if you want to attract more clients by registering them just by one click.
I have a JavaScript SPA which consumes a backend REST API built with Django (Django Rest Framework). It's a small academic project which is likely to attract only a few hundred users on a regular basis. Our initial design assumed that users might wish to save data, but recent consultation with potential clients has made us question whether we need to incorporate this feature. So this would completely remove any need for POST requests to the backend API, leaving only GETs. These GETs (via axios) contain only path parameters, no query params, and return small JSON payloads, used to render SVG components in the application (this data is read-only, static data, already stored in the backend db).
The assumed need to cater for user uploads led us to also add user login/logout and account management features. We even started to look at integrating Auth0. But if we remove user upload entirely do we even need to secure our API endpoints in this way?
From what's given in the OP, answer is, No, you do not need authentication.
Irrespective of the HTTP verb used, just ask yourself, whatever functionality you are exposing through your REST apis, at least, do you care to find out who did what using your APIs? if not you don't need Authentication
Basically,
Do you want to restrict access to any APIs?
Do you want to tie an action to any persona?
Do you want to audit, (who did what when)?
If answer to all these 3 is no, you do not need authentication.
I'm creating a personal website and learning to implement a service worker that takes advantage of the push API in order to update myself and whatever others look at it that I have updated the website whenever I deploy. I figured out that the pushSubscription provides you with a capability URL and that I would need to store that somewhere in order to push a message to that url.
That's where my question comes in. Do I need a privacy policy if I'm going to be storing these capability URL in a database? If so, can I somehow only allow my website to store my capability URL instead of storing others?
your question would likely work better at law.stackexchange, thought let me say this: I work on privacy policies as a service (at iubenda) and one of the things you learn is that privacy policy requirements are usually triggered a lot sooner than most people think.
So in theory, in many legislations privacy policies are a requirement whenever your site is in any way commercial (this could be a personal site as well with a connection to your job in any way) and processes any personal data (this on the other hand could be the IP that gets automatically processed for connection purposes. Or, take what most people do on any site they make - Google Analytics - as an example: Google requests you to have a compliant privacy policy (check under 7).
Therefore let me give you this rule of thumb: having a privacy policy is rarely a bad idea from a requirement standpoint and it doesn't usually start with push notifications.
Also, here you might feel like reading up a bit about it when curiosity strikes:
California
UK
I've read about Firebase and it looks awesome for what I want to do.
I've read about authentication and how based on rules certain logged-in users are authorized to do different stuff. Al good.
However, I'm unsure about another type of security: how do I make sure that only my own site (using client-side javascript) can talk to my firebase-backend? I'm asking because afaik there's no way to prevent anyone from looking up my firebase endpoint from the client-side code (url pointing to my specific firebase backend) and start using that for god knows what.
This is especially worrisome in situations in which I want to open up writes to the anonymous user role. (e.g: some analytics perhaps)
Any help in clearing my mind on this much appreciated.
Update (May 2021): Thanks to the new feature called Firebase App Check, it is now actually possible to limit calls to your backend service to only those requests coming from iOS, Android and Web apps that are registered in your Firebase project.
You'll typically want to combine this with the user authentication based security that Kato describes below, so that you have another shield against abusive users that do use your app.
In my opinion, this isn't so much a question about Firebase's security as a general discussion of the internet architecture as it stands today. Since the web is an open platform, you can't prevent anyone from visiting a URL (including to your Firebase) any more than you can prevent someone from driving past your house in the real world. If you could, a visitor could still lie about the site of origin and there is no way to stop this either.
Secure your data with authentication. Use the Authorized Domains in Forge to prevent CSRF. Put security rules in place to prevent users from doing things they should not. Most data writes you would use a server to prevent can be accomplished with security rules alone.
This is actually one of the finer qualities of Firebase and API services in general. The client is completely isolated and thus easily replaced or extended. As long as you can prove you're allowed in, and follow the rules, where you call in from is unimportant.
Regarding anonymous access, if you could make them visit only from your site, that still won't stop malicious writes (I can open my JavaScript debugger and write as many times as I want while sitting on your site). Instead, place tight security rules on the format, content, and length of data writable by anonymous users, or save yourself some time and find an existing service to handle your analytics for you, like the ubiquitous Google Analytics.
You can, of course, use a server as an intermediary as you would with any data store. This is useful for some advanced kinds of logic that can't be enforced by security rules or trusted to an authenticated user (like advanced game mechanics). But even if you hide Firebase (or any database or service) behind a server to prevent access, the server will still have an API and still face all the same challenges of identifying clients' origins, as long as it's on the web.
Another alternative to anonymous access is to use custom login, which would allow a server to create its own Firebase access tokens (a user wouldn't necessarily have to authenticate for this; the signing of the tokens is completely up to you). This is advantageous because, if the anonymous user misbehaves, the access token can then be revoked (by storing a value in Firebase which is used by the security rules to enforce access).
UPDATE
Firebase now has anonymous authentication built into simple login, no need to use custom login for common use cases here.